unix/fiss

src/finit/finit.c in master
Repositories | Summary | Log | Files | LICENSE

finit.c (1548B) download


 1/* See LICENSE file for copyright and license details. */
 2#include <common.h>
 3#include <fmt.h>
 4#include <signal.h>
 5#include <stdio.h>
 6#include <stdlib.h>
 7#include <sys/types.h>
 8#include <sys/wait.h>
 9#include <unistd.h>
10
11#define TIMEO 30
12
13static void sighalt(void);
14static void sigreap(void);
15static void sigreboot(void);
16
17static const struct {
18	int sig;
19	void (*handler)(void);
20} sigmap[] = {
21	{ SIGTERM, sighalt },
22	{ SIGINT, sigreboot },
23	{ SIGCHLD, sigreap },
24	{ SIGALRM, sigreap },
25};
26
27static sigset_t set;
28static pid_t    run_pid;
29
30static char start_command[] = "/etc/fiss/run";
31static char stop_command[]  = "/etc/fiss/halt";
32
33int main(void) {
34	int signal;
35
36	if (getpid() != 1)
37		return 1;
38
39	chdir("/");
40	sigfillset(&set);
41	sigprocmask(SIG_BLOCK, &set, NULL);
42
43	switch (run_pid = fork()) {
44		case 0:
45			sigprocmask(SIG_UNBLOCK, &set, NULL);
46			setsid();
47			execl(start_command, start_command, NULL);
48			perror("execvp");
49			_exit(1);
50		case -1:
51			perror("fork");
52	}
53
54	while (1) {
55		alarm(TIMEO);
56		sigwait(&set, &signal);
57		for (int i = 0; i < (int) LEN(sigmap); i++) {
58			if (sigmap[i].sig == signal) {
59				sigmap[i].handler();
60				break;
61			}
62		}
63	}
64
65	/* not reachable */
66	return 0;
67}
68
69static void
70sighalt(void) {
71	execl(stop_command, stop_command, "halt", NULL);
72}
73
74static void
75sigreboot(void) {
76	execl(stop_command, stop_command, "reboot", NULL);
77}
78
79static void
80sigreap(void) {
81	pid_t pid;
82	while ((pid = waitpid(-1, NULL, WNOHANG)) > 0)
83		if (pid == run_pid) {
84			fprint(1, "run stopped, halting\n");
85			sighalt();
86		}
87	alarm(TIMEO);
88}