sinit.c (1350B)
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 12 static void sigpoweroff(void); 13 static void sigreap(void); 14 static void sigreboot(void); 15 static void spawn(char *const []); 16 17 static struct { 18 int sig; 19 void (*handler)(void); 20 } sigmap[] = { 21 { SIGUSR1, sigpoweroff }, 22 { SIGCHLD, sigreap }, 23 { SIGINT, sigreboot }, 24 }; 25 26 #include "config.h" 27 28 static sigset_t set; 29 30 int 31 main(void) 32 { 33 int sig; 34 size_t i; 35 36 if (getpid() != 1) 37 return EXIT_FAILURE; 38 chdir("/"); 39 sigfillset(&set); 40 sigprocmask(SIG_BLOCK, &set, NULL); 41 spawn(rcinitcmd); 42 while (1) { 43 sigwait(&set, &sig); 44 for (i = 0; i < LEN(sigmap); i++) { 45 if (sigmap[i].sig == sig) { 46 sigmap[i].handler(); 47 break; 48 } 49 } 50 } 51 /* not reachable */ 52 return EXIT_SUCCESS; 53 } 54 55 static void 56 sigpoweroff(void) 57 { 58 spawn(rcpoweroffcmd); 59 } 60 61 static void 62 sigreap(void) 63 { 64 while (waitpid(-1, NULL, WNOHANG) > 0) 65 ; 66 } 67 68 static void 69 sigreboot(void) 70 { 71 spawn(rcrebootcmd); 72 } 73 74 static void 75 spawn(char *const argv[]) 76 { 77 pid_t pid; 78 79 pid = fork(); 80 if (pid < 0) { 81 perror("fork"); 82 } else if (pid == 0) { 83 sigprocmask(SIG_UNBLOCK, &set, NULL); 84 setsid(); 85 execvp(argv[0], argv); 86 perror("execvp"); 87 _exit(EXIT_FAILURE); 88 } 89 }