summary refs log tree commit diff
diff options
context:
space:
mode:
authorC. McEnroe <june@causal.agency>2020-08-15 14:46:11 -0400
committerC. McEnroe <june@causal.agency>2020-08-15 14:54:33 -0400
commit34c39437f2bc2045a7017230dca7179faee5b4e6 (patch)
treeb3d2f61035e3a153ea77308cf0563ec0a21b6e9c
parentImplement non-blocking line-buffered reading (diff)
downloadcatsit-34c39437f2bc2045a7017230dca7179faee5b4e6.tar.gz
catsit-34c39437f2bc2045a7017230dca7179faee5b4e6.zip
Read service pipes
Changed line reading functions to return const char * because modifying
the strings by adding '\0' into them screws up the following call.
-rw-r--r--daemon.c11
-rw-r--r--daemon.h6
-rw-r--r--service.c32
3 files changed, 43 insertions, 6 deletions
diff --git a/daemon.c b/daemon.c
index 42ea78f..c759f20 100644
--- a/daemon.c
+++ b/daemon.c
@@ -286,13 +286,20 @@ int main(int argc, char *argv[]) {
 		}
 
 		if (nfds > 0 && fds[0].revents) {
-			for (char *line; NULL != (line = lineRead(&fifoLine, fifo));) {
+			const char *line;
+			while (NULL != (line = lineRead(&fifoLine, fifo))) {
 				syslog(LOG_INFO, "control: %s", line);
 			}
 			if (errno != EAGAIN) syslog(LOG_ERR, "read: %m");
 		}
 
-		// TODO: Handle pipes.
+		if (nfds > 0) {
+			for (size_t i = 0; i < services.len; ++i) {
+				if (fds[1 + 2 * i].revents || fds[2 + 2 * i].revents) {
+					serviceRead(&services.ptr[i]);
+				}
+			}
+		}
 
 		if (timespecisset(&deadline)) {
 			clock_gettime(CLOCK_MONOTONIC, &now);
diff --git a/daemon.h b/daemon.h
index 7290420..17b1c7f 100644
--- a/daemon.h
+++ b/daemon.h
@@ -17,6 +17,7 @@
 #include <errno.h>
 #include <grp.h>
 #include <pwd.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
@@ -55,13 +56,13 @@ struct Line {
 	char buf[512];
 };
 
-static inline char *lineFlush(struct Line *line) {
+static inline const 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) {
+static inline const char *lineRead(struct Line *line, int fd) {
 	char *nul = memchr(line->buf, '\0', line->len);
 	if (nul) {
 		nul++;
@@ -131,6 +132,7 @@ void serviceStart(struct Service *service);
 void serviceStop(struct Service *service);
 void serviceRestart(struct Service *service);
 void serviceSignal(struct Service *service, int signal);
+void serviceRead(struct Service *service);
 void serviceReap(pid_t pid, int status);
 
 extern char configError[];
diff --git a/service.c b/service.c
index 12f465f..718397d 100644
--- a/service.c
+++ b/service.c
@@ -16,10 +16,12 @@
 
 #include <assert.h>
 #include <err.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <limits.h>
 #include <paths.h>
 #include <signal.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -201,6 +203,33 @@ void serviceRestart(struct Service *service) {
 	}
 }
 
+static void serviceLog(struct Service *service, int pri, const char *log) {
+	syslog(
+		pri, "%s[%ju]: %s",
+		service->name, (intmax_t)service->pid, log
+	);
+}
+
+void serviceRead(struct Service *service) {
+	const char *out;
+	while (NULL != (out = lineRead(&service->outLine, service->outPipe[0]))) {
+		serviceLog(service, LOG_INFO, out);
+	}
+	if (errno != EAGAIN) syslog(LOG_ERR, "read: %m");
+	const char *err;
+	while (NULL != (err = lineRead(&service->errLine, service->errPipe[0]))) {
+		serviceLog(service, LOG_NOTICE, err);
+	}
+	if (errno != EAGAIN) syslog(LOG_ERR, "read: %m");
+}
+
+static void serviceFlush(struct Service *service) {
+	const char *out = lineFlush(&service->outLine);
+	const char *err = lineFlush(&service->errLine);
+	if (out) serviceLog(service, LOG_INFO, out);
+	if (err) serviceLog(service, LOG_NOTICE, err);
+}
+
 void serviceReap(pid_t pid, int status) {
 	struct Service *service = NULL;
 	for (size_t i = 0; i < services.len; ++i) {
@@ -213,8 +242,7 @@ void serviceReap(pid_t pid, int status) {
 		syslog(LOG_WARNING, "reaping unknown child %jd", (intmax_t)pid);
 		return;
 	}
-
-	// TODO: Flush line buffers.
+	serviceFlush(service);
 
 	service->state = Stop;
 	if (WIFEXITED(status)) {