mirror of
git://git.2f30.org/morpheus.git
synced 2024-06-16 12:48:34 +00:00
Make sinit a bit more sane
This commit is contained in:
parent
d262895579
commit
64445f446f
139
stuff/sinit.c
139
stuff/sinit.c
@ -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);
|
||||||
|
if (fd >= 0) {
|
||||||
while (1) {
|
while (1) {
|
||||||
FD_ZERO(&rfds);
|
FD_ZERO(&rfds);
|
||||||
FD_SET(fd, &rfds);
|
FD_SET(fd, &rfds);
|
||||||
n = select(fd + 1, &rfds, NULL, NULL, NULL);
|
n = select(fd + 1, &rfds, NULL, NULL, NULL);
|
||||||
if (n <= 0)
|
if (n <= 0)
|
||||||
continue;
|
continue;
|
||||||
if (FD_ISSET(fd, &rfds)) {
|
if (FD_ISSET(fd, &rfds))
|
||||||
n = read(fd, buf, sizeof(buf) - 1);
|
dispatchcmd(fd);
|
||||||
if (n < 0 || 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) {
|
}
|
||||||
|
|
||||||
|
/* can't reach */
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cmdpoweroff(const Arg *arg)
|
||||||
|
{
|
||||||
spawn("/bin/sh", (char *[]){
|
spawn("/bin/sh", (char *[]){
|
||||||
"sh",
|
"sh",
|
||||||
"-c",
|
"-c",
|
||||||
"/etc/rc.shutdown poweroff",
|
"/etc/rc.shutdown poweroff",
|
||||||
NULL
|
NULL
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
static void
|
||||||
|
cmdreboot(const Arg *arg)
|
||||||
/* unreached */
|
{
|
||||||
return 0;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user