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