morpheus

suckless linux distro
git clone git://git.2f30.org/morpheus.git
Log | Files | Refs | Submodules | README | LICENSE

commit 64445f446fc11e5e7b083229e84f6ff71788c169
parent d262895579ad2624d5a588e4991598fcc8aec0fe
Author: sin <sin@2f30.org>
Date:   Wed Feb  5 18:18:37 +0000

Make sinit a bit more sane

Diffstat:
stuff/sinit.c | 157+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
1 file changed, 105 insertions(+), 52 deletions(-)
diff --git a/stuff/sinit.c b/stuff/sinit.c @@ -1,49 +1,61 @@ +#include <err.h> #include <errno.h> #include <fcntl.h> #include <signal.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <sys/select.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> -static int -spawn(const char *file, char *const argv[]) -{ - pid_t pid; +#define LEN(x) (sizeof (x) / sizeof *(x)) - pid = fork(); - if (pid < 0) - return pid; - if (pid == 0) { - setsid(); - setpgid(0, 0); - execvp(file, argv); - _exit(errno == ENOENT ? 127 : 126); - } -} +typedef union { + int i; + unsigned int ui; + float f; + const void *v; +} Arg; + +typedef struct { + const char *name; + void (*func)(const Arg *arg); + const Arg arg; +} Command; + +static void cmdpoweroff(const Arg *); +static void cmdreboot(const Arg *); +static void dispatchcmd(int); +static int spawn(const char *, char *const []); + +static const char *fifopath = "/var/run/init.fifo"; +static Command commands[] = { + { "poweroff", cmdpoweroff, {0} }, + { "reboot", cmdreboot, {0} }, +}; int main(void) { - const char *fifopath = "/var/run/init.fifo"; sigset_t set; pid_t pid; fd_set rfds; - char buf[BUFSIZ], *p; - int c; - int fd; - int n; + int c, fd, n; - if (getpid() != 1) return 1; + if (getpid() != 1) + return EXIT_FAILURE; sigfillset(&set); sigprocmask(SIG_BLOCK, &set, 0); pid = fork(); - if (pid < 0) return 1; - if (pid > 0) for (;;) wait(&c); + if (pid < 0) + return EXIT_FAILURE; + if (pid > 0) + for (;;) + wait(&c); sigprocmask(SIG_UNBLOCK, &set, 0); @@ -52,39 +64,80 @@ main(void) unlink(fifopath); umask(0); mkfifo(fifopath, 0600); + fd = open(fifopath, O_RDWR | O_NONBLOCK); - while (1) { - FD_ZERO(&rfds); - FD_SET(fd, &rfds); - n = select(fd + 1, &rfds, NULL, NULL, NULL); - if (n <= 0) - continue; - if (FD_ISSET(fd, &rfds)) { - n = read(fd, buf, sizeof(buf) - 1); - if (n < 0 || n == 0) + if (fd >= 0) { + while (1) { + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + n = select(fd + 1, &rfds, NULL, NULL, NULL); + if (n <= 0) continue; - buf[n] = '\0'; - p = strchr(buf, '\n'); - if (p) *p = '\0'; - if (strcmp(buf, "reboot") == 0) { - spawn("/bin/sh", (char *[]){ - "sh", - "-c", - "/etc/rc.shutdown reboot", - NULL - }); - } - if (strcmp(buf, "poweroff") == 0) { - spawn("/bin/sh", (char *[]){ - "sh", - "-c", - "/etc/rc.shutdown poweroff", - NULL - }); - } + if (FD_ISSET(fd, &rfds)) + dispatchcmd(fd); } } - /* unreached */ - return 0; + /* can't reach */ + return EXIT_SUCCESS; +} + +static void +cmdpoweroff(const Arg *arg) +{ + spawn("/bin/sh", (char *[]){ + "sh", + "-c", + "/etc/rc.shutdown poweroff", + NULL + }); +} + +static void +cmdreboot(const Arg *arg) +{ + spawn("/bin/sh", (char *[]){ + "sh", + "-c", + "/etc/rc.shutdown reboot", + NULL + }); +} + +static void +dispatchcmd(int fd) +{ + int i; + char buf[BUFSIZ], *p; + ssize_t n; + + n = read(fd, buf, sizeof(buf) - 1); + if (n <= 0) + return; + buf[n] = '\0'; + p = strchr(buf, '\n'); + if (p) + *p = '\0'; + for (i = 0; i < LEN(commands); i++) { + if (strcmp(commands[i].name, buf) == 0) { + commands[i].func(&commands[i].arg); + break; + } + } +} + +static int +spawn(const char *file, char *const argv[]) +{ + pid_t pid; + + pid = fork(); + if (pid < 0) + return -1; + if (pid == 0) { + setsid(); + setpgid(0, 0); + execvp(file, argv); + _exit(errno == ENOENT ? 127 : 126); + } }