aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.def.h2
-rw-r--r--sinit.c123
2 files changed, 86 insertions, 39 deletions
diff --git a/config.def.h b/config.def.h
index ac9cf9b..9bfe505 100644
--- 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
index 3942457..14ee7ca 100644
--- 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_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;