about summary refs log tree commit diff
path: root/daemon.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemon.c')
-rw-r--r--daemon.c107
1 files changed, 67 insertions, 40 deletions
diff --git a/daemon.c b/daemon.c
index f36e277..736fd08 100644
--- a/daemon.c
+++ b/daemon.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2020  C. McEnroe <june@causal.agency>
+/* Copyright (C) 2020  June McEnroe <june@causal.agency>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU Affero General Public License as published by
@@ -49,6 +49,34 @@ static void signalHandler(int signal) {
 	signals[signal] = 1;
 }
 
+static ssize_t getlinecont(char **line, size_t *lcap, FILE *file) {
+	size_t cap = 0;
+	char *buf = NULL;
+	ssize_t llen = getline(line, lcap, file);
+	while (llen > 1 && (*line)[llen - 1] == '\n' && (*line)[llen - 2] == '\\') {
+		llen -= 2;
+		ssize_t len = getline(&buf, &cap, file);
+		if (len < 0) {
+			llen = -1;
+			break;
+		}
+		size_t req = llen + len + 1;
+		if (req > *lcap) {
+			char *ptr = realloc(*line, req);
+			if (!ptr) {
+				llen = -1;
+				break;
+			}
+			*line = ptr;
+			*lcap = req;
+		}
+		strlcpy(*line + llen, buf, *lcap - llen);
+		llen += len;
+	}
+	free(buf);
+	return llen;
+}
+
 static int parseConfig(const char *path) {
 	int ret = -1;
 	size_t cap = 0;
@@ -63,14 +91,15 @@ static int parseConfig(const char *path) {
 	prependClear();
 
 	int line = 1;
-	for (ssize_t len; 0 <= (len = getline(&buf, &cap, file)); ++line) {
+	for (ssize_t len; 0 <= (len = getlinecont(&buf, &cap, file)); ++line) {
 		if (buf[len - 1] == '\n') buf[len - 1] = '\0';
 
 		char *ptr = &buf[strspn(buf, WS)];
 		if (!ptr[0] || ptr[0] == '#') {
 			continue;
 		} else if (ptr[0] == '%') {
-			int error = prependAdd(&ptr[1]);
+			ptr++;
+			int error = prependAdd(&ptr[strspn(ptr, WS)]);
 			if (error) {
 				syslog(LOG_WARNING, "cannot add prepend command: %m");
 				goto err;
@@ -84,7 +113,7 @@ static int parseConfig(const char *path) {
 				);
 				goto err;
 			}
-			int error = serviceAdd(name, ptr);
+			int error = serviceAdd(name, &ptr[strspn(ptr, WS)]);
 			if (error) {
 				syslog(LOG_WARNING, "cannot add service: %m");
 				goto err;
@@ -215,30 +244,9 @@ int main(int argc, char *argv[]) {
 		}
 	}
 
-#ifdef __OpenBSD__
-	struct {
-		const char *path;
-		const char *mode;
-	} paths[] = {
-		{ fifoPath, "crw" },
-		{ configPath, "r" },
-		{ "/", "r" },
-		{ "/dev/null", "rw" },
-		{ serviceDir, "r" },
-		{ _PATH_BSHELL, "x" },
-		{ pidPath, "cw" },
-		{ NULL, NULL },
-	};
-	for (size_t i = 0; paths[i].path; ++i) {
-		error = unveil(paths[i].path, paths[i].mode);
-		if (error) err(EX_CANTCREAT, "%s", paths[i].path);
-	}
-	error = pledge(
-		"stdio cpath dpath rpath wpath flock getpw proc exec id", NULL
-	);
-	if (error) err(EX_OSERR, "pledge");
-#endif
-	
+	error = access(configPath, R_OK);
+	if (error) err(EX_NOINPUT, "%s", configPath);
+
 	error = access(serviceDir, X_OK);
 	if (error) err(EX_NOINPUT, "%s", serviceDir);
 
@@ -292,9 +300,6 @@ int main(int argc, char *argv[]) {
 	int writer = open(fifoPath, O_WRONLY | O_NONBLOCK | O_CLOEXEC);
 	if (writer < 0) err(EX_CANTCREAT, "%s", fifoPath);
 
-	error = parseConfig(configPath);
-	if (error) return EX_DATAERR;
-
 	if (daemonize) {
 		error = daemon(0, 0);
 		if (error) {
@@ -302,27 +307,47 @@ int main(int argc, char *argv[]) {
 			return EX_OSERR;
 		}
 	}
-	if (pidPath) {
-		int len = dprintf(pidFile, "%ju", (uintmax_t)getpid());
-		if (len < 0) syslog(LOG_WARNING, "%s: %m", pidPath);
-	}
 
 #ifdef __OpenBSD__
-	error = pledge("stdio cpath rpath proc exec id", NULL);
+	error = 0
+		|| unveil(fifoPath, "c")
+		|| unveil(configPath, "r")
+		|| unveil(serviceDir, "r")
+		|| unveil(_PATH_BSHELL, "x");
+	if (error) err(EX_OSERR, "unveil");
+	if (pidPath) {
+		error = unveil(pidPath, "c");
+		if (error) err(EX_OSERR, "unveil");
+	}
+	error = pledge("stdio rpath cpath proc exec id", NULL);
 	if (error) err(EX_OSERR, "pledge");
 #endif
 
+	if (pidPath) {
+		int len = dprintf(pidFile, "%ju", (uintmax_t)getpid());
+		if (len < 0) syslog(LOG_WARNING, "%s: %m", pidPath);
+	}
+
 	signal(SIGHUP, signalHandler);
 	signal(SIGINT, signalHandler);
 	signal(SIGTERM, signalHandler);
 	signal(SIGCHLD, signalHandler);
 	signal(SIGINFO, signalHandler);
 
+	parseConfig(configPath);
 	for (size_t i = 0; i < services.len; ++i) {
 		serviceStart(&services.ptr[i]);
 	}
 	setTitle();
 
+	struct pollfd *fds = calloc(1 + 2 * services.len, sizeof(*fds));
+	if (!fds) {
+		syslog(LOG_ERR, "calloc: %m");
+		goto shutdown;
+	}
+	fds[0].fd = fifo;
+	fds[0].events = POLLIN;
+
 	sigset_t mask;
 	sigemptyset(&mask);
 	for (;;) {
@@ -342,6 +367,11 @@ int main(int argc, char *argv[]) {
 		}
 		if (signals[SIGHUP]) {
 			parseConfig(configPath);
+			fds = reallocarray(fds, 1 + 2 * services.len, sizeof(*fds));
+			if (!fds) {
+				syslog(LOG_ERR, "reallocarray: %m");
+				goto shutdown;
+			}
 			setTitle();
 			signals[SIGHUP] = 0;
 		}
@@ -351,10 +381,6 @@ int main(int argc, char *argv[]) {
 			signals[SIGINFO] = 0;
 		}
 
-		struct pollfd fds[1 + 2 * services.len];
-		fds[0].fd = fifo;
-		fds[0].events = POLLIN;
-
 		struct timespec deadline = {0};
 		for (size_t i = 0; i < services.len; ++i) {
 			struct Service *service = &services.ptr[i];
@@ -425,6 +451,7 @@ int main(int argc, char *argv[]) {
 		}
 	}
 
+shutdown:
 	close(fifo);
 	unlink(fifoPath);