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}