commit 64445f446fc11e5e7b083229e84f6ff71788c169
parent d262895579ad2624d5a588e4991598fcc8aec0fe
Author: sin <sin@2f30.org>
Date: Wed, 5 Feb 2014 18:18:37 +0000
Make sinit a bit more sane
Diffstat:
M | 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);
+ }
}