diff options
Diffstat (limited to 'daemon.c')
-rw-r--r-- | daemon.c | 107 |
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); |