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