blob: d29328c36f9a801af03a5ff403746fe9c41c74a0
1 | /* vi: set sw=4 ts=4: */ |
2 | /* |
3 | * Mini init implementation for busybox |
4 | * |
5 | * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>. |
6 | * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> |
7 | * Adjusted by so many folks, it's impossible to keep track. |
8 | * |
9 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
10 | */ |
11 | |
12 | //config:config INIT |
13 | //config: bool "init" |
14 | //config: default y |
15 | //config: select FEATURE_SYSLOG |
16 | //config: help |
17 | //config: init is the first program run when the system boots. |
18 | //config: |
19 | //config:config FEATURE_USE_INITTAB |
20 | //config: bool "Support reading an inittab file" |
21 | //config: default y |
22 | //config: depends on INIT |
23 | //config: help |
24 | //config: Allow init to read an inittab file when the system boot. |
25 | //config: |
26 | //config:config FEATURE_KILL_REMOVED |
27 | //config: bool "Support killing processes that have been removed from inittab" |
28 | //config: default n |
29 | //config: depends on FEATURE_USE_INITTAB |
30 | //config: help |
31 | //config: When respawn entries are removed from inittab and a SIGHUP is |
32 | //config: sent to init, this option will make init kill the processes |
33 | //config: that have been removed. |
34 | //config: |
35 | //config:config FEATURE_KILL_DELAY |
36 | //config: int "How long to wait between TERM and KILL (0 - send TERM only)" if FEATURE_KILL_REMOVED |
37 | //config: range 0 1024 |
38 | //config: default 0 |
39 | //config: depends on FEATURE_KILL_REMOVED |
40 | //config: help |
41 | //config: With nonzero setting, init sends TERM, forks, child waits N |
42 | //config: seconds, sends KILL and exits. Setting it too high is unwise |
43 | //config: (child will hang around for too long and could actually kill |
44 | //config: the wrong process!) |
45 | //config: |
46 | //config:config FEATURE_INIT_SCTTY |
47 | //config: bool "Run commands with leading dash with controlling tty" |
48 | //config: default y |
49 | //config: depends on INIT |
50 | //config: help |
51 | //config: If this option is enabled, init will try to give a controlling |
52 | //config: tty to any command which has leading hyphen (often it's "-/bin/sh"). |
53 | //config: More precisely, init will do "ioctl(STDIN_FILENO, TIOCSCTTY, 0)". |
54 | //config: If device attached to STDIN_FILENO can be a ctty but is not yet |
55 | //config: a ctty for other session, it will become this process' ctty. |
56 | //config: This is not the traditional init behavour, but is often what you want |
57 | //config: in an embedded system where the console is only accessed during |
58 | //config: development or for maintenance. |
59 | //config: NB: using cttyhack applet may work better. |
60 | //config: |
61 | //config:config FEATURE_INIT_SYSLOG |
62 | //config: bool "Enable init to write to syslog" |
63 | //config: default y |
64 | //config: depends on INIT |
65 | //config: |
66 | //config:config FEATURE_EXTRA_QUIET |
67 | //config: bool "Be _extra_ quiet on boot" |
68 | //config: default y |
69 | //config: depends on INIT |
70 | //config: help |
71 | //config: Prevent init from logging some messages to the console during boot. |
72 | //config: |
73 | //config:config FEATURE_INIT_COREDUMPS |
74 | //config: bool "Support dumping core for child processes (debugging only)" |
75 | //config: default y |
76 | //config: depends on INIT |
77 | //config: help |
78 | //config: If this option is enabled and the file /.init_enable_core |
79 | //config: exists, then init will call setrlimit() to allow unlimited |
80 | //config: core file sizes. If this option is disabled, processes |
81 | //config: will not generate any core files. |
82 | //config: |
83 | //config:config FEATURE_INITRD |
84 | //config: bool "Support running init from within an initrd (not initramfs)" |
85 | //config: default y |
86 | //config: depends on INIT |
87 | //config: help |
88 | //config: Legacy support for running init under the old-style initrd. Allows |
89 | //config: the name linuxrc to act as init, and it doesn't assume init is PID 1. |
90 | //config: |
91 | //config: This does not apply to initramfs, which runs /init as PID 1 and |
92 | //config: requires no special support. |
93 | //config: |
94 | //config:config INIT_TERMINAL_TYPE |
95 | //config: string "Initial terminal type" |
96 | //config: default "linux" |
97 | //config: depends on INIT |
98 | //config: help |
99 | //config: This is the initial value set by init for the TERM environment |
100 | //config: variable. This variable is used by programs which make use of |
101 | //config: extended terminal capabilities. |
102 | //config: |
103 | //config: Note that on Linux, init attempts to detect serial terminal and |
104 | //config: sets TERM to "vt102" if one is found. |
105 | |
106 | //applet:IF_INIT(APPLET(init, BB_DIR_SBIN, BB_SUID_DROP)) |
107 | //applet:IF_FEATURE_INITRD(APPLET_ODDNAME(linuxrc, init, BB_DIR_ROOT, BB_SUID_DROP, linuxrc)) |
108 | |
109 | //kbuild:lib-$(CONFIG_INIT) += init.o |
110 | |
111 | #define DEBUG_SEGV_HANDLER 0 |
112 | |
113 | #include "libbb.h" |
114 | #include <syslog.h> |
115 | #include <paths.h> |
116 | #include <sys/resource.h> |
117 | #ifdef __linux__ |
118 | # include <linux/vt.h> |
119 | # include <sys/sysinfo.h> |
120 | #endif |
121 | #include "reboot.h" /* reboot() constants */ |
122 | |
123 | #if DEBUG_SEGV_HANDLER |
124 | # undef _GNU_SOURCE |
125 | # define _GNU_SOURCE 1 |
126 | # undef __USE_GNU |
127 | # define __USE_GNU 1 |
128 | # include <execinfo.h> |
129 | # include <sys/ucontext.h> |
130 | #endif |
131 | |
132 | /* Used only for sanitizing purposes in set_sane_term() below. On systems where |
133 | * the baud rate is stored in a separate field, we can safely disable them. */ |
134 | #ifndef CBAUD |
135 | # define CBAUD 0 |
136 | # define CBAUDEX 0 |
137 | #endif |
138 | |
139 | /* Was a CONFIG_xxx option. A lot of people were building |
140 | * not fully functional init by switching it on! */ |
141 | #define DEBUG_INIT 0 |
142 | |
143 | #define CONSOLE_NAME_SIZE 32 |
144 | |
145 | /* Default sysinit script. */ |
146 | #ifndef INIT_SCRIPT |
147 | # define INIT_SCRIPT "/etc/init.d/rcS" |
148 | #endif |
149 | |
150 | /* Each type of actions can appear many times. They will be |
151 | * handled in order. RESTART is an exception, only 1st is used. |
152 | */ |
153 | /* Start these actions first and wait for completion */ |
154 | #define SYSINIT 0x01 |
155 | /* Start these after SYSINIT and wait for completion */ |
156 | #define WAIT 0x02 |
157 | /* Start these after WAIT and *dont* wait for completion */ |
158 | #define ONCE 0x04 |
159 | /* |
160 | * NB: while SYSINIT/WAIT/ONCE are being processed, |
161 | * SIGHUP ("reread /etc/inittab") will be processed only after |
162 | * each group of actions. If new inittab adds, say, a SYSINIT action, |
163 | * it will not be run, since init is already "past SYSINIT stage". |
164 | */ |
165 | /* Start these after ONCE are started, restart on exit */ |
166 | #define RESPAWN 0x08 |
167 | /* Like RESPAWN, but wait for <Enter> to be pressed on tty */ |
168 | #define ASKFIRST 0x10 |
169 | /* |
170 | * Start these on SIGINT, and wait for completion. |
171 | * Then go back to respawning RESPAWN and ASKFIRST actions. |
172 | * NB: kernel sends SIGINT to us if Ctrl-Alt-Del was pressed. |
173 | */ |
174 | #define CTRLALTDEL 0x20 |
175 | /* |
176 | * Start these before killing all processes in preparation for |
177 | * running RESTART actions or doing low-level halt/reboot/poweroff |
178 | * (initiated by SIGUSR1/SIGTERM/SIGUSR2). |
179 | * Wait for completion before proceeding. |
180 | */ |
181 | #define SHUTDOWN 0x40 |
182 | /* |
183 | * exec() on SIGQUIT. SHUTDOWN actions are started and waited for, |
184 | * then all processes are killed, then init exec's 1st RESTART action, |
185 | * replacing itself by it. If no RESTART action specified, |
186 | * SIGQUIT has no effect. |
187 | */ |
188 | #define RESTART 0x80 |
189 | |
190 | |
191 | /* A linked list of init_actions, to be read from inittab */ |
192 | struct init_action { |
193 | struct init_action *next; |
194 | pid_t pid; |
195 | uint8_t action_type; |
196 | char terminal[CONSOLE_NAME_SIZE]; |
197 | char command[1]; |
198 | }; |
199 | |
200 | static struct init_action *init_action_list = NULL; |
201 | |
202 | static const char *log_console = VC_5; |
203 | |
204 | enum { |
205 | L_LOG = 0x1, |
206 | L_CONSOLE = 0x2, |
207 | }; |
208 | |
209 | /* Print a message to the specified device. |
210 | * "where" may be bitwise-or'd from L_LOG | L_CONSOLE |
211 | * NB: careful, we can be called after vfork! |
212 | */ |
213 | #define dbg_message(...) do { if (DEBUG_INIT) message(__VA_ARGS__); } while (0) |
214 | static void message(int where, const char *fmt, ...) |
215 | __attribute__ ((format(printf, 2, 3))); |
216 | static void message(int where, const char *fmt, ...) |
217 | { |
218 | va_list arguments; |
219 | unsigned l; |
220 | char msg[128]; |
221 | |
222 | msg[0] = '\r'; |
223 | va_start(arguments, fmt); |
224 | l = 1 + vsnprintf(msg + 1, sizeof(msg) - 2, fmt, arguments); |
225 | if (l > sizeof(msg) - 2) |
226 | l = sizeof(msg) - 2; |
227 | va_end(arguments); |
228 | |
229 | #if ENABLE_FEATURE_INIT_SYSLOG |
230 | msg[l] = '\0'; |
231 | if (where & L_LOG) { |
232 | /* Log the message to syslogd */ |
233 | openlog(applet_name, 0, LOG_DAEMON); |
234 | /* don't print "\r" */ |
235 | syslog(LOG_INFO, "%s", msg + 1); |
236 | closelog(); |
237 | } |
238 | msg[l++] = '\n'; |
239 | msg[l] = '\0'; |
240 | #else |
241 | { |
242 | static int log_fd = -1; |
243 | |
244 | msg[l++] = '\n'; |
245 | msg[l] = '\0'; |
246 | /* Take full control of the log tty, and never close it. |
247 | * It's mine, all mine! Muhahahaha! */ |
248 | if (log_fd < 0) { |
249 | if (!log_console) { |
250 | log_fd = STDERR_FILENO; |
251 | } else { |
252 | log_fd = device_open(log_console, O_WRONLY | O_NONBLOCK | O_NOCTTY); |
253 | if (log_fd < 0) { |
254 | bb_error_msg("can't log to %s", log_console); |
255 | where = L_CONSOLE; |
256 | } else { |
257 | close_on_exec_on(log_fd); |
258 | } |
259 | } |
260 | } |
261 | if (where & L_LOG) { |
262 | full_write(log_fd, msg, l); |
263 | if (log_fd == STDERR_FILENO) |
264 | return; /* don't print dup messages */ |
265 | } |
266 | } |
267 | #endif |
268 | |
269 | if (where & L_CONSOLE) { |
270 | /* Send console messages to console so people will see them. */ |
271 | full_write(STDERR_FILENO, msg, l); |
272 | } |
273 | } |
274 | |
275 | static void console_init(void) |
276 | { |
277 | #ifdef VT_OPENQRY |
278 | int vtno; |
279 | #endif |
280 | char *s; |
281 | |
282 | s = getenv("CONSOLE"); |
283 | if (!s) |
284 | s = getenv("console"); |
285 | if (s) { |
286 | int fd = open(s, O_RDWR | O_NONBLOCK | O_NOCTTY); |
287 | if (fd >= 0) { |
288 | dup2(fd, STDIN_FILENO); |
289 | dup2(fd, STDOUT_FILENO); |
290 | xmove_fd(fd, STDERR_FILENO); |
291 | } |
292 | dbg_message(L_LOG, "console='%s'", s); |
293 | } else { |
294 | /* Make sure fd 0,1,2 are not closed |
295 | * (so that they won't be used by future opens) */ |
296 | bb_sanitize_stdio(); |
297 | // Users report problems |
298 | // /* Make sure init can't be blocked by writing to stderr */ |
299 | // fcntl(STDERR_FILENO, F_SETFL, fcntl(STDERR_FILENO, F_GETFL) | O_NONBLOCK); |
300 | } |
301 | |
302 | s = getenv("TERM"); |
303 | #ifdef VT_OPENQRY |
304 | if (ioctl(STDIN_FILENO, VT_OPENQRY, &vtno) != 0) { |
305 | /* Not a linux terminal, probably serial console. |
306 | * Force the TERM setting to vt102 |
307 | * if TERM is set to linux (the default) */ |
308 | if (!s || strcmp(s, "linux") == 0) |
309 | putenv((char*)"TERM=vt102"); |
310 | if (!ENABLE_FEATURE_INIT_SYSLOG) |
311 | log_console = NULL; |
312 | } else |
313 | #endif |
314 | if (!s) |
315 | putenv((char*)"TERM=" CONFIG_INIT_TERMINAL_TYPE); |
316 | } |
317 | |
318 | /* Set terminal settings to reasonable defaults. |
319 | * NB: careful, we can be called after vfork! */ |
320 | static void set_sane_term(void) |
321 | { |
322 | struct termios tty; |
323 | |
324 | tcgetattr(STDIN_FILENO, &tty); |
325 | |
326 | /* set control chars */ |
327 | tty.c_cc[VINTR] = 3; /* C-c */ |
328 | tty.c_cc[VQUIT] = 28; /* C-\ */ |
329 | tty.c_cc[VERASE] = 127; /* C-? */ |
330 | tty.c_cc[VKILL] = 21; /* C-u */ |
331 | tty.c_cc[VEOF] = 4; /* C-d */ |
332 | tty.c_cc[VSTART] = 17; /* C-q */ |
333 | tty.c_cc[VSTOP] = 19; /* C-s */ |
334 | tty.c_cc[VSUSP] = 26; /* C-z */ |
335 | |
336 | #ifdef __linux__ |
337 | /* use line discipline 0 */ |
338 | tty.c_line = 0; |
339 | #endif |
340 | |
341 | /* Make it be sane */ |
342 | #ifndef CRTSCTS |
343 | # define CRTSCTS 0 |
344 | #endif |
345 | /* added CRTSCTS to fix Debian bug 528560 */ |
346 | tty.c_cflag &= CBAUD | CBAUDEX | CSIZE | CSTOPB | PARENB | PARODD | CRTSCTS; |
347 | tty.c_cflag |= CREAD | HUPCL | CLOCAL; |
348 | |
349 | /* input modes */ |
350 | tty.c_iflag = ICRNL | IXON | IXOFF; |
351 | |
352 | /* output modes */ |
353 | tty.c_oflag = OPOST | ONLCR; |
354 | |
355 | /* local modes */ |
356 | tty.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN; |
357 | |
358 | tcsetattr_stdin_TCSANOW(&tty); |
359 | } |
360 | |
361 | /* Open the new terminal device. |
362 | * NB: careful, we can be called after vfork! */ |
363 | static int open_stdio_to_tty(const char* tty_name) |
364 | { |
365 | /* empty tty_name means "use init's tty", else... */ |
366 | if (tty_name[0]) { |
367 | int fd; |
368 | |
369 | close(STDIN_FILENO); |
370 | /* fd can be only < 0 or 0: */ |
371 | fd = device_open(tty_name, O_RDWR); |
372 | if (fd) { |
373 | message(L_LOG | L_CONSOLE, "can't open %s: %s", |
374 | tty_name, strerror(errno)); |
375 | return 0; /* failure */ |
376 | } |
377 | dup2(STDIN_FILENO, STDOUT_FILENO); |
378 | dup2(STDIN_FILENO, STDERR_FILENO); |
379 | } |
380 | set_sane_term(); |
381 | return 1; /* success */ |
382 | } |
383 | |
384 | static void reset_sighandlers_and_unblock_sigs(void) |
385 | { |
386 | bb_signals(0 |
387 | + (1 << SIGUSR1) |
388 | + (1 << SIGUSR2) |
389 | + (1 << SIGTERM) |
390 | + (1 << SIGQUIT) |
391 | + (1 << SIGINT) |
392 | + (1 << SIGHUP) |
393 | + (1 << SIGTSTP) |
394 | + (1 << SIGSTOP) |
395 | , SIG_DFL); |
396 | sigprocmask_allsigs(SIG_UNBLOCK); |
397 | } |
398 | |
399 | /* Wrapper around exec: |
400 | * Takes string. |
401 | * If chars like '>' detected, execs '[-]/bin/sh -c "exec ......."'. |
402 | * Otherwise splits words on whitespace, deals with leading dash, |
403 | * and uses plain exec(). |
404 | * NB: careful, we can be called after vfork! |
405 | */ |
406 | static void init_exec(const char *command) |
407 | { |
408 | /* +8 allows to write VLA sizes below more efficiently: */ |
409 | unsigned command_size = strlen(command) + 8; |
410 | /* strlen(command) + strlen("exec ")+1: */ |
411 | char buf[command_size]; |
412 | /* strlen(command) / 2 + 4: */ |
413 | char *cmd[command_size / 2]; |
414 | int dash; |
415 | |
416 | dash = (command[0] == '-' /* maybe? && command[1] == '/' */); |
417 | command += dash; |
418 | |
419 | /* See if any special /bin/sh requiring characters are present */ |
420 | if (strpbrk(command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) { |
421 | sprintf(buf, "exec %s", command); /* excluding "-" */ |
422 | /* NB: LIBBB_DEFAULT_LOGIN_SHELL define has leading dash */ |
423 | cmd[0] = (char*)(LIBBB_DEFAULT_LOGIN_SHELL + !dash); |
424 | cmd[1] = (char*)"-c"; |
425 | cmd[2] = buf; |
426 | cmd[3] = NULL; |
427 | command = LIBBB_DEFAULT_LOGIN_SHELL + 1; |
428 | } else { |
429 | /* Convert command (char*) into cmd (char**, one word per string) */ |
430 | char *word, *next; |
431 | int i = 0; |
432 | next = strcpy(buf, command - dash); /* command including "-" */ |
433 | command = next + dash; |
434 | while ((word = strsep(&next, " \t")) != NULL) { |
435 | if (*word != '\0') { /* not two spaces/tabs together? */ |
436 | cmd[i] = word; |
437 | i++; |
438 | } |
439 | } |
440 | cmd[i] = NULL; |
441 | } |
442 | /* If we saw leading "-", it is interactive shell. |
443 | * Try harder to give it a controlling tty. |
444 | */ |
445 | if (ENABLE_FEATURE_INIT_SCTTY && dash) { |
446 | /* _Attempt_ to make stdin a controlling tty. */ |
447 | ioctl(STDIN_FILENO, TIOCSCTTY, 0 /*only try, don't steal*/); |
448 | } |
449 | /* Here command never contains the dash, cmd[0] might */ |
450 | BB_EXECVP(command, cmd); |
451 | message(L_LOG | L_CONSOLE, "can't run '%s': %s", command, strerror(errno)); |
452 | /* returns if execvp fails */ |
453 | } |
454 | |
455 | /* Used only by run_actions */ |
456 | static pid_t run(const struct init_action *a) |
457 | { |
458 | pid_t pid; |
459 | |
460 | /* Careful: don't be affected by a signal in vforked child */ |
461 | sigprocmask_allsigs(SIG_BLOCK); |
462 | if (BB_MMU && (a->action_type & ASKFIRST)) |
463 | pid = fork(); |
464 | else |
465 | pid = vfork(); |
466 | if (pid < 0) |
467 | message(L_LOG | L_CONSOLE, "can't fork"); |
468 | if (pid) { |
469 | sigprocmask_allsigs(SIG_UNBLOCK); |
470 | return pid; /* Parent or error */ |
471 | } |
472 | |
473 | /* Child */ |
474 | |
475 | /* Reset signal handlers that were set by the parent process */ |
476 | reset_sighandlers_and_unblock_sigs(); |
477 | |
478 | /* Create a new session and make ourself the process group leader */ |
479 | setsid(); |
480 | |
481 | /* Open the new terminal device */ |
482 | if (!open_stdio_to_tty(a->terminal)) |
483 | _exit(EXIT_FAILURE); |
484 | |
485 | /* NB: on NOMMU we can't wait for input in child, so |
486 | * "askfirst" will work the same as "respawn". */ |
487 | if (BB_MMU && (a->action_type & ASKFIRST)) { |
488 | static const char press_enter[] ALIGN1 = |
489 | #ifdef CUSTOMIZED_BANNER |
490 | #include CUSTOMIZED_BANNER |
491 | #endif |
492 | "\nPlease press Enter to activate this console. "; |
493 | char c; |
494 | /* |
495 | * Save memory by not exec-ing anything large (like a shell) |
496 | * before the user wants it. This is critical if swap is not |
497 | * enabled and the system has low memory. Generally this will |
498 | * be run on the second virtual console, and the first will |
499 | * be allowed to start a shell or whatever an init script |
500 | * specifies. |
501 | */ |
502 | dbg_message(L_LOG, "waiting for enter to start '%s'" |
503 | "(pid %d, tty '%s')\n", |
504 | a->command, getpid(), a->terminal); |
505 | full_write(STDOUT_FILENO, press_enter, sizeof(press_enter) - 1); |
506 | while (safe_read(STDIN_FILENO, &c, 1) == 1 && c != '\n') |
507 | continue; |
508 | } |
509 | |
510 | /* |
511 | * When a file named /.init_enable_core exists, setrlimit is called |
512 | * before processes are spawned to set core file size as unlimited. |
513 | * This is for debugging only. Don't use this is production, unless |
514 | * you want core dumps lying about.... |
515 | */ |
516 | if (ENABLE_FEATURE_INIT_COREDUMPS) { |
517 | if (access("/.init_enable_core", F_OK) == 0) { |
518 | struct rlimit limit; |
519 | limit.rlim_cur = RLIM_INFINITY; |
520 | limit.rlim_max = RLIM_INFINITY; |
521 | setrlimit(RLIMIT_CORE, &limit); |
522 | } |
523 | } |
524 | |
525 | /* Log the process name and args */ |
526 | message(L_LOG, "starting pid %d, tty '%s': '%s'", |
527 | getpid(), a->terminal, a->command); |
528 | |
529 | /* Now run it. The new program will take over this PID, |
530 | * so nothing further in init.c should be run. */ |
531 | init_exec(a->command); |
532 | /* We're still here? Some error happened. */ |
533 | _exit(-1); |
534 | } |
535 | |
536 | static struct init_action *mark_terminated(pid_t pid) |
537 | { |
538 | struct init_action *a; |
539 | |
540 | if (pid > 0) { |
541 | update_utmp(pid, DEAD_PROCESS, |
542 | /*tty_name:*/ NULL, |
543 | /*username:*/ NULL, |
544 | /*hostname:*/ NULL |
545 | ); |
546 | for (a = init_action_list; a; a = a->next) { |
547 | if (a->pid == pid) { |
548 | a->pid = 0; |
549 | return a; |
550 | } |
551 | } |
552 | } |
553 | return NULL; |
554 | } |
555 | |
556 | static void waitfor(pid_t pid) |
557 | { |
558 | /* waitfor(run(x)): protect against failed fork inside run() */ |
559 | if (pid <= 0) |
560 | return; |
561 | |
562 | /* Wait for any child (prevent zombies from exiting orphaned processes) |
563 | * but exit the loop only when specified one has exited. */ |
564 | while (1) { |
565 | pid_t wpid = wait(NULL); |
566 | mark_terminated(wpid); |
567 | /* Unsafe. SIGTSTP handler might have wait'ed it already */ |
568 | /*if (wpid == pid) break;*/ |
569 | /* More reliable: */ |
570 | if (kill(pid, 0)) |
571 | break; |
572 | } |
573 | } |
574 | |
575 | /* Run all commands of a particular type */ |
576 | static void run_actions(int action_type) |
577 | { |
578 | struct init_action *a; |
579 | |
580 | for (a = init_action_list; a; a = a->next) { |
581 | if (!(a->action_type & action_type)) |
582 | continue; |
583 | |
584 | if (a->action_type & (SYSINIT | WAIT | ONCE | CTRLALTDEL | SHUTDOWN)) { |
585 | pid_t pid = run(a); |
586 | if (a->action_type & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN)) |
587 | waitfor(pid); |
588 | } |
589 | if (a->action_type & (RESPAWN | ASKFIRST)) { |
590 | /* Only run stuff with pid == 0. If pid != 0, |
591 | * it is already running |
592 | */ |
593 | if (a->pid == 0) |
594 | a->pid = run(a); |
595 | } |
596 | } |
597 | } |
598 | |
599 | static void new_init_action(uint8_t action_type, const char *command, const char *cons) |
600 | { |
601 | struct init_action *a, **nextp; |
602 | |
603 | /* Scenario: |
604 | * old inittab: |
605 | * ::shutdown:umount -a -r |
606 | * ::shutdown:swapoff -a |
607 | * new inittab: |
608 | * ::shutdown:swapoff -a |
609 | * ::shutdown:umount -a -r |
610 | * On reload, we must ensure entries end up in correct order. |
611 | * To achieve that, if we find a matching entry, we move it |
612 | * to the end. |
613 | */ |
614 | nextp = &init_action_list; |
615 | while ((a = *nextp) != NULL) { |
616 | /* Don't enter action if it's already in the list. |
617 | * This prevents losing running RESPAWNs. |
618 | */ |
619 | if (strcmp(a->command, command) == 0 |
620 | && strcmp(a->terminal, cons) == 0 |
621 | ) { |
622 | /* Remove from list */ |
623 | *nextp = a->next; |
624 | /* Find the end of the list */ |
625 | while (*nextp != NULL) |
626 | nextp = &(*nextp)->next; |
627 | a->next = NULL; |
628 | goto append; |
629 | } |
630 | nextp = &a->next; |
631 | } |
632 | |
633 | a = xzalloc(sizeof(*a) + strlen(command)); |
634 | |
635 | /* Append to the end of the list */ |
636 | append: |
637 | *nextp = a; |
638 | a->action_type = action_type; |
639 | strcpy(a->command, command); |
640 | safe_strncpy(a->terminal, cons, sizeof(a->terminal)); |
641 | dbg_message(L_LOG | L_CONSOLE, "command='%s' action=%x tty='%s'\n", |
642 | a->command, a->action_type, a->terminal); |
643 | } |
644 | |
645 | /* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined, |
646 | * then parse_inittab() simply adds in some default |
647 | * actions (i.e., runs INIT_SCRIPT and then starts a pair |
648 | * of "askfirst" shells). If CONFIG_FEATURE_USE_INITTAB |
649 | * _is_ defined, but /etc/inittab is missing, this |
650 | * results in the same set of default behaviors. |
651 | */ |
652 | static void parse_inittab(void) |
653 | { |
654 | #if ENABLE_FEATURE_USE_INITTAB |
655 | char *token[4]; |
656 | parser_t *parser = config_open2("/etc/inittab", fopen_for_read); |
657 | |
658 | if (parser == NULL) |
659 | #endif |
660 | { |
661 | /* No inittab file - set up some default behavior */ |
662 | /* Sysinit */ |
663 | new_init_action(SYSINIT, INIT_SCRIPT, ""); |
664 | /* Askfirst shell on tty1-4 */ |
665 | new_init_action(ASKFIRST, bb_default_login_shell, ""); |
666 | //TODO: VC_1 instead of ""? "" is console -> ctty problems -> angry users |
667 | new_init_action(ASKFIRST, bb_default_login_shell, VC_2); |
668 | new_init_action(ASKFIRST, bb_default_login_shell, VC_3); |
669 | new_init_action(ASKFIRST, bb_default_login_shell, VC_4); |
670 | /* Reboot on Ctrl-Alt-Del */ |
671 | new_init_action(CTRLALTDEL, "reboot", ""); |
672 | /* Umount all filesystems on halt/reboot */ |
673 | new_init_action(SHUTDOWN, "umount -a -r", ""); |
674 | /* Swapoff on halt/reboot */ |
675 | new_init_action(SHUTDOWN, "swapoff -a", ""); |
676 | /* Restart init when a QUIT is received */ |
677 | new_init_action(RESTART, "init", ""); |
678 | return; |
679 | } |
680 | |
681 | #if ENABLE_FEATURE_USE_INITTAB |
682 | /* optional_tty:ignored_runlevel:action:command |
683 | * Delims are not to be collapsed and need exactly 4 tokens |
684 | */ |
685 | while (config_read(parser, token, 4, 0, "#:", |
686 | PARSE_NORMAL & ~(PARSE_TRIM | PARSE_COLLAPSE))) { |
687 | /* order must correspond to SYSINIT..RESTART constants */ |
688 | static const char actions[] ALIGN1 = |
689 | "sysinit\0""wait\0""once\0""respawn\0""askfirst\0" |
690 | "ctrlaltdel\0""shutdown\0""restart\0"; |
691 | int action; |
692 | char *tty = token[0]; |
693 | |
694 | if (!token[3]) /* less than 4 tokens */ |
695 | goto bad_entry; |
696 | action = index_in_strings(actions, token[2]); |
697 | if (action < 0 || !token[3][0]) /* token[3]: command */ |
698 | goto bad_entry; |
699 | /* turn .*TTY -> /dev/TTY */ |
700 | if (tty[0]) { |
701 | tty = concat_path_file("/dev/", skip_dev_pfx(tty)); |
702 | } |
703 | new_init_action(1 << action, token[3], tty); |
704 | if (tty[0]) |
705 | free(tty); |
706 | continue; |
707 | bad_entry: |
708 | message(L_LOG | L_CONSOLE, "Bad inittab entry at line %d", |
709 | parser->lineno); |
710 | } |
711 | config_close(parser); |
712 | #endif |
713 | } |
714 | |
715 | static void pause_and_low_level_reboot(unsigned magic) NORETURN; |
716 | static void pause_and_low_level_reboot(unsigned magic) |
717 | { |
718 | pid_t pid; |
719 | |
720 | /* Allow time for last message to reach serial console, etc */ |
721 | sleep(1); |
722 | |
723 | /* We have to fork here, since the kernel calls do_exit(EXIT_SUCCESS) |
724 | * in linux/kernel/sys.c, which can cause the machine to panic when |
725 | * the init process exits... */ |
726 | pid = vfork(); |
727 | if (pid == 0) { /* child */ |
728 | reboot(magic); |
729 | _exit(EXIT_SUCCESS); |
730 | } |
731 | while (1) |
732 | sleep(1); |
733 | } |
734 | |
735 | static void run_shutdown_and_kill_processes(void) |
736 | { |
737 | /* Run everything to be run at "shutdown". This is done _prior_ |
738 | * to killing everything, in case people wish to use scripts to |
739 | * shut things down gracefully... */ |
740 | run_actions(SHUTDOWN); |
741 | |
742 | message(L_CONSOLE | L_LOG, "The system is going down NOW!"); |
743 | |
744 | /* Send signals to every process _except_ pid 1 */ |
745 | kill(-1, SIGTERM); |
746 | message(L_CONSOLE | L_LOG, "Sent SIG%s to all processes", "TERM"); |
747 | sync(); |
748 | sleep(1); |
749 | |
750 | kill(-1, SIGKILL); |
751 | message(L_CONSOLE, "Sent SIG%s to all processes", "KILL"); |
752 | sync(); |
753 | /*sleep(1); - callers take care about making a pause */ |
754 | } |
755 | |
756 | /* Signal handling by init: |
757 | * |
758 | * For process with PID==1, on entry kernel sets all signals to SIG_DFL |
759 | * and unmasks all signals. However, for process with PID==1, |
760 | * default action (SIG_DFL) on any signal is to ignore it, |
761 | * even for special signals SIGKILL and SIGCONT. |
762 | * Also, any signal can be caught or blocked. |
763 | * (but SIGSTOP is still handled specially, at least in 2.6.20) |
764 | * |
765 | * We install two kinds of handlers, "immediate" and "delayed". |
766 | * |
767 | * Immediate handlers execute at any time, even while, say, sysinit |
768 | * is running. |
769 | * |
770 | * Delayed handlers just set a flag variable. The variable is checked |
771 | * in the main loop and acted upon. |
772 | * |
773 | * halt/poweroff/reboot and restart have immediate handlers. |
774 | * They only traverse linked list of struct action's, never modify it, |
775 | * this should be safe to do even in signal handler. Also they |
776 | * never return. |
777 | * |
778 | * SIGSTOP and SIGTSTP have immediate handlers. They just wait |
779 | * for SIGCONT to happen. |
780 | * |
781 | * SIGHUP has a delayed handler, because modifying linked list |
782 | * of struct action's from a signal handler while it is manipulated |
783 | * by the program may be disastrous. |
784 | * |
785 | * Ctrl-Alt-Del has a delayed handler. Not a must, but allowing |
786 | * it to happen even somewhere inside "sysinit" would be a bit awkward. |
787 | * |
788 | * There is a tiny probability that SIGHUP and Ctrl-Alt-Del will collide |
789 | * and only one will be remembered and acted upon. |
790 | */ |
791 | |
792 | /* The SIGPWR/SIGUSR[12]/SIGTERM handler */ |
793 | static void halt_reboot_pwoff(int sig) NORETURN; |
794 | static void halt_reboot_pwoff(int sig) |
795 | { |
796 | const char *m; |
797 | unsigned rb; |
798 | |
799 | /* We may call run() and it unmasks signals, |
800 | * including the one masked inside this signal handler. |
801 | * Testcase which would start multiple reboot scripts: |
802 | * while true; do reboot; done |
803 | * Preventing it: |
804 | */ |
805 | reset_sighandlers_and_unblock_sigs(); |
806 | |
807 | run_shutdown_and_kill_processes(); |
808 | |
809 | m = "halt"; |
810 | rb = RB_HALT_SYSTEM; |
811 | if (sig == SIGTERM) { |
812 | m = "reboot"; |
813 | rb = RB_AUTOBOOT; |
814 | } else if (sig == SIGUSR2) { |
815 | m = "poweroff"; |
816 | rb = RB_POWER_OFF; |
817 | } |
818 | message(L_CONSOLE, "Requesting system %s", m); |
819 | pause_and_low_level_reboot(rb); |
820 | /* not reached */ |
821 | } |
822 | |
823 | /* Handler for QUIT - exec "restart" action, |
824 | * else (no such action defined) do nothing */ |
825 | static void restart_handler(int sig UNUSED_PARAM) |
826 | { |
827 | struct init_action *a; |
828 | |
829 | for (a = init_action_list; a; a = a->next) { |
830 | if (!(a->action_type & RESTART)) |
831 | continue; |
832 | |
833 | /* Starting from here, we won't return. |
834 | * Thus don't need to worry about preserving errno |
835 | * and such. |
836 | */ |
837 | |
838 | reset_sighandlers_and_unblock_sigs(); |
839 | |
840 | run_shutdown_and_kill_processes(); |
841 | |
842 | #ifdef RB_ENABLE_CAD |
843 | /* Allow Ctrl-Alt-Del to reboot the system. |
844 | * This is how kernel sets it up for init, we follow suit. |
845 | */ |
846 | reboot(RB_ENABLE_CAD); /* misnomer */ |
847 | #endif |
848 | |
849 | if (open_stdio_to_tty(a->terminal)) { |
850 | dbg_message(L_CONSOLE, "Trying to re-exec %s", a->command); |
851 | /* Theoretically should be safe. |
852 | * But in practice, kernel bugs may leave |
853 | * unkillable processes, and wait() may block forever. |
854 | * Oh well. Hoping "new" init won't be too surprised |
855 | * by having children it didn't create. |
856 | */ |
857 | //while (wait(NULL) > 0) |
858 | // continue; |
859 | init_exec(a->command); |
860 | } |
861 | /* Open or exec failed */ |
862 | pause_and_low_level_reboot(RB_HALT_SYSTEM); |
863 | /* not reached */ |
864 | } |
865 | } |
866 | |
867 | /* The SIGSTOP/SIGTSTP handler |
868 | * NB: inside it, all signals except SIGCONT are masked |
869 | * via appropriate setup in sigaction(). |
870 | */ |
871 | static void stop_handler(int sig UNUSED_PARAM) |
872 | { |
873 | smallint saved_bb_got_signal; |
874 | int saved_errno; |
875 | |
876 | saved_bb_got_signal = bb_got_signal; |
877 | saved_errno = errno; |
878 | signal(SIGCONT, record_signo); |
879 | |
880 | while (1) { |
881 | pid_t wpid; |
882 | |
883 | if (bb_got_signal == SIGCONT) |
884 | break; |
885 | /* NB: this can accidentally wait() for a process |
886 | * which we waitfor() elsewhere! waitfor() must have |
887 | * code which is resilient against this. |
888 | */ |
889 | wpid = wait_any_nohang(NULL); |
890 | mark_terminated(wpid); |
891 | sleep(1); |
892 | } |
893 | |
894 | signal(SIGCONT, SIG_DFL); |
895 | errno = saved_errno; |
896 | bb_got_signal = saved_bb_got_signal; |
897 | } |
898 | |
899 | #if ENABLE_FEATURE_USE_INITTAB |
900 | static void reload_inittab(void) |
901 | { |
902 | struct init_action *a, **nextp; |
903 | |
904 | message(L_LOG, "reloading /etc/inittab"); |
905 | |
906 | /* Disable old entries */ |
907 | for (a = init_action_list; a; a = a->next) |
908 | a->action_type = 0; |
909 | |
910 | /* Append new entries, or modify existing entries |
911 | * (incl. setting a->action_type) if cmd and device name |
912 | * match new ones. End result: only entries with |
913 | * a->action_type == 0 are stale. |
914 | */ |
915 | parse_inittab(); |
916 | |
917 | #if ENABLE_FEATURE_KILL_REMOVED |
918 | /* Kill stale entries */ |
919 | /* Be nice and send SIGTERM first */ |
920 | for (a = init_action_list; a; a = a->next) |
921 | if (a->action_type == 0 && a->pid != 0) |
922 | kill(a->pid, SIGTERM); |
923 | if (CONFIG_FEATURE_KILL_DELAY) { |
924 | /* NB: parent will wait in NOMMU case */ |
925 | if ((BB_MMU ? fork() : vfork()) == 0) { /* child */ |
926 | sleep(CONFIG_FEATURE_KILL_DELAY); |
927 | for (a = init_action_list; a; a = a->next) |
928 | if (a->action_type == 0 && a->pid != 0) |
929 | kill(a->pid, SIGKILL); |
930 | _exit(EXIT_SUCCESS); |
931 | } |
932 | } |
933 | #endif |
934 | |
935 | /* Remove stale entries and SYSINIT entries. |
936 | * We never rerun SYSINIT entries anyway, |
937 | * removing them too saves a few bytes |
938 | */ |
939 | nextp = &init_action_list; |
940 | while ((a = *nextp) != NULL) { |
941 | /* |
942 | * Why pid == 0 check? |
943 | * Process can be removed from inittab and added *later*. |
944 | * If we delete its entry but process still runs, |
945 | * duplicate is spawned when the entry is re-added. |
946 | */ |
947 | if ((a->action_type & ~SYSINIT) == 0 && a->pid == 0) { |
948 | *nextp = a->next; |
949 | free(a); |
950 | } else { |
951 | nextp = &a->next; |
952 | } |
953 | } |
954 | |
955 | /* Not needed: */ |
956 | /* run_actions(RESPAWN | ASKFIRST); */ |
957 | /* - we return to main loop, which does this automagically */ |
958 | } |
959 | #endif |
960 | |
961 | static int check_delayed_sigs(void) |
962 | { |
963 | int sigs_seen = 0; |
964 | |
965 | while (1) { |
966 | smallint sig = bb_got_signal; |
967 | |
968 | if (!sig) |
969 | return sigs_seen; |
970 | bb_got_signal = 0; |
971 | sigs_seen = 1; |
972 | #if ENABLE_FEATURE_USE_INITTAB |
973 | if (sig == SIGHUP) |
974 | reload_inittab(); |
975 | #endif |
976 | if (sig == SIGINT) |
977 | run_actions(CTRLALTDEL); |
978 | } |
979 | } |
980 | |
981 | #if DEBUG_SEGV_HANDLER |
982 | static |
983 | void handle_sigsegv(int sig, siginfo_t *info, void *ucontext) |
984 | { |
985 | long ip; |
986 | ucontext_t *uc; |
987 | |
988 | uc = ucontext; |
989 | ip = uc->uc_mcontext.gregs[REG_EIP]; |
990 | fdprintf(2, "signal:%d address:0x%lx ip:0x%lx\n", |
991 | sig, |
992 | /* this is void*, but using %p would print "(null)" |
993 | * even for ptrs which are not exactly 0, but, say, 0x123: |
994 | */ |
995 | (long)info->si_addr, |
996 | ip); |
997 | { |
998 | /* glibc extension */ |
999 | void *array[50]; |
1000 | int size; |
1001 | size = backtrace(array, 50); |
1002 | backtrace_symbols_fd(array, size, 2); |
1003 | } |
1004 | for (;;) sleep(9999); |
1005 | } |
1006 | #endif |
1007 | |
1008 | int init_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
1009 | int init_main(int argc UNUSED_PARAM, char **argv) |
1010 | { |
1011 | if (argv[1] && strcmp(argv[1], "-q") == 0) { |
1012 | return kill(1, SIGHUP); |
1013 | } |
1014 | |
1015 | #if DEBUG_SEGV_HANDLER |
1016 | { |
1017 | struct sigaction sa; |
1018 | memset(&sa, 0, sizeof(sa)); |
1019 | sa.sa_sigaction = handle_sigsegv; |
1020 | sa.sa_flags = SA_SIGINFO; |
1021 | sigaction(SIGSEGV, &sa, NULL); |
1022 | sigaction(SIGILL, &sa, NULL); |
1023 | sigaction(SIGFPE, &sa, NULL); |
1024 | sigaction(SIGBUS, &sa, NULL); |
1025 | } |
1026 | #endif |
1027 | |
1028 | if (!DEBUG_INIT) { |
1029 | /* Expect to be invoked as init with PID=1 or be invoked as linuxrc */ |
1030 | if (getpid() != 1 |
1031 | && (!ENABLE_FEATURE_INITRD || applet_name[0] != 'l') /* not linuxrc? */ |
1032 | ) { |
1033 | bb_error_msg_and_die("must be run as PID 1"); |
1034 | } |
1035 | #ifdef RB_DISABLE_CAD |
1036 | /* Turn off rebooting via CTL-ALT-DEL - we get a |
1037 | * SIGINT on CAD so we can shut things down gracefully... */ |
1038 | reboot(RB_DISABLE_CAD); /* misnomer */ |
1039 | #endif |
1040 | } |
1041 | |
1042 | /* If, say, xmalloc would ever die, we don't want to oops kernel |
1043 | * by exiting. |
1044 | * NB: we set die_sleep *after* PID 1 check and bb_show_usage. |
1045 | * Otherwise, for example, "init u" ("please rexec yourself" |
1046 | * command for sysvinit) will show help text (which isn't too bad), |
1047 | * *and sleep forever* (which is bad!) |
1048 | */ |
1049 | die_sleep = 30 * 24*60*60; |
1050 | |
1051 | /* Figure out where the default console should be */ |
1052 | console_init(); |
1053 | set_sane_term(); |
1054 | xchdir("/"); |
1055 | setsid(); |
1056 | |
1057 | /* Make sure environs is set to something sane */ |
1058 | putenv((char *) "HOME=/"); |
1059 | putenv((char *) bb_PATH_root_path); |
1060 | putenv((char *) "SHELL=/bin/sh"); |
1061 | putenv((char *) "USER=root"); /* needed? why? */ |
1062 | |
1063 | if (argv[1]) |
1064 | xsetenv("RUNLEVEL", argv[1]); |
1065 | |
1066 | #if !ENABLE_FEATURE_EXTRA_QUIET |
1067 | /* Hello world */ |
1068 | message(L_CONSOLE | L_LOG, "init started: %s", bb_banner); |
1069 | #endif |
1070 | |
1071 | #if 0 |
1072 | /* It's 2013, does anyone really still depend on this? */ |
1073 | /* If you do, consider adding swapon to sysinot actions then! */ |
1074 | /* struct sysinfo is linux-specific */ |
1075 | # ifdef __linux__ |
1076 | /* Make sure there is enough memory to do something useful. */ |
1077 | /*if (ENABLE_SWAPONOFF) - WRONG: we may have non-bbox swapon*/ { |
1078 | struct sysinfo info; |
1079 | |
1080 | if (sysinfo(&info) == 0 |
1081 | && (info.mem_unit ? info.mem_unit : 1) * (long long)info.totalram < 1024*1024 |
1082 | ) { |
1083 | message(L_CONSOLE, "Low memory, forcing swapon"); |
1084 | /* swapon -a requires /proc typically */ |
1085 | new_init_action(SYSINIT, "mount -t proc proc /proc", ""); |
1086 | /* Try to turn on swap */ |
1087 | new_init_action(SYSINIT, "swapon -a", ""); |
1088 | run_actions(SYSINIT); /* wait and removing */ |
1089 | } |
1090 | } |
1091 | # endif |
1092 | #endif |
1093 | |
1094 | /* Check if we are supposed to be in single user mode */ |
1095 | if (argv[1] |
1096 | && (strcmp(argv[1], "single") == 0 || strcmp(argv[1], "-s") == 0 || LONE_CHAR(argv[1], '1')) |
1097 | ) { |
1098 | /* ??? shouldn't we set RUNLEVEL="b" here? */ |
1099 | /* Start a shell on console */ |
1100 | new_init_action(RESPAWN, bb_default_login_shell, ""); |
1101 | } else { |
1102 | /* Not in single user mode - see what inittab says */ |
1103 | |
1104 | /* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined, |
1105 | * then parse_inittab() simply adds in some default |
1106 | * actions (i.e., INIT_SCRIPT and a pair |
1107 | * of "askfirst" shells) */ |
1108 | parse_inittab(); |
1109 | } |
1110 | |
1111 | #if ENABLE_SELINUX |
1112 | if (getenv("SELINUX_INIT") == NULL) { |
1113 | int enforce = 0; |
1114 | |
1115 | putenv((char*)"SELINUX_INIT=YES"); |
1116 | if (selinux_init_load_policy(&enforce) == 0) { |
1117 | BB_EXECVP(argv[0], argv); |
1118 | } else if (enforce > 0) { |
1119 | /* SELinux in enforcing mode but load_policy failed */ |
1120 | message(L_CONSOLE, "can't load SELinux Policy. " |
1121 | "Machine is in enforcing mode. Halting now."); |
1122 | return EXIT_FAILURE; |
1123 | } |
1124 | } |
1125 | #endif |
1126 | |
1127 | /* Make the command line just say "init" - thats all, nothing else */ |
1128 | strncpy(argv[0], "init", strlen(argv[0])); |
1129 | /* Wipe argv[1]-argv[N] so they don't clutter the ps listing */ |
1130 | while (*++argv) |
1131 | nuke_str(*argv); |
1132 | |
1133 | /* Set up signal handlers */ |
1134 | if (!DEBUG_INIT) { |
1135 | struct sigaction sa; |
1136 | |
1137 | bb_signals(0 |
1138 | + (1 << SIGPWR) /* halt */ |
1139 | + (1 << SIGUSR1) /* halt */ |
1140 | + (1 << SIGTERM) /* reboot */ |
1141 | + (1 << SIGUSR2) /* poweroff */ |
1142 | , halt_reboot_pwoff); |
1143 | signal(SIGQUIT, restart_handler); /* re-exec another init */ |
1144 | |
1145 | /* Stop handler must allow only SIGCONT inside itself */ |
1146 | memset(&sa, 0, sizeof(sa)); |
1147 | sigfillset(&sa.sa_mask); |
1148 | sigdelset(&sa.sa_mask, SIGCONT); |
1149 | sa.sa_handler = stop_handler; |
1150 | /* NB: sa_flags doesn't have SA_RESTART. |
1151 | * It must be able to interrupt wait(). |
1152 | */ |
1153 | sigaction_set(SIGTSTP, &sa); /* pause */ |
1154 | /* Does not work as intended, at least in 2.6.20. |
1155 | * SIGSTOP is simply ignored by init: |
1156 | */ |
1157 | sigaction_set(SIGSTOP, &sa); /* pause */ |
1158 | |
1159 | /* SIGINT (Ctrl-Alt-Del) must interrupt wait(), |
1160 | * setting handler without SA_RESTART flag. |
1161 | */ |
1162 | bb_signals_recursive_norestart((1 << SIGINT), record_signo); |
1163 | } |
1164 | |
1165 | /* Set up "reread /etc/inittab" handler. |
1166 | * Handler is set up without SA_RESTART, it will interrupt syscalls. |
1167 | */ |
1168 | if (!DEBUG_INIT && ENABLE_FEATURE_USE_INITTAB) |
1169 | bb_signals_recursive_norestart((1 << SIGHUP), record_signo); |
1170 | |
1171 | /* Now run everything that needs to be run */ |
1172 | /* First run the sysinit command */ |
1173 | run_actions(SYSINIT); |
1174 | check_delayed_sigs(); |
1175 | /* Next run anything that wants to block */ |
1176 | run_actions(WAIT); |
1177 | check_delayed_sigs(); |
1178 | /* Next run anything to be run only once */ |
1179 | run_actions(ONCE); |
1180 | |
1181 | /* Now run the looping stuff for the rest of forever. |
1182 | */ |
1183 | while (1) { |
1184 | int maybe_WNOHANG; |
1185 | |
1186 | maybe_WNOHANG = check_delayed_sigs(); |
1187 | |
1188 | /* (Re)run the respawn/askfirst stuff */ |
1189 | run_actions(RESPAWN | ASKFIRST); |
1190 | maybe_WNOHANG |= check_delayed_sigs(); |
1191 | |
1192 | /* Don't consume all CPU time - sleep a bit */ |
1193 | sleep(1); |
1194 | maybe_WNOHANG |= check_delayed_sigs(); |
1195 | |
1196 | /* Wait for any child process(es) to exit. |
1197 | * |
1198 | * If check_delayed_sigs above reported that a signal |
1199 | * was caught, wait will be nonblocking. This ensures |
1200 | * that if SIGHUP has reloaded inittab, respawn and askfirst |
1201 | * actions will not be delayed until next child death. |
1202 | */ |
1203 | if (maybe_WNOHANG) |
1204 | maybe_WNOHANG = WNOHANG; |
1205 | while (1) { |
1206 | pid_t wpid; |
1207 | struct init_action *a; |
1208 | |
1209 | /* If signals happen _in_ the wait, they interrupt it, |
1210 | * bb_signals_recursive_norestart set them up that way |
1211 | */ |
1212 | wpid = waitpid(-1, NULL, maybe_WNOHANG); |
1213 | if (wpid <= 0) |
1214 | break; |
1215 | |
1216 | a = mark_terminated(wpid); |
1217 | if (a) { |
1218 | message(L_LOG, "process '%s' (pid %d) exited. " |
1219 | "Scheduling for restart.", |
1220 | a->command, wpid); |
1221 | } |
1222 | /* See if anyone else is waiting to be reaped */ |
1223 | maybe_WNOHANG = WNOHANG; |
1224 | } |
1225 | } /* while (1) */ |
1226 | } |
1227 | |
1228 | //usage:#define linuxrc_trivial_usage NOUSAGE_STR |
1229 | //usage:#define linuxrc_full_usage "" |
1230 | |
1231 | //usage:#define init_trivial_usage |
1232 | //usage: "" |
1233 | //usage:#define init_full_usage "\n\n" |
1234 | //usage: "Init is the first process started during boot. It never exits." |
1235 | //usage: IF_FEATURE_USE_INITTAB( |
1236 | //usage: "\n""It (re)spawns children according to /etc/inittab." |
1237 | //usage: ) |
1238 | //usage: IF_NOT_FEATURE_USE_INITTAB( |
1239 | //usage: "\n""This version of init doesn't use /etc/inittab," |
1240 | //usage: "\n""has fixed set of processed to run." |
1241 | //usage: ) |
1242 | //usage: |
1243 | //usage:#define init_notes_usage |
1244 | //usage: "This version of init is designed to be run only by the kernel.\n" |
1245 | //usage: "\n" |
1246 | //usage: "BusyBox init doesn't support multiple runlevels. The runlevels field of\n" |
1247 | //usage: "the /etc/inittab file is completely ignored by BusyBox init. If you want\n" |
1248 | //usage: "runlevels, use sysvinit.\n" |
1249 | //usage: "\n" |
1250 | //usage: "BusyBox init works just fine without an inittab. If no inittab is found,\n" |
1251 | //usage: "it has the following default behavior:\n" |
1252 | //usage: "\n" |
1253 | //usage: " ::sysinit:/etc/init.d/rcS\n" |
1254 | //usage: " ::askfirst:/bin/sh\n" |
1255 | //usage: " ::ctrlaltdel:/sbin/reboot\n" |
1256 | //usage: " ::shutdown:/sbin/swapoff -a\n" |
1257 | //usage: " ::shutdown:/bin/umount -a -r\n" |
1258 | //usage: " ::restart:/sbin/init\n" |
1259 | //usage: " tty2::askfirst:/bin/sh\n" |
1260 | //usage: " tty3::askfirst:/bin/sh\n" |
1261 | //usage: " tty4::askfirst:/bin/sh\n" |
1262 | //usage: "\n" |
1263 | //usage: "If you choose to use an /etc/inittab file, the inittab entry format is as follows:\n" |
1264 | //usage: "\n" |
1265 | //usage: " <id>:<runlevels>:<action>:<process>\n" |
1266 | //usage: "\n" |
1267 | //usage: " <id>:\n" |
1268 | //usage: "\n" |
1269 | //usage: " WARNING: This field has a non-traditional meaning for BusyBox init!\n" |
1270 | //usage: " The id field is used by BusyBox init to specify the controlling tty for\n" |
1271 | //usage: " the specified process to run on. The contents of this field are\n" |
1272 | //usage: " appended to \"/dev/\" and used as-is. There is no need for this field to\n" |
1273 | //usage: " be unique, although if it isn't you may have strange results. If this\n" |
1274 | //usage: " field is left blank, then the init's stdin/out will be used.\n" |
1275 | //usage: "\n" |
1276 | //usage: " <runlevels>:\n" |
1277 | //usage: "\n" |
1278 | //usage: " The runlevels field is completely ignored.\n" |
1279 | //usage: "\n" |
1280 | //usage: " <action>:\n" |
1281 | //usage: "\n" |
1282 | //usage: " Valid actions include: sysinit, respawn, askfirst, wait,\n" |
1283 | //usage: " once, restart, ctrlaltdel, and shutdown.\n" |
1284 | //usage: "\n" |
1285 | //usage: " The available actions can be classified into two groups: actions\n" |
1286 | //usage: " that are run only once, and actions that are re-run when the specified\n" |
1287 | //usage: " process exits.\n" |
1288 | //usage: "\n" |
1289 | //usage: " Run only-once actions:\n" |
1290 | //usage: "\n" |
1291 | //usage: " 'sysinit' is the first item run on boot. init waits until all\n" |
1292 | //usage: " sysinit actions are completed before continuing. Following the\n" |
1293 | //usage: " completion of all sysinit actions, all 'wait' actions are run.\n" |
1294 | //usage: " 'wait' actions, like 'sysinit' actions, cause init to wait until\n" |
1295 | //usage: " the specified task completes. 'once' actions are asynchronous,\n" |
1296 | //usage: " therefore, init does not wait for them to complete. 'restart' is\n" |
1297 | //usage: " the action taken to restart the init process. By default this should\n" |
1298 | //usage: " simply run /sbin/init, but can be a script which runs pivot_root or it\n" |
1299 | //usage: " can do all sorts of other interesting things. The 'ctrlaltdel' init\n" |
1300 | //usage: " actions are run when the system detects that someone on the system\n" |
1301 | //usage: " console has pressed the CTRL-ALT-DEL key combination. Typically one\n" |
1302 | //usage: " wants to run 'reboot' at this point to cause the system to reboot.\n" |
1303 | //usage: " Finally the 'shutdown' action specifies the actions to taken when\n" |
1304 | //usage: " init is told to reboot. Unmounting filesystems and disabling swap\n" |
1305 | //usage: " is a very good here.\n" |
1306 | //usage: "\n" |
1307 | //usage: " Run repeatedly actions:\n" |
1308 | //usage: "\n" |
1309 | //usage: " 'respawn' actions are run after the 'once' actions. When a process\n" |
1310 | //usage: " started with a 'respawn' action exits, init automatically restarts\n" |
1311 | //usage: " it. Unlike sysvinit, BusyBox init does not stop processes from\n" |
1312 | //usage: " respawning out of control. The 'askfirst' actions acts just like\n" |
1313 | //usage: " respawn, except that before running the specified process it\n" |
1314 | //usage: " displays the line \"Please press Enter to activate this console.\"\n" |
1315 | //usage: " and then waits for the user to press enter before starting the\n" |
1316 | //usage: " specified process.\n" |
1317 | //usage: "\n" |
1318 | //usage: " Unrecognized actions (like initdefault) will cause init to emit an\n" |
1319 | //usage: " error message, and then go along with its business. All actions are\n" |
1320 | //usage: " run in the order they appear in /etc/inittab.\n" |
1321 | //usage: "\n" |
1322 | //usage: " <process>:\n" |
1323 | //usage: "\n" |
1324 | //usage: " Specifies the process to be executed and its command line.\n" |
1325 | //usage: "\n" |
1326 | //usage: "Example /etc/inittab file:\n" |
1327 | //usage: "\n" |
1328 | //usage: " # This is run first except when booting in single-user mode\n" |
1329 | //usage: " #\n" |
1330 | //usage: " ::sysinit:/etc/init.d/rcS\n" |
1331 | //usage: " \n" |
1332 | //usage: " # /bin/sh invocations on selected ttys\n" |
1333 | //usage: " #\n" |
1334 | //usage: " # Start an \"askfirst\" shell on the console (whatever that may be)\n" |
1335 | //usage: " ::askfirst:-/bin/sh\n" |
1336 | //usage: " # Start an \"askfirst\" shell on /dev/tty2-4\n" |
1337 | //usage: " tty2::askfirst:-/bin/sh\n" |
1338 | //usage: " tty3::askfirst:-/bin/sh\n" |
1339 | //usage: " tty4::askfirst:-/bin/sh\n" |
1340 | //usage: " \n" |
1341 | //usage: " # /sbin/getty invocations for selected ttys\n" |
1342 | //usage: " #\n" |
1343 | //usage: " tty4::respawn:/sbin/getty 38400 tty4\n" |
1344 | //usage: " tty5::respawn:/sbin/getty 38400 tty5\n" |
1345 | //usage: " \n" |
1346 | //usage: " \n" |
1347 | //usage: " # Example of how to put a getty on a serial line (for a terminal)\n" |
1348 | //usage: " #\n" |
1349 | //usage: " #::respawn:/sbin/getty -L ttyS0 9600 vt100\n" |
1350 | //usage: " #::respawn:/sbin/getty -L ttyS1 9600 vt100\n" |
1351 | //usage: " #\n" |
1352 | //usage: " # Example how to put a getty on a modem line\n" |
1353 | //usage: " #::respawn:/sbin/getty 57600 ttyS2\n" |
1354 | //usage: " \n" |
1355 | //usage: " # Stuff to do when restarting the init process\n" |
1356 | //usage: " ::restart:/sbin/init\n" |
1357 | //usage: " \n" |
1358 | //usage: " # Stuff to do before rebooting\n" |
1359 | //usage: " ::ctrlaltdel:/sbin/reboot\n" |
1360 | //usage: " ::shutdown:/bin/umount -a -r\n" |
1361 | //usage: " ::shutdown:/sbin/swapoff -a\n" |
1362 |