Make sinit a bit more sane

This commit is contained in:
sin 2014-02-05 18:18:37 +00:00
parent d262895579
commit 64445f446f

View File

@ -1,49 +1,61 @@
#include <err.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <signal.h> #include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/select.h> #include <sys/select.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
static int #define LEN(x) (sizeof (x) / sizeof *(x))
spawn(const char *file, char *const argv[])
{
pid_t pid;
pid = fork(); typedef union {
if (pid < 0) int i;
return pid; unsigned int ui;
if (pid == 0) { float f;
setsid(); const void *v;
setpgid(0, 0); } Arg;
execvp(file, argv);
_exit(errno == ENOENT ? 127 : 126); 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 int
main(void) main(void)
{ {
const char *fifopath = "/var/run/init.fifo";
sigset_t set; sigset_t set;
pid_t pid; pid_t pid;
fd_set rfds; fd_set rfds;
char buf[BUFSIZ], *p; int c, fd, n;
int c;
int fd;
int n;
if (getpid() != 1) return 1; if (getpid() != 1)
return EXIT_FAILURE;
sigfillset(&set); sigfillset(&set);
sigprocmask(SIG_BLOCK, &set, 0); sigprocmask(SIG_BLOCK, &set, 0);
pid = fork(); pid = fork();
if (pid < 0) return 1; if (pid < 0)
if (pid > 0) for (;;) wait(&c); return EXIT_FAILURE;
if (pid > 0)
for (;;)
wait(&c);
sigprocmask(SIG_UNBLOCK, &set, 0); sigprocmask(SIG_UNBLOCK, &set, 0);
@ -52,39 +64,80 @@ main(void)
unlink(fifopath); unlink(fifopath);
umask(0); umask(0);
mkfifo(fifopath, 0600); mkfifo(fifopath, 0600);
fd = open(fifopath, O_RDWR | O_NONBLOCK); fd = open(fifopath, O_RDWR | O_NONBLOCK);
while (1) { if (fd >= 0) {
FD_ZERO(&rfds); while (1) {
FD_SET(fd, &rfds); FD_ZERO(&rfds);
n = select(fd + 1, &rfds, NULL, NULL, NULL); FD_SET(fd, &rfds);
if (n <= 0) n = select(fd + 1, &rfds, NULL, NULL, NULL);
continue; if (n <= 0)
if (FD_ISSET(fd, &rfds)) {
n = read(fd, buf, sizeof(buf) - 1);
if (n < 0 || n == 0)
continue; continue;
buf[n] = '\0'; if (FD_ISSET(fd, &rfds))
p = strchr(buf, '\n'); dispatchcmd(fd);
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
});
}
} }
} }
/* unreached */ /* can't reach */
return 0; 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);
}
} }