diff options
author | sin <sin@2f30.org> | 2014-02-07 12:47:15 +0000 |
---|---|---|
committer | sin <sin@2f30.org> | 2014-02-07 12:57:46 +0000 |
commit | 8194f460daaa9343ce9863838b14132d0ad8037c (patch) | |
tree | e8f37cc8d5b70a4daa4640afb82df2c69f8b82a7 /sinit.c | |
parent | 23dbb870c7ad1d82a5c2a967683158da54ab3469 (diff) |
Refactor code
We no longer have two processes, one for reaping children and
another for handling the FIFO.
Use signalfd() to multiplex signal handling and reading from the
FIFO.
This setup will also allow us to capture ctrl-alt-del and to work
with a read-only rootfs.
To create the FIFO, we send a SIGHUP signal to init from our init
scripts.
Diffstat (limited to 'sinit.c')
-rw-r--r-- | sinit.c | 123 |
1 files changed, 86 insertions, 37 deletions
@@ -7,6 +7,7 @@ #include <stdlib.h> #include <string.h> #include <sys/select.h> +#include <sys/signalfd.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/wait.h> @@ -23,57 +24,78 @@ typedef struct { const Arg arg; } Command; +volatile sig_atomic_t signum; + +typedef struct { + int sig; + void (*func)(void); +} Sigmap; + static void dispatchcmd(int); +static void sigfifo(void); +static void sigreap(void); +static void sigreboot(void); static void spawn(const Arg *); +static Sigmap dispatchsig[] = { + { SIGHUP, sigfifo }, + { SIGCHLD, sigreap }, + { SIGINT, sigreboot }, +}; + +static int sigfd = -1; +static int fifofd = -1; + #include "config.h" int main(void) { - sigset_t set; - pid_t pid; + struct signalfd_siginfo siginfo; + sigset_t sigset; + int maxfd, i, ret; + ssize_t n; fd_set rfds; - int status, fd, n; if (getpid() != 1) return EXIT_FAILURE; setsid(); - sigfillset(&set); - sigprocmask(SIG_BLOCK, &set, 0); - - pid = fork(); - if (pid < 0) - return EXIT_FAILURE; - if (pid > 0) - for (;;) - wait(&status); - - sigprocmask(SIG_UNBLOCK, &set, 0); - - spawn(&rcinitarg); - - if (!fifopath) - return EXIT_SUCCESS; - - unlink(fifopath); - umask(0); - if (mkfifo(fifopath, 0600) < 0) - weprintf("sinit: mkfifo %s:", fifopath); - - fd = open(fifopath, O_RDWR | O_NONBLOCK); - if (fd < 0) - weprintf("sinit: open %s:", fifopath); - if (fd >= 0) { - while (1) { - FD_ZERO(&rfds); - FD_SET(fd, &rfds); - n = select(fd + 1, &rfds, NULL, NULL, NULL); - if (n < 0) - eprintf("sinit: select:"); - if (FD_ISSET(fd, &rfds)) - dispatchcmd(fd); + sigemptyset(&sigset); + for (i = 0; i < LEN(dispatchsig); i++) + sigaddset(&sigset, dispatchsig[i].sig); + sigprocmask(SIG_BLOCK, &sigset, NULL); + + sigfd = signalfd(-1, &sigset, 0); + if (sigfd < 0) + eprintf("sinit: signalfd:"); + + spawn(&(Arg){ .v = rcinitcmd }); + + while (1) { + FD_ZERO(&rfds); + FD_SET(sigfd, &rfds); + maxfd = sigfd; + if (fifofd != -1) { + FD_SET(fifofd, &rfds); + if (fifofd > maxfd) + maxfd = fifofd; + } + ret = select(maxfd + 1, &rfds, NULL, NULL, NULL); + if (ret < 0) + eprintf("sinit: select:"); + if (ret > 0) { + if (FD_ISSET(sigfd, &rfds)) { + n = read(sigfd, &siginfo, sizeof(siginfo)); + if (n <= 0) + continue; + for (i = 0; i < LEN(dispatchsig); i++) + if (dispatchsig[i].sig == siginfo.ssi_signo) + dispatchsig[i].func(); + } + if (fifofd != -1) + if (FD_ISSET(fifofd, &rfds)) + dispatchcmd(fifofd); } } @@ -103,6 +125,33 @@ dispatchcmd(int fd) } static void +sigfifo(void) +{ + if (!fifopath) + return; + unlink(fifopath); + umask(0); + if (mkfifo(fifopath, 0600) < 0) + weprintf("sinit: mkfifo %s:", fifopath); + fifofd = open(fifopath, O_RDWR | O_NONBLOCK); + if (fifofd < 0) + weprintf("sinit: open %s:", fifopath); +} + +static void +sigreap(void) +{ + while (waitpid(-1, NULL, WNOHANG) > 0) + ; +} + +static void +sigreboot(void) +{ + spawn(&(Arg){ .v = rcrebootcmd }); +} + +static void spawn(const Arg *arg) { int status; |