xref: /aosp_15_r20/external/toybox/toys/pending/init.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
1*cf5a6c84SAndroid Build Coastguard Worker /* init.c - init program.
2*cf5a6c84SAndroid Build Coastguard Worker  *
3*cf5a6c84SAndroid Build Coastguard Worker  * Copyright 2012 Harvind Singh <[email protected]>
4*cf5a6c84SAndroid Build Coastguard Worker  * Copyright 2013 Kyungwan Han  <[email protected]>
5*cf5a6c84SAndroid Build Coastguard Worker  *
6*cf5a6c84SAndroid Build Coastguard Worker  * No Standard
7*cf5a6c84SAndroid Build Coastguard Worker 
8*cf5a6c84SAndroid Build Coastguard Worker USE_INIT(NEWTOY(init, "", TOYFLAG_SBIN))
9*cf5a6c84SAndroid Build Coastguard Worker 
10*cf5a6c84SAndroid Build Coastguard Worker config INIT
11*cf5a6c84SAndroid Build Coastguard Worker   bool "init"
12*cf5a6c84SAndroid Build Coastguard Worker   default n
13*cf5a6c84SAndroid Build Coastguard Worker   help
14*cf5a6c84SAndroid Build Coastguard Worker     usage: init
15*cf5a6c84SAndroid Build Coastguard Worker 
16*cf5a6c84SAndroid Build Coastguard Worker     System V style init.
17*cf5a6c84SAndroid Build Coastguard Worker 
18*cf5a6c84SAndroid Build Coastguard Worker     First program to run (as PID 1) when the system comes up, reading
19*cf5a6c84SAndroid Build Coastguard Worker     /etc/inittab to determine actions.
20*cf5a6c84SAndroid Build Coastguard Worker */
21*cf5a6c84SAndroid Build Coastguard Worker 
22*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
23*cf5a6c84SAndroid Build Coastguard Worker #include <sys/reboot.h>
24*cf5a6c84SAndroid Build Coastguard Worker 
25*cf5a6c84SAndroid Build Coastguard Worker struct action_list_seed {
26*cf5a6c84SAndroid Build Coastguard Worker   struct action_list_seed *next;
27*cf5a6c84SAndroid Build Coastguard Worker   pid_t pid;
28*cf5a6c84SAndroid Build Coastguard Worker   uint8_t action;
29*cf5a6c84SAndroid Build Coastguard Worker   char *terminal_name;
30*cf5a6c84SAndroid Build Coastguard Worker   char *command;
31*cf5a6c84SAndroid Build Coastguard Worker } *action_list_pointer = NULL;
32*cf5a6c84SAndroid Build Coastguard Worker int caught_signal;
33*cf5a6c84SAndroid Build Coastguard Worker 
34*cf5a6c84SAndroid Build Coastguard Worker //INITTAB action defination
35*cf5a6c84SAndroid Build Coastguard Worker #define SYSINIT     0x01
36*cf5a6c84SAndroid Build Coastguard Worker #define WAIT        0x02
37*cf5a6c84SAndroid Build Coastguard Worker #define ONCE        0x04
38*cf5a6c84SAndroid Build Coastguard Worker #define RESPAWN     0x08
39*cf5a6c84SAndroid Build Coastguard Worker #define ASKFIRST    0x10
40*cf5a6c84SAndroid Build Coastguard Worker #define CTRLALTDEL  0x20
41*cf5a6c84SAndroid Build Coastguard Worker #define SHUTDOWN    0x40
42*cf5a6c84SAndroid Build Coastguard Worker #define RESTART     0x80
43*cf5a6c84SAndroid Build Coastguard Worker 
initialize_console(void)44*cf5a6c84SAndroid Build Coastguard Worker static void initialize_console(void)
45*cf5a6c84SAndroid Build Coastguard Worker {
46*cf5a6c84SAndroid Build Coastguard Worker   int fd;
47*cf5a6c84SAndroid Build Coastguard Worker   char *p = getenv("CONSOLE");
48*cf5a6c84SAndroid Build Coastguard Worker 
49*cf5a6c84SAndroid Build Coastguard Worker   if (!p) p = getenv("console");
50*cf5a6c84SAndroid Build Coastguard Worker   if (!p) {
51*cf5a6c84SAndroid Build Coastguard Worker     fd = open("/dev/null", O_RDWR);
52*cf5a6c84SAndroid Build Coastguard Worker     if (fd >= 0) {
53*cf5a6c84SAndroid Build Coastguard Worker       while (fd < 2) fd = dup(fd);
54*cf5a6c84SAndroid Build Coastguard Worker       while (fd > 2) close(fd--);
55*cf5a6c84SAndroid Build Coastguard Worker     }
56*cf5a6c84SAndroid Build Coastguard Worker   } else {
57*cf5a6c84SAndroid Build Coastguard Worker     fd = open(p, O_RDWR | O_NONBLOCK | O_NOCTTY);
58*cf5a6c84SAndroid Build Coastguard Worker     if (fd < 0) printf("Unable to open console %s\n",p);
59*cf5a6c84SAndroid Build Coastguard Worker     else {
60*cf5a6c84SAndroid Build Coastguard Worker       dup2(fd,0);
61*cf5a6c84SAndroid Build Coastguard Worker       dup2(fd,1);
62*cf5a6c84SAndroid Build Coastguard Worker       dup2(fd,2);
63*cf5a6c84SAndroid Build Coastguard Worker     }
64*cf5a6c84SAndroid Build Coastguard Worker   }
65*cf5a6c84SAndroid Build Coastguard Worker 
66*cf5a6c84SAndroid Build Coastguard Worker   if (!getenv("TERM")) putenv("TERM=linux");
67*cf5a6c84SAndroid Build Coastguard Worker }
68*cf5a6c84SAndroid Build Coastguard Worker 
reset_term(int fd)69*cf5a6c84SAndroid Build Coastguard Worker static void reset_term(int fd)
70*cf5a6c84SAndroid Build Coastguard Worker {
71*cf5a6c84SAndroid Build Coastguard Worker   struct termios terminal;
72*cf5a6c84SAndroid Build Coastguard Worker 
73*cf5a6c84SAndroid Build Coastguard Worker   tcgetattr(fd, &terminal);
74*cf5a6c84SAndroid Build Coastguard Worker   terminal.c_cc[VINTR] = 3;    //ctrl-c
75*cf5a6c84SAndroid Build Coastguard Worker   terminal.c_cc[VQUIT] = 28;   /*ctrl-\*/
76*cf5a6c84SAndroid Build Coastguard Worker   terminal.c_cc[VERASE] = 127; //ctrl-?
77*cf5a6c84SAndroid Build Coastguard Worker   terminal.c_cc[VKILL] = 21;   //ctrl-u
78*cf5a6c84SAndroid Build Coastguard Worker   terminal.c_cc[VEOF] = 4;     //ctrl-d
79*cf5a6c84SAndroid Build Coastguard Worker   terminal.c_cc[VSTART] = 17;  //ctrl-q
80*cf5a6c84SAndroid Build Coastguard Worker   terminal.c_cc[VSTOP] = 19;   //ctrl-s
81*cf5a6c84SAndroid Build Coastguard Worker   terminal.c_cc[VSUSP] = 26;   //ctrl-z
82*cf5a6c84SAndroid Build Coastguard Worker 
83*cf5a6c84SAndroid Build Coastguard Worker   terminal.c_line = 0;
84*cf5a6c84SAndroid Build Coastguard Worker   terminal.c_cflag &= CRTSCTS|PARODD|PARENB|CSTOPB|CSIZE|CBAUDEX|CBAUD;
85*cf5a6c84SAndroid Build Coastguard Worker   terminal.c_cflag |= CLOCAL|HUPCL|CREAD;
86*cf5a6c84SAndroid Build Coastguard Worker 
87*cf5a6c84SAndroid Build Coastguard Worker   //enable start/stop input and output control + map CR to NL on input
88*cf5a6c84SAndroid Build Coastguard Worker   terminal.c_iflag = IXON|IXOFF|ICRNL;
89*cf5a6c84SAndroid Build Coastguard Worker 
90*cf5a6c84SAndroid Build Coastguard Worker   //Map NL to CR-NL on output
91*cf5a6c84SAndroid Build Coastguard Worker   terminal.c_oflag = ONLCR|OPOST;
92*cf5a6c84SAndroid Build Coastguard Worker   terminal.c_lflag = IEXTEN|ECHOKE|ECHOCTL|ECHOK|ECHOE|ECHO|ICANON|ISIG;
93*cf5a6c84SAndroid Build Coastguard Worker   tcsetattr(fd, TCSANOW, &terminal);
94*cf5a6c84SAndroid Build Coastguard Worker }
95*cf5a6c84SAndroid Build Coastguard Worker 
add_new_action(int action,char * command,char * term)96*cf5a6c84SAndroid Build Coastguard Worker static void add_new_action(int action, char *command, char *term)
97*cf5a6c84SAndroid Build Coastguard Worker {
98*cf5a6c84SAndroid Build Coastguard Worker   struct action_list_seed *x,**y;
99*cf5a6c84SAndroid Build Coastguard Worker 
100*cf5a6c84SAndroid Build Coastguard Worker   y = &action_list_pointer;
101*cf5a6c84SAndroid Build Coastguard Worker   x = *y;
102*cf5a6c84SAndroid Build Coastguard Worker   while (x) {
103*cf5a6c84SAndroid Build Coastguard Worker     if (!(strcmp(x->command, command)) && !(strcmp(x->terminal_name, term))) {
104*cf5a6c84SAndroid Build Coastguard Worker       *y = x->next; //remove from the list
105*cf5a6c84SAndroid Build Coastguard Worker       while(*y) y = &(*y)->next; //traverse through list till end
106*cf5a6c84SAndroid Build Coastguard Worker       x->next = NULL;
107*cf5a6c84SAndroid Build Coastguard Worker       break;
108*cf5a6c84SAndroid Build Coastguard Worker     }
109*cf5a6c84SAndroid Build Coastguard Worker     y = &(x)->next;
110*cf5a6c84SAndroid Build Coastguard Worker     x = *y;
111*cf5a6c84SAndroid Build Coastguard Worker   }
112*cf5a6c84SAndroid Build Coastguard Worker 
113*cf5a6c84SAndroid Build Coastguard Worker   //create a new node
114*cf5a6c84SAndroid Build Coastguard Worker   if (!x) {
115*cf5a6c84SAndroid Build Coastguard Worker     x = xzalloc(sizeof(*x));
116*cf5a6c84SAndroid Build Coastguard Worker     x->command = xstrdup(command);
117*cf5a6c84SAndroid Build Coastguard Worker     x->terminal_name = xstrdup(term);
118*cf5a6c84SAndroid Build Coastguard Worker   }
119*cf5a6c84SAndroid Build Coastguard Worker   x->action = action;
120*cf5a6c84SAndroid Build Coastguard Worker   *y = x;
121*cf5a6c84SAndroid Build Coastguard Worker }
122*cf5a6c84SAndroid Build Coastguard Worker 
parse_inittab(void)123*cf5a6c84SAndroid Build Coastguard Worker static void parse_inittab(void)
124*cf5a6c84SAndroid Build Coastguard Worker {
125*cf5a6c84SAndroid Build Coastguard Worker   char *line = 0;
126*cf5a6c84SAndroid Build Coastguard Worker   size_t allocated_length = 0;
127*cf5a6c84SAndroid Build Coastguard Worker   ssize_t line_length = 0;
128*cf5a6c84SAndroid Build Coastguard Worker   int line_number = 0;
129*cf5a6c84SAndroid Build Coastguard Worker   char *act_name = "sysinit\0wait\0once\0respawn\0askfirst\0ctrlaltdel\0"
130*cf5a6c84SAndroid Build Coastguard Worker                     "shutdown\0restart\0";
131*cf5a6c84SAndroid Build Coastguard Worker   FILE *fp = fopen("/etc/inittab", "r");
132*cf5a6c84SAndroid Build Coastguard Worker 
133*cf5a6c84SAndroid Build Coastguard Worker   if (!fp) {
134*cf5a6c84SAndroid Build Coastguard Worker     error_msg("Unable to open /etc/inittab. Using Default inittab");
135*cf5a6c84SAndroid Build Coastguard Worker     add_new_action(SYSINIT, "/etc/init.d/rcS", "");
136*cf5a6c84SAndroid Build Coastguard Worker     add_new_action(RESPAWN, "/sbin/getty -n -l /bin/sh -L 115200 tty1 vt100", "");
137*cf5a6c84SAndroid Build Coastguard Worker     return;
138*cf5a6c84SAndroid Build Coastguard Worker   }
139*cf5a6c84SAndroid Build Coastguard Worker 
140*cf5a6c84SAndroid Build Coastguard Worker   while ((line_length = getline(&line, &allocated_length, fp)) > 0) {
141*cf5a6c84SAndroid Build Coastguard Worker     char *p = line, *x, *tty_name = 0, *command = 0, *extracted_token, *tmp;
142*cf5a6c84SAndroid Build Coastguard Worker     int action = 0, token_count = 0, i;
143*cf5a6c84SAndroid Build Coastguard Worker 
144*cf5a6c84SAndroid Build Coastguard Worker     if (p[line_length - 1] == '\n') p[line_length - 1] = '\0';
145*cf5a6c84SAndroid Build Coastguard Worker     if ((x = strchr(p, '#'))) *x = '\0';
146*cf5a6c84SAndroid Build Coastguard Worker     line_number++;
147*cf5a6c84SAndroid Build Coastguard Worker     action = 0;
148*cf5a6c84SAndroid Build Coastguard Worker 
149*cf5a6c84SAndroid Build Coastguard Worker     while ((extracted_token = strsep(&p,":"))) {
150*cf5a6c84SAndroid Build Coastguard Worker       token_count++;
151*cf5a6c84SAndroid Build Coastguard Worker       switch (token_count) {
152*cf5a6c84SAndroid Build Coastguard Worker         case 1:
153*cf5a6c84SAndroid Build Coastguard Worker           if (*extracted_token) {
154*cf5a6c84SAndroid Build Coastguard Worker             if (!strncmp(extracted_token, "/dev/", 5))
155*cf5a6c84SAndroid Build Coastguard Worker               tty_name = xmprintf("%s",extracted_token);
156*cf5a6c84SAndroid Build Coastguard Worker             else tty_name = xmprintf("/dev/%s",extracted_token);
157*cf5a6c84SAndroid Build Coastguard Worker           } else tty_name = xstrdup("");
158*cf5a6c84SAndroid Build Coastguard Worker           break;
159*cf5a6c84SAndroid Build Coastguard Worker         case 2:
160*cf5a6c84SAndroid Build Coastguard Worker           break;
161*cf5a6c84SAndroid Build Coastguard Worker         case 3:
162*cf5a6c84SAndroid Build Coastguard Worker           for (tmp = act_name, i = 0; *tmp; i++, tmp += strlen(tmp) +1) {
163*cf5a6c84SAndroid Build Coastguard Worker             if (!strcmp(tmp, extracted_token)) {
164*cf5a6c84SAndroid Build Coastguard Worker               action = 1 << i;
165*cf5a6c84SAndroid Build Coastguard Worker               break;
166*cf5a6c84SAndroid Build Coastguard Worker             }
167*cf5a6c84SAndroid Build Coastguard Worker           }
168*cf5a6c84SAndroid Build Coastguard Worker           if (!*tmp) error_msg("Invalid action at line number %d ---- ignoring",line_number);
169*cf5a6c84SAndroid Build Coastguard Worker           break;
170*cf5a6c84SAndroid Build Coastguard Worker         case 4:
171*cf5a6c84SAndroid Build Coastguard Worker           command = xstrdup(extracted_token);
172*cf5a6c84SAndroid Build Coastguard Worker           break;
173*cf5a6c84SAndroid Build Coastguard Worker         default:
174*cf5a6c84SAndroid Build Coastguard Worker           error_msg("Bad inittab entry at line %d", line_number);
175*cf5a6c84SAndroid Build Coastguard Worker           break;
176*cf5a6c84SAndroid Build Coastguard Worker       }
177*cf5a6c84SAndroid Build Coastguard Worker     }  //while token
178*cf5a6c84SAndroid Build Coastguard Worker 
179*cf5a6c84SAndroid Build Coastguard Worker     if (token_count == 4 && action) add_new_action(action, command, tty_name);
180*cf5a6c84SAndroid Build Coastguard Worker     free(tty_name);
181*cf5a6c84SAndroid Build Coastguard Worker     free(command);
182*cf5a6c84SAndroid Build Coastguard Worker   }
183*cf5a6c84SAndroid Build Coastguard Worker   free(line);
184*cf5a6c84SAndroid Build Coastguard Worker   fclose(fp);
185*cf5a6c84SAndroid Build Coastguard Worker }
186*cf5a6c84SAndroid Build Coastguard Worker 
reload_inittab(void)187*cf5a6c84SAndroid Build Coastguard Worker static void reload_inittab(void)
188*cf5a6c84SAndroid Build Coastguard Worker {
189*cf5a6c84SAndroid Build Coastguard Worker   // Remove all inactive actions, then reload /etc/inittab
190*cf5a6c84SAndroid Build Coastguard Worker   struct action_list_seed **y;
191*cf5a6c84SAndroid Build Coastguard Worker   y = &action_list_pointer;
192*cf5a6c84SAndroid Build Coastguard Worker   while (*y) {
193*cf5a6c84SAndroid Build Coastguard Worker     if (!(*y)->pid) {
194*cf5a6c84SAndroid Build Coastguard Worker       struct action_list_seed *x = *y;
195*cf5a6c84SAndroid Build Coastguard Worker       free(x->terminal_name);
196*cf5a6c84SAndroid Build Coastguard Worker       free(x->command);
197*cf5a6c84SAndroid Build Coastguard Worker       *y = (*y)->next;
198*cf5a6c84SAndroid Build Coastguard Worker       free(x);
199*cf5a6c84SAndroid Build Coastguard Worker       continue;
200*cf5a6c84SAndroid Build Coastguard Worker     }
201*cf5a6c84SAndroid Build Coastguard Worker     y = &(*y)->next;
202*cf5a6c84SAndroid Build Coastguard Worker   }
203*cf5a6c84SAndroid Build Coastguard Worker   parse_inittab();
204*cf5a6c84SAndroid Build Coastguard Worker }
205*cf5a6c84SAndroid Build Coastguard Worker 
run_command(char * command)206*cf5a6c84SAndroid Build Coastguard Worker static void run_command(char *command)
207*cf5a6c84SAndroid Build Coastguard Worker {
208*cf5a6c84SAndroid Build Coastguard Worker   char *final_command[128];
209*cf5a6c84SAndroid Build Coastguard Worker   int hyphen = (command[0]=='-');
210*cf5a6c84SAndroid Build Coastguard Worker 
211*cf5a6c84SAndroid Build Coastguard Worker   command = command + hyphen;
212*cf5a6c84SAndroid Build Coastguard Worker   if (!strpbrk(command, "?<>'\";[]{}\\|=()*&^$!`~")) {
213*cf5a6c84SAndroid Build Coastguard Worker     char *next_command;
214*cf5a6c84SAndroid Build Coastguard Worker     char *extracted_command;
215*cf5a6c84SAndroid Build Coastguard Worker     int x = 0;
216*cf5a6c84SAndroid Build Coastguard Worker 
217*cf5a6c84SAndroid Build Coastguard Worker     next_command = strncpy(toybuf, command - hyphen, sizeof(toybuf));
218*cf5a6c84SAndroid Build Coastguard Worker     next_command[sizeof(toybuf) - 1] = toybuf[sizeof(toybuf) - 1 ] = '\0';
219*cf5a6c84SAndroid Build Coastguard Worker     command = next_command + hyphen;
220*cf5a6c84SAndroid Build Coastguard Worker     while ((extracted_command = strsep(&next_command," \t"))) {
221*cf5a6c84SAndroid Build Coastguard Worker       if (*extracted_command) {
222*cf5a6c84SAndroid Build Coastguard Worker         final_command[x] = extracted_command;
223*cf5a6c84SAndroid Build Coastguard Worker         x++;
224*cf5a6c84SAndroid Build Coastguard Worker       }
225*cf5a6c84SAndroid Build Coastguard Worker     }
226*cf5a6c84SAndroid Build Coastguard Worker     final_command[x] = NULL;
227*cf5a6c84SAndroid Build Coastguard Worker   } else {
228*cf5a6c84SAndroid Build Coastguard Worker     snprintf(toybuf, sizeof(toybuf), "exec %s", command);
229*cf5a6c84SAndroid Build Coastguard Worker     command = "-/bin/sh"+1;
230*cf5a6c84SAndroid Build Coastguard Worker     final_command[0] = ("-/bin/sh"+!hyphen);
231*cf5a6c84SAndroid Build Coastguard Worker     final_command[1] = "-c";
232*cf5a6c84SAndroid Build Coastguard Worker     final_command[2] = toybuf;
233*cf5a6c84SAndroid Build Coastguard Worker     final_command[3] = NULL;
234*cf5a6c84SAndroid Build Coastguard Worker   }
235*cf5a6c84SAndroid Build Coastguard Worker   if (hyphen) ioctl(0, TIOCSCTTY, 0);
236*cf5a6c84SAndroid Build Coastguard Worker   execvp(command, final_command);
237*cf5a6c84SAndroid Build Coastguard Worker   error_msg("unable to run %s",command);
238*cf5a6c84SAndroid Build Coastguard Worker }
239*cf5a6c84SAndroid Build Coastguard Worker 
240*cf5a6c84SAndroid Build Coastguard Worker //runs all same type of actions
final_run(struct action_list_seed * x)241*cf5a6c84SAndroid Build Coastguard Worker static pid_t final_run(struct action_list_seed *x)
242*cf5a6c84SAndroid Build Coastguard Worker {
243*cf5a6c84SAndroid Build Coastguard Worker   pid_t pid;
244*cf5a6c84SAndroid Build Coastguard Worker   int fd;
245*cf5a6c84SAndroid Build Coastguard Worker   sigset_t signal_set;
246*cf5a6c84SAndroid Build Coastguard Worker 
247*cf5a6c84SAndroid Build Coastguard Worker   sigfillset(&signal_set);
248*cf5a6c84SAndroid Build Coastguard Worker   sigprocmask(SIG_BLOCK, &signal_set, NULL);
249*cf5a6c84SAndroid Build Coastguard Worker   if (x->action & ASKFIRST) pid = fork();
250*cf5a6c84SAndroid Build Coastguard Worker   else pid = vfork();
251*cf5a6c84SAndroid Build Coastguard Worker 
252*cf5a6c84SAndroid Build Coastguard Worker   if (pid > 0) {
253*cf5a6c84SAndroid Build Coastguard Worker     //parent process or error
254*cf5a6c84SAndroid Build Coastguard Worker     //unblock the signals
255*cf5a6c84SAndroid Build Coastguard Worker     sigfillset(&signal_set);
256*cf5a6c84SAndroid Build Coastguard Worker     sigprocmask(SIG_UNBLOCK, &signal_set, NULL);
257*cf5a6c84SAndroid Build Coastguard Worker 
258*cf5a6c84SAndroid Build Coastguard Worker     return pid;
259*cf5a6c84SAndroid Build Coastguard Worker   } else if (pid < 0) {
260*cf5a6c84SAndroid Build Coastguard Worker     perror_msg("fork fail");
261*cf5a6c84SAndroid Build Coastguard Worker     sleep(1);
262*cf5a6c84SAndroid Build Coastguard Worker     return 0;
263*cf5a6c84SAndroid Build Coastguard Worker   }
264*cf5a6c84SAndroid Build Coastguard Worker 
265*cf5a6c84SAndroid Build Coastguard Worker   //new born child process
266*cf5a6c84SAndroid Build Coastguard Worker   sigset_t signal_set_c;
267*cf5a6c84SAndroid Build Coastguard Worker   sigfillset(&signal_set_c);
268*cf5a6c84SAndroid Build Coastguard Worker   sigprocmask(SIG_UNBLOCK, &signal_set_c, NULL);
269*cf5a6c84SAndroid Build Coastguard Worker   setsid(); //new session
270*cf5a6c84SAndroid Build Coastguard Worker 
271*cf5a6c84SAndroid Build Coastguard Worker   if (x->terminal_name[0]) {
272*cf5a6c84SAndroid Build Coastguard Worker     close(0);
273*cf5a6c84SAndroid Build Coastguard Worker     fd = open(x->terminal_name, (O_RDWR|O_NONBLOCK),0600);
274*cf5a6c84SAndroid Build Coastguard Worker     if (fd != 0) {
275*cf5a6c84SAndroid Build Coastguard Worker       error_msg("Unable to open %s,%s\n", x->terminal_name, strerror(errno));
276*cf5a6c84SAndroid Build Coastguard Worker       _exit(EXIT_FAILURE);
277*cf5a6c84SAndroid Build Coastguard Worker     } else {
278*cf5a6c84SAndroid Build Coastguard Worker       dup2(0, 1);
279*cf5a6c84SAndroid Build Coastguard Worker       dup2(0, 2);
280*cf5a6c84SAndroid Build Coastguard Worker     }
281*cf5a6c84SAndroid Build Coastguard Worker   }
282*cf5a6c84SAndroid Build Coastguard Worker   reset_term(0);
283*cf5a6c84SAndroid Build Coastguard Worker   run_command(x->command);
284*cf5a6c84SAndroid Build Coastguard Worker   _exit(-1);
285*cf5a6c84SAndroid Build Coastguard Worker }
286*cf5a6c84SAndroid Build Coastguard Worker 
mark_as_terminated_process(pid_t pid)287*cf5a6c84SAndroid Build Coastguard Worker static struct action_list_seed* mark_as_terminated_process(pid_t pid)
288*cf5a6c84SAndroid Build Coastguard Worker {
289*cf5a6c84SAndroid Build Coastguard Worker   struct action_list_seed *x;
290*cf5a6c84SAndroid Build Coastguard Worker 
291*cf5a6c84SAndroid Build Coastguard Worker   if (pid > 0) {
292*cf5a6c84SAndroid Build Coastguard Worker     for (x = action_list_pointer; x; x = x->next) {
293*cf5a6c84SAndroid Build Coastguard Worker       if (x->pid == pid) {
294*cf5a6c84SAndroid Build Coastguard Worker         x->pid = 0;
295*cf5a6c84SAndroid Build Coastguard Worker         return x;
296*cf5a6c84SAndroid Build Coastguard Worker       }
297*cf5a6c84SAndroid Build Coastguard Worker     }
298*cf5a6c84SAndroid Build Coastguard Worker   }
299*cf5a6c84SAndroid Build Coastguard Worker 
300*cf5a6c84SAndroid Build Coastguard Worker   return NULL;
301*cf5a6c84SAndroid Build Coastguard Worker }
302*cf5a6c84SAndroid Build Coastguard Worker 
waitforpid(pid_t pid)303*cf5a6c84SAndroid Build Coastguard Worker static void waitforpid(pid_t pid)
304*cf5a6c84SAndroid Build Coastguard Worker {
305*cf5a6c84SAndroid Build Coastguard Worker   if (pid <= 0) return;
306*cf5a6c84SAndroid Build Coastguard Worker 
307*cf5a6c84SAndroid Build Coastguard Worker   while (!kill(pid, 0)) mark_as_terminated_process(wait(NULL));
308*cf5a6c84SAndroid Build Coastguard Worker }
309*cf5a6c84SAndroid Build Coastguard Worker 
run_action_from_list(int action)310*cf5a6c84SAndroid Build Coastguard Worker static void run_action_from_list(int action)
311*cf5a6c84SAndroid Build Coastguard Worker {
312*cf5a6c84SAndroid Build Coastguard Worker   pid_t pid;
313*cf5a6c84SAndroid Build Coastguard Worker   struct action_list_seed *x = action_list_pointer;
314*cf5a6c84SAndroid Build Coastguard Worker 
315*cf5a6c84SAndroid Build Coastguard Worker   for (; x; x = x->next) {
316*cf5a6c84SAndroid Build Coastguard Worker     if (!(x->action & action)) continue;
317*cf5a6c84SAndroid Build Coastguard Worker     if (x->action & (SHUTDOWN|ONCE|SYSINIT|CTRLALTDEL|WAIT)) {
318*cf5a6c84SAndroid Build Coastguard Worker       pid = final_run(x);
319*cf5a6c84SAndroid Build Coastguard Worker       if (!pid) return;
320*cf5a6c84SAndroid Build Coastguard Worker       if (x->action & (SHUTDOWN|SYSINIT|CTRLALTDEL|WAIT)) waitforpid(pid);
321*cf5a6c84SAndroid Build Coastguard Worker     }
322*cf5a6c84SAndroid Build Coastguard Worker     if (x->action & (ASKFIRST|RESPAWN))
323*cf5a6c84SAndroid Build Coastguard Worker       if (!(x->pid)) x->pid = final_run(x);
324*cf5a6c84SAndroid Build Coastguard Worker   }
325*cf5a6c84SAndroid Build Coastguard Worker  }
326*cf5a6c84SAndroid Build Coastguard Worker 
set_default(void)327*cf5a6c84SAndroid Build Coastguard Worker static void set_default(void)
328*cf5a6c84SAndroid Build Coastguard Worker {
329*cf5a6c84SAndroid Build Coastguard Worker   sigset_t signal_set_c;
330*cf5a6c84SAndroid Build Coastguard Worker 
331*cf5a6c84SAndroid Build Coastguard Worker   xsignal_all_killers(SIG_DFL);
332*cf5a6c84SAndroid Build Coastguard Worker   sigfillset(&signal_set_c);
333*cf5a6c84SAndroid Build Coastguard Worker   sigprocmask(SIG_UNBLOCK,&signal_set_c, NULL);
334*cf5a6c84SAndroid Build Coastguard Worker 
335*cf5a6c84SAndroid Build Coastguard Worker   run_action_from_list(SHUTDOWN);
336*cf5a6c84SAndroid Build Coastguard Worker   error_msg("The system is going down NOW!");
337*cf5a6c84SAndroid Build Coastguard Worker   kill(-1, SIGTERM);
338*cf5a6c84SAndroid Build Coastguard Worker   error_msg("Sent SIGTERM to all processes");
339*cf5a6c84SAndroid Build Coastguard Worker   sync();
340*cf5a6c84SAndroid Build Coastguard Worker   sleep(1);
341*cf5a6c84SAndroid Build Coastguard Worker   kill(-1,SIGKILL);
342*cf5a6c84SAndroid Build Coastguard Worker   sync();
343*cf5a6c84SAndroid Build Coastguard Worker }
344*cf5a6c84SAndroid Build Coastguard Worker 
halt_poweroff_reboot_handler(int sig_no)345*cf5a6c84SAndroid Build Coastguard Worker static void halt_poweroff_reboot_handler(int sig_no)
346*cf5a6c84SAndroid Build Coastguard Worker {
347*cf5a6c84SAndroid Build Coastguard Worker   unsigned int reboot_magic_no = 0;
348*cf5a6c84SAndroid Build Coastguard Worker   pid_t pid;
349*cf5a6c84SAndroid Build Coastguard Worker 
350*cf5a6c84SAndroid Build Coastguard Worker   set_default();
351*cf5a6c84SAndroid Build Coastguard Worker 
352*cf5a6c84SAndroid Build Coastguard Worker   switch (sig_no) {
353*cf5a6c84SAndroid Build Coastguard Worker     case SIGUSR1:
354*cf5a6c84SAndroid Build Coastguard Worker       error_msg("Requesting system halt");
355*cf5a6c84SAndroid Build Coastguard Worker       reboot_magic_no=RB_HALT_SYSTEM;
356*cf5a6c84SAndroid Build Coastguard Worker       break;
357*cf5a6c84SAndroid Build Coastguard Worker     case SIGUSR2:
358*cf5a6c84SAndroid Build Coastguard Worker       error_msg("Requesting system poweroff");
359*cf5a6c84SAndroid Build Coastguard Worker       reboot_magic_no=RB_POWER_OFF;
360*cf5a6c84SAndroid Build Coastguard Worker       break;
361*cf5a6c84SAndroid Build Coastguard Worker     case SIGTERM:
362*cf5a6c84SAndroid Build Coastguard Worker       error_msg("Requesting system reboot");
363*cf5a6c84SAndroid Build Coastguard Worker       reboot_magic_no=RB_AUTOBOOT;
364*cf5a6c84SAndroid Build Coastguard Worker       break;
365*cf5a6c84SAndroid Build Coastguard Worker     default:
366*cf5a6c84SAndroid Build Coastguard Worker       break;
367*cf5a6c84SAndroid Build Coastguard Worker   }
368*cf5a6c84SAndroid Build Coastguard Worker 
369*cf5a6c84SAndroid Build Coastguard Worker   sleep(1);
370*cf5a6c84SAndroid Build Coastguard Worker   pid = vfork();
371*cf5a6c84SAndroid Build Coastguard Worker 
372*cf5a6c84SAndroid Build Coastguard Worker   if (pid == 0) {
373*cf5a6c84SAndroid Build Coastguard Worker     reboot(reboot_magic_no);
374*cf5a6c84SAndroid Build Coastguard Worker     _exit(EXIT_SUCCESS);
375*cf5a6c84SAndroid Build Coastguard Worker   }
376*cf5a6c84SAndroid Build Coastguard Worker 
377*cf5a6c84SAndroid Build Coastguard Worker   while(1) sleep(1);
378*cf5a6c84SAndroid Build Coastguard Worker }
379*cf5a6c84SAndroid Build Coastguard Worker 
restart_init_handler(int sig_no)380*cf5a6c84SAndroid Build Coastguard Worker static void restart_init_handler(int sig_no)
381*cf5a6c84SAndroid Build Coastguard Worker {
382*cf5a6c84SAndroid Build Coastguard Worker   struct action_list_seed *x;
383*cf5a6c84SAndroid Build Coastguard Worker   pid_t pid;
384*cf5a6c84SAndroid Build Coastguard Worker   int fd;
385*cf5a6c84SAndroid Build Coastguard Worker 
386*cf5a6c84SAndroid Build Coastguard Worker   for (x = action_list_pointer; x; x = x->next) {
387*cf5a6c84SAndroid Build Coastguard Worker     if (!(x->action & RESTART)) continue;
388*cf5a6c84SAndroid Build Coastguard Worker 
389*cf5a6c84SAndroid Build Coastguard Worker     set_default();
390*cf5a6c84SAndroid Build Coastguard Worker 
391*cf5a6c84SAndroid Build Coastguard Worker     if (x->terminal_name[0]) {
392*cf5a6c84SAndroid Build Coastguard Worker       close(0);
393*cf5a6c84SAndroid Build Coastguard Worker       fd = open(x->terminal_name, (O_RDWR|O_NONBLOCK),0600);
394*cf5a6c84SAndroid Build Coastguard Worker 
395*cf5a6c84SAndroid Build Coastguard Worker       if (fd != 0) {
396*cf5a6c84SAndroid Build Coastguard Worker         error_msg("Unable to open %s,%s\n", x->terminal_name, strerror(errno));
397*cf5a6c84SAndroid Build Coastguard Worker         sleep(1);
398*cf5a6c84SAndroid Build Coastguard Worker         pid = vfork();
399*cf5a6c84SAndroid Build Coastguard Worker 
400*cf5a6c84SAndroid Build Coastguard Worker         if (pid == 0) {
401*cf5a6c84SAndroid Build Coastguard Worker           reboot(RB_HALT_SYSTEM);
402*cf5a6c84SAndroid Build Coastguard Worker           _exit(EXIT_SUCCESS);
403*cf5a6c84SAndroid Build Coastguard Worker         }
404*cf5a6c84SAndroid Build Coastguard Worker 
405*cf5a6c84SAndroid Build Coastguard Worker         while(1) sleep(1);
406*cf5a6c84SAndroid Build Coastguard Worker       } else {
407*cf5a6c84SAndroid Build Coastguard Worker         dup2(0, 1);
408*cf5a6c84SAndroid Build Coastguard Worker         dup2(0, 2);
409*cf5a6c84SAndroid Build Coastguard Worker         reset_term(0);
410*cf5a6c84SAndroid Build Coastguard Worker         run_command(x->command);
411*cf5a6c84SAndroid Build Coastguard Worker       }
412*cf5a6c84SAndroid Build Coastguard Worker     }
413*cf5a6c84SAndroid Build Coastguard Worker   }
414*cf5a6c84SAndroid Build Coastguard Worker }
415*cf5a6c84SAndroid Build Coastguard Worker 
catch_signal(int sig_no)416*cf5a6c84SAndroid Build Coastguard Worker static void catch_signal(int sig_no)
417*cf5a6c84SAndroid Build Coastguard Worker {
418*cf5a6c84SAndroid Build Coastguard Worker   caught_signal = sig_no;
419*cf5a6c84SAndroid Build Coastguard Worker   error_msg("signal seen: %d", sig_no);
420*cf5a6c84SAndroid Build Coastguard Worker }
421*cf5a6c84SAndroid Build Coastguard Worker 
pause_handler(int sig_no)422*cf5a6c84SAndroid Build Coastguard Worker static void pause_handler(int sig_no)
423*cf5a6c84SAndroid Build Coastguard Worker {
424*cf5a6c84SAndroid Build Coastguard Worker   int signal_backup,errno_backup;
425*cf5a6c84SAndroid Build Coastguard Worker   pid_t pid;
426*cf5a6c84SAndroid Build Coastguard Worker 
427*cf5a6c84SAndroid Build Coastguard Worker   errno_backup = errno;
428*cf5a6c84SAndroid Build Coastguard Worker   signal_backup = caught_signal;
429*cf5a6c84SAndroid Build Coastguard Worker   xsignal(SIGCONT, catch_signal);
430*cf5a6c84SAndroid Build Coastguard Worker 
431*cf5a6c84SAndroid Build Coastguard Worker   while(1) {
432*cf5a6c84SAndroid Build Coastguard Worker     if (caught_signal == SIGCONT) break;
433*cf5a6c84SAndroid Build Coastguard Worker     do pid = waitpid(-1,NULL,WNOHANG); while((pid==-1) && (errno=EINTR));
434*cf5a6c84SAndroid Build Coastguard Worker     mark_as_terminated_process(pid);
435*cf5a6c84SAndroid Build Coastguard Worker     sleep(1);
436*cf5a6c84SAndroid Build Coastguard Worker   }
437*cf5a6c84SAndroid Build Coastguard Worker 
438*cf5a6c84SAndroid Build Coastguard Worker   signal(SIGCONT, SIG_DFL);
439*cf5a6c84SAndroid Build Coastguard Worker   errno = errno_backup;
440*cf5a6c84SAndroid Build Coastguard Worker   caught_signal = signal_backup;
441*cf5a6c84SAndroid Build Coastguard Worker }
442*cf5a6c84SAndroid Build Coastguard Worker 
check_if_pending_signals(void)443*cf5a6c84SAndroid Build Coastguard Worker static int check_if_pending_signals(void)
444*cf5a6c84SAndroid Build Coastguard Worker {
445*cf5a6c84SAndroid Build Coastguard Worker   int signal_caught = 0;
446*cf5a6c84SAndroid Build Coastguard Worker 
447*cf5a6c84SAndroid Build Coastguard Worker   while(1) {
448*cf5a6c84SAndroid Build Coastguard Worker     int sig = caught_signal;
449*cf5a6c84SAndroid Build Coastguard Worker     if (!sig) return signal_caught;
450*cf5a6c84SAndroid Build Coastguard Worker     caught_signal = 0;
451*cf5a6c84SAndroid Build Coastguard Worker     signal_caught = 1;
452*cf5a6c84SAndroid Build Coastguard Worker     if (sig == SIGINT) run_action_from_list(CTRLALTDEL);
453*cf5a6c84SAndroid Build Coastguard Worker     else if (sig == SIGHUP) {
454*cf5a6c84SAndroid Build Coastguard Worker       error_msg("reloading inittab");
455*cf5a6c84SAndroid Build Coastguard Worker       reload_inittab();
456*cf5a6c84SAndroid Build Coastguard Worker     }
457*cf5a6c84SAndroid Build Coastguard Worker   }
458*cf5a6c84SAndroid Build Coastguard Worker }
459*cf5a6c84SAndroid Build Coastguard Worker 
init_main(void)460*cf5a6c84SAndroid Build Coastguard Worker void init_main(void)
461*cf5a6c84SAndroid Build Coastguard Worker {
462*cf5a6c84SAndroid Build Coastguard Worker   struct sigaction sig_act;
463*cf5a6c84SAndroid Build Coastguard Worker 
464*cf5a6c84SAndroid Build Coastguard Worker   if (getpid() != 1) error_exit("Already running");
465*cf5a6c84SAndroid Build Coastguard Worker   printf("Started init\n");
466*cf5a6c84SAndroid Build Coastguard Worker   initialize_console();
467*cf5a6c84SAndroid Build Coastguard Worker   reset_term(0);
468*cf5a6c84SAndroid Build Coastguard Worker 
469*cf5a6c84SAndroid Build Coastguard Worker   if (chdir("/")) perror_exit("Can't cd to /");
470*cf5a6c84SAndroid Build Coastguard Worker   setsid();
471*cf5a6c84SAndroid Build Coastguard Worker 
472*cf5a6c84SAndroid Build Coastguard Worker   putenv("HOME=/");
473*cf5a6c84SAndroid Build Coastguard Worker   putenv("PATH=/sbin:/usr/sbin:/bin:/usr/bin");
474*cf5a6c84SAndroid Build Coastguard Worker   putenv("SHELL=/bin/sh");
475*cf5a6c84SAndroid Build Coastguard Worker   putenv("USER=root");
476*cf5a6c84SAndroid Build Coastguard Worker 
477*cf5a6c84SAndroid Build Coastguard Worker   parse_inittab();
478*cf5a6c84SAndroid Build Coastguard Worker   xsignal(SIGUSR1, halt_poweroff_reboot_handler);//halt
479*cf5a6c84SAndroid Build Coastguard Worker   xsignal(SIGUSR2, halt_poweroff_reboot_handler);//poweroff
480*cf5a6c84SAndroid Build Coastguard Worker   xsignal(SIGTERM, halt_poweroff_reboot_handler);//reboot
481*cf5a6c84SAndroid Build Coastguard Worker   xsignal(SIGQUIT, restart_init_handler);//restart init
482*cf5a6c84SAndroid Build Coastguard Worker   memset(&sig_act, 0, sizeof(sig_act));
483*cf5a6c84SAndroid Build Coastguard Worker   sigfillset(&sig_act.sa_mask);
484*cf5a6c84SAndroid Build Coastguard Worker   sigdelset(&sig_act.sa_mask, SIGCONT);
485*cf5a6c84SAndroid Build Coastguard Worker   sig_act.sa_handler = pause_handler;
486*cf5a6c84SAndroid Build Coastguard Worker   sigaction(SIGTSTP, &sig_act, NULL);
487*cf5a6c84SAndroid Build Coastguard Worker   memset(&sig_act, 0, sizeof(sig_act));
488*cf5a6c84SAndroid Build Coastguard Worker   sig_act.sa_handler = catch_signal;
489*cf5a6c84SAndroid Build Coastguard Worker   sigaction(SIGINT, &sig_act, NULL);
490*cf5a6c84SAndroid Build Coastguard Worker   sigaction(SIGHUP, &sig_act, NULL);
491*cf5a6c84SAndroid Build Coastguard Worker   run_action_from_list(SYSINIT);
492*cf5a6c84SAndroid Build Coastguard Worker   check_if_pending_signals();
493*cf5a6c84SAndroid Build Coastguard Worker   run_action_from_list(WAIT);
494*cf5a6c84SAndroid Build Coastguard Worker   check_if_pending_signals();
495*cf5a6c84SAndroid Build Coastguard Worker   run_action_from_list(ONCE);
496*cf5a6c84SAndroid Build Coastguard Worker   while (1) {
497*cf5a6c84SAndroid Build Coastguard Worker     int suspected_WNOHANG = check_if_pending_signals();
498*cf5a6c84SAndroid Build Coastguard Worker 
499*cf5a6c84SAndroid Build Coastguard Worker     run_action_from_list(RESPAWN | ASKFIRST);
500*cf5a6c84SAndroid Build Coastguard Worker     suspected_WNOHANG = suspected_WNOHANG|check_if_pending_signals();
501*cf5a6c84SAndroid Build Coastguard Worker     sleep(1);//let cpu breath
502*cf5a6c84SAndroid Build Coastguard Worker     suspected_WNOHANG = suspected_WNOHANG|check_if_pending_signals();
503*cf5a6c84SAndroid Build Coastguard Worker     if (suspected_WNOHANG) suspected_WNOHANG=WNOHANG;
504*cf5a6c84SAndroid Build Coastguard Worker 
505*cf5a6c84SAndroid Build Coastguard Worker     while(1) {
506*cf5a6c84SAndroid Build Coastguard Worker       pid_t pid = waitpid(-1, NULL, suspected_WNOHANG);
507*cf5a6c84SAndroid Build Coastguard Worker 
508*cf5a6c84SAndroid Build Coastguard Worker       if (pid <= 0) break;
509*cf5a6c84SAndroid Build Coastguard Worker       mark_as_terminated_process(pid);
510*cf5a6c84SAndroid Build Coastguard Worker       suspected_WNOHANG = WNOHANG;
511*cf5a6c84SAndroid Build Coastguard Worker     }
512*cf5a6c84SAndroid Build Coastguard Worker   }
513*cf5a6c84SAndroid Build Coastguard Worker }
514