Implement non-blocking line-buffered reading
This commit is contained in:
parent
3e2568aeb0
commit
f556af9ad5
18
daemon.c
18
daemon.c
@ -209,8 +209,11 @@ int main(int argc, char *argv[]) {
|
||||
warn("%s", fifoPath);
|
||||
}
|
||||
|
||||
int fifo = open(fifoPath, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
|
||||
// XXX: Make sure there is always at least one writer open, otherwise we
|
||||
// get EOF continually.
|
||||
int fifo = open(fifoPath, O_RDWR | O_NONBLOCK | O_CLOEXEC);
|
||||
if (fifo < 0) err(EX_CANTCREAT, "%s", fifoPath);
|
||||
struct Line fifoLine = {0};
|
||||
|
||||
openlog(getprogname(), LOG_NDELAY | LOG_PID | LOG_PERROR, LOG_DAEMON);
|
||||
|
||||
@ -277,8 +280,19 @@ int main(int argc, char *argv[]) {
|
||||
(timespecisset(&deadline) ? &timeout : NULL),
|
||||
&mask
|
||||
);
|
||||
if (nfds < 0 && errno != EINTR) {
|
||||
syslog(LOG_ERR, "ppoll: %m");
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: Handle FIFO and pipes.
|
||||
if (nfds > 0 && fds[0].revents) {
|
||||
for (char *line; NULL != (line = lineRead(&fifoLine, fifo));) {
|
||||
syslog(LOG_INFO, "control: %s", line);
|
||||
}
|
||||
if (errno != EAGAIN) syslog(LOG_ERR, "read: %m");
|
||||
}
|
||||
|
||||
// TODO: Handle pipes.
|
||||
|
||||
if (timespecisset(&deadline)) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
|
43
daemon.h
43
daemon.h
@ -14,6 +14,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <stdint.h>
|
||||
@ -49,6 +50,42 @@ static inline int prependAdd(const char *command) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct Line {
|
||||
size_t len;
|
||||
char buf[512];
|
||||
};
|
||||
|
||||
static inline char *lineFlush(struct Line *line) {
|
||||
if (!line->len) return NULL;
|
||||
line->buf[line->len++] = '\0';
|
||||
return line->buf;
|
||||
}
|
||||
|
||||
static inline char *lineRead(struct Line *line, int fd) {
|
||||
char *nul = memchr(line->buf, '\0', line->len);
|
||||
if (nul) {
|
||||
nul++;
|
||||
line->len -= nul - line->buf;
|
||||
memmove(line->buf, nul, line->len);
|
||||
}
|
||||
|
||||
size_t cap = sizeof(line->buf) - line->len - 1;
|
||||
if (!cap) return lineFlush(line);
|
||||
|
||||
ssize_t len = read(fd, &line->buf[line->len], cap);
|
||||
if (len < 0 && errno != EAGAIN) return NULL;
|
||||
if (len > 0) line->len += len;
|
||||
|
||||
char *nl = memchr(line->buf, '\n', line->len);
|
||||
if (nl) {
|
||||
*nl = '\0';
|
||||
return line->buf;
|
||||
} else {
|
||||
errno = EAGAIN;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
enum {
|
||||
SHELL,
|
||||
PATH,
|
||||
@ -70,12 +107,6 @@ enum State {
|
||||
Restart,
|
||||
};
|
||||
|
||||
enum { LineCap = 512 };
|
||||
struct Line {
|
||||
size_t len;
|
||||
char buf[LineCap];
|
||||
};
|
||||
|
||||
struct Service {
|
||||
char *name;
|
||||
char *command;
|
||||
|
Loading…
Reference in New Issue
Block a user