Refactor code - sinit - suckless init | |
git clone git://git.suckless.org/sinit | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 8194f460daaa9343ce9863838b14132d0ad8037c | |
parent 23dbb870c7ad1d82a5c2a967683158da54ab3469 | |
Author: sin <[email protected]> | |
Date: Fri, 7 Feb 2014 12:47:15 +0000 | |
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: | |
M config.def.h | 2 -- | |
M sinit.c | 123 +++++++++++++++++++++--------… | |
2 files changed, 86 insertions(+), 39 deletions(-) | |
--- | |
diff --git a/config.def.h b/config.def.h | |
@@ -1,8 +1,6 @@ | |
/* See LICENSE file for copyright and license details. */ | |
static const char *rcinitcmd[] = { "/bin/rc.init", NULL }; | |
-static Arg rcinitarg = { .v = rcinitcmd }; | |
- | |
static const char *rcrebootcmd[] = { "/bin/rc.shutdown", "reboot", NULL }; | |
static const char *rcpoweroffcmd[] = { "/bin/rc.shutdown", "poweroff", NULL }; | |
diff --git a/sinit.c b/sinit.c | |
@@ -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_… | |
+ 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; |