diff options
-rw-r--r-- | daemon.c | 2 | ||||
-rw-r--r-- | daemon.h | 5 | ||||
-rw-r--r-- | service.c | 52 | ||||
-rw-r--r-- | spawnd.8 | 5 |
4 files changed, 60 insertions, 4 deletions
diff --git a/daemon.c b/daemon.c index a2ce4dc..d0a6579 100644 --- a/daemon.c +++ b/daemon.c @@ -18,6 +18,7 @@ #include <errno.h> #include <fcntl.h> #include <grp.h> +#include <poll.h> #include <pwd.h> #include <stdarg.h> #include <stdbool.h> @@ -122,7 +123,6 @@ int main(int argc, char *argv[]) { setprogname(argv[0]); bool daemonize = true; - setAdd(&stopExits, 127); setAdd(&stopExits, EX_USAGE); setAdd(&stopExits, EX_DATAERR); setAdd(&stopExits, EX_NOINPUT); diff --git a/daemon.h b/daemon.h index a62f78f..09cda47 100644 --- a/daemon.h +++ b/daemon.h @@ -95,10 +95,13 @@ extern struct Services { } services; int serviceAdd(const char *name, const char *command); +void serviceStart(struct Service *service); extern char configError[]; int configParse(const char *path); +extern int restartInterval; + struct Set256 { uint32_t bits[8]; }; @@ -112,5 +115,5 @@ static inline uint32_t setTest(const struct Set256 *set, byte x) { return set->bits[x / 32] & (1 << (uint32_t)(x & 31)); } -extern int restartInterval; +enum { StopExit = 127 }; extern struct Set256 stopExits; diff --git a/service.c b/service.c index f5038da..3472151 100644 --- a/service.c +++ b/service.c @@ -14,11 +14,15 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <assert.h> +#include <err.h> #include <fcntl.h> +#include <limits.h> #include <paths.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <syslog.h> #include <unistd.h> #include "daemon.h" @@ -100,3 +104,51 @@ err: serviceFree(service); return -1; } + +void serviceStart(struct Service *service) { + if (service->state == Start) return; + service->intent = Start; + // TODO: Reset restart interval. + + service->pid = fork(); + if (service->pid < 0) { + syslog(LOG_ERR, "fork: %m"); + return; + // FIXME: Do we treat this as a restart condition? + } + if (service->pid) { + service->state = Start; + return; + } + + closelog(); + dup2(service->outPipe[1], STDOUT_FILENO); + dup2(service->errPipe[1], STDERR_FILENO); + + int error = chdir(serviceDir); + if (error) err(StopExit, "%s", serviceDir); + + error = setgid(serviceGID); + if (error) err(StopExit, "setgid"); + + error = setuid(serviceUID); + if (error) err(StopExit, "setuid"); + + size_t len = 0; + char command[ARG_MAX]; + for (size_t i = 0; i < prepend.len; ++i) { + int n = snprintf( + &command[len], sizeof(command) - len, "%s;", prepend.commands[i] + ); + assert(n > 0); + len += n; + } + snprintf(&command[len], sizeof(command) - len, "exec %s", service->command); + + execle( + _PATH_BSHELL, + _PATH_BSHELL, "-c", command, service->name, NULL, + serviceEnviron + ); + err(StopExit, "%s", _PATH_BSHELL); +} diff --git a/spawnd.8 b/spawnd.8 index fc97498..1981304 100644 --- a/spawnd.8 +++ b/spawnd.8 @@ -114,8 +114,9 @@ The default list contains the values of .Dv EX_CANTCREAT , .Dv EX_CONFIG defined in -.Xr sysexits 3 , -as well as 127. +.Xr sysexits 3 . +The exit status 127 +is always treated as a stop exit. . .It Fl t Ar interval Set the initial interval between restarts |