URI: 
       Refactor code - sinit - suckless init
  HTML git clone git://git.suckless.org/sinit
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 8194f460daaa9343ce9863838b14132d0ad8037c
   DIR parent 23dbb870c7ad1d82a5c2a967683158da54ab3469
  HTML Author: sin <sin@2f30.org>
       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(-)
       ---
   DIR 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 };
        
   DIR 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_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;