diff options
author | Eric Andersen <andersen@codepoet.org> | 2002-03-05 15:12:19 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2002-03-05 15:12:19 +0000 |
commit | 0298be88aece2a10b04c71db34fb154bdbbc45c9 (patch) | |
tree | 1cf3eb885a205ee40713b468a0b9a7687fa84cc5 | |
parent | 684d745bf3551a0539b4e678b3d3de4f4f800c7a (diff) | |
download | busybox-w32-0298be88aece2a10b04c71db34fb154bdbbc45c9.tar.gz busybox-w32-0298be88aece2a10b04c71db34fb154bdbbc45c9.tar.bz2 busybox-w32-0298be88aece2a10b04c71db34fb154bdbbc45c9.zip |
Update init.c per my changes in the stable branch
-Erik
-rw-r--r-- | init/init.c | 491 |
1 files changed, 269 insertions, 222 deletions
diff --git a/init/init.c b/init/init.c index e48dc50cc..408dd1f95 100644 --- a/init/init.c +++ b/init/init.c | |||
@@ -47,6 +47,9 @@ | |||
47 | # include <sys/syslog.h> | 47 | # include <sys/syslog.h> |
48 | #endif | 48 | #endif |
49 | 49 | ||
50 | #if defined(__UCLIBC__) && !defined(__UCLIBC_HAS_MMU__) | ||
51 | #define fork vfork | ||
52 | #endif | ||
50 | 53 | ||
51 | /* From <linux/vt.h> */ | 54 | /* From <linux/vt.h> */ |
52 | struct vt_stat { | 55 | struct vt_stat { |
@@ -82,19 +85,10 @@ struct serial_struct { | |||
82 | #define init_reboot(magic) reboot(0xfee1dead, 672274793, magic) | 85 | #define init_reboot(magic) reboot(0xfee1dead, 672274793, magic) |
83 | #endif | 86 | #endif |
84 | 87 | ||
85 | #ifndef RB_HALT_SYSTEM | ||
86 | static const int RB_HALT_SYSTEM = 0xcdef0123; | ||
87 | static const int RB_ENABLE_CAD = 0x89abcdef; | ||
88 | static const int RB_DISABLE_CAD = 0; | ||
89 | #define RB_POWER_OFF 0x4321fedc | ||
90 | static const int RB_AUTOBOOT = 0x01234567; | ||
91 | #endif | ||
92 | |||
93 | #ifndef _PATH_STDPATH | 88 | #ifndef _PATH_STDPATH |
94 | #define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin" | 89 | #define _PATH_STDPATH "/usr/bin:/bin:/usr/sbin:/sbin" |
95 | #endif | 90 | #endif |
96 | 91 | ||
97 | |||
98 | #if defined CONFIG_FEATURE_INIT_COREDUMPS | 92 | #if defined CONFIG_FEATURE_INIT_COREDUMPS |
99 | /* | 93 | /* |
100 | * When a file named CORE_ENABLE_FLAG_FILE exists, setrlimit is called | 94 | * When a file named CORE_ENABLE_FLAG_FILE exists, setrlimit is called |
@@ -115,7 +109,6 @@ static const int RB_AUTOBOOT = 0x01234567; | |||
115 | extern int bdflush (int func, long int data); | 109 | extern int bdflush (int func, long int data); |
116 | #endif | 110 | #endif |
117 | 111 | ||
118 | |||
119 | #define SHELL "/bin/sh" /* Default shell */ | 112 | #define SHELL "/bin/sh" /* Default shell */ |
120 | #define LOGIN_SHELL "-" SHELL /* Default login shell */ | 113 | #define LOGIN_SHELL "-" SHELL /* Default login shell */ |
121 | #define INITTAB "/etc/inittab" /* inittab file location */ | 114 | #define INITTAB "/etc/inittab" /* inittab file location */ |
@@ -124,35 +117,24 @@ static const int RB_AUTOBOOT = 0x01234567; | |||
124 | #endif | 117 | #endif |
125 | 118 | ||
126 | #define MAXENV 16 /* Number of env. vars */ | 119 | #define MAXENV 16 /* Number of env. vars */ |
127 | //static const int MAXENV = 16; /* Number of env. vars */ | ||
128 | static const int LOG = 0x1; | ||
129 | static const int CONSOLE = 0x2; | ||
130 | #if defined BB_FEATURE_EXTRA_QUIET | ||
131 | static const int MAYBE_CONSOLE = 0x0; | ||
132 | #else | ||
133 | #define MAYBE_CONSOLE CONSOLE | ||
134 | #endif | ||
135 | |||
136 | 120 | ||
137 | /* Allowed init action types */ | 121 | /* Allowed init action types */ |
138 | typedef enum { | 122 | #define SYSINIT 0x001 |
139 | SYSINIT = 1, | 123 | #define RESPAWN 0x002 |
140 | RESPAWN, | 124 | #define ASKFIRST 0x004 |
141 | ASKFIRST, | 125 | #define WAIT 0x008 |
142 | WAIT, | 126 | #define ONCE 0x010 |
143 | ONCE, | 127 | #define CTRLALTDEL 0x020 |
144 | CTRLALTDEL, | 128 | #define SHUTDOWN 0x040 |
145 | SHUTDOWN, | 129 | #define RESTART 0x080 |
146 | RESTART | ||
147 | } initActionEnum; | ||
148 | 130 | ||
149 | /* A mapping between "inittab" action name strings and action type codes. */ | 131 | /* A mapping between "inittab" action name strings and action type codes. */ |
150 | typedef struct initActionType { | 132 | struct init_action_type { |
151 | const char *name; | 133 | const char *name; |
152 | initActionEnum action; | 134 | int action; |
153 | } initActionType; | 135 | }; |
154 | 136 | ||
155 | static const struct initActionType actions[] = { | 137 | static const struct init_action_type actions[] = { |
156 | {"sysinit", SYSINIT}, | 138 | {"sysinit", SYSINIT}, |
157 | {"respawn", RESPAWN}, | 139 | {"respawn", RESPAWN}, |
158 | {"askfirst", ASKFIRST}, | 140 | {"askfirst", ASKFIRST}, |
@@ -164,18 +146,17 @@ static const struct initActionType actions[] = { | |||
164 | {0, 0} | 146 | {0, 0} |
165 | }; | 147 | }; |
166 | 148 | ||
167 | /* Set up a linked list of initActions, to be read from inittab */ | 149 | /* Set up a linked list of init_actions, to be read from inittab */ |
168 | typedef struct initActionTag initAction; | 150 | struct init_action { |
169 | struct initActionTag { | ||
170 | pid_t pid; | 151 | pid_t pid; |
171 | char process[256]; | 152 | char command[256]; |
172 | char console[256]; | 153 | char terminal[256]; |
173 | initAction *nextPtr; | 154 | struct init_action *next; |
174 | initActionEnum action; | 155 | int action; |
175 | }; | 156 | }; |
176 | static initAction *initActionList = NULL; | ||
177 | |||
178 | 157 | ||
158 | /* Static variables */ | ||
159 | static struct init_action *init_action_list = NULL; | ||
179 | static char *secondConsole = VC_2; | 160 | static char *secondConsole = VC_2; |
180 | static char *thirdConsole = VC_3; | 161 | static char *thirdConsole = VC_3; |
181 | static char *fourthConsole = VC_4; | 162 | static char *fourthConsole = VC_4; |
@@ -183,9 +164,26 @@ static char *log = VC_5; | |||
183 | static int kernelVersion = 0; | 164 | static int kernelVersion = 0; |
184 | static char termType[32] = "TERM=linux"; | 165 | static char termType[32] = "TERM=linux"; |
185 | static char console[32] = _PATH_CONSOLE; | 166 | static char console[32] = _PATH_CONSOLE; |
186 | sig_atomic_t got_cont = 0; | 167 | static sig_atomic_t got_cont = 0; |
168 | static const int LOG = 0x1; | ||
169 | static const int CONSOLE = 0x2; | ||
170 | #if defined BB_FEATURE_EXTRA_QUIET | ||
171 | static const int MAYBE_CONSOLE = 0x0; | ||
172 | #else | ||
173 | #define MAYBE_CONSOLE CONSOLE | ||
174 | #endif | ||
175 | #ifndef RB_HALT_SYSTEM | ||
176 | static const int RB_HALT_SYSTEM = 0xcdef0123; | ||
177 | static const int RB_ENABLE_CAD = 0x89abcdef; | ||
178 | static const int RB_DISABLE_CAD = 0; | ||
179 | #define RB_POWER_OFF 0x4321fedc | ||
180 | static const int RB_AUTOBOOT = 0x01234567; | ||
181 | #endif | ||
182 | |||
183 | /* Function prototypes */ | ||
184 | static void delete_init_action(struct init_action *a); | ||
185 | static int waitfor(struct init_action *a); | ||
187 | 186 | ||
188 | static void delete_initAction(initAction * action); | ||
189 | 187 | ||
190 | static void loop_forever(void) | 188 | static void loop_forever(void) |
191 | { | 189 | { |
@@ -200,8 +198,7 @@ static inline messageND(int device, char *fmt, ...) { } | |||
200 | #else | 198 | #else |
201 | #define messageND message | 199 | #define messageND message |
202 | #endif | 200 | #endif |
203 | static void message(int device, char *fmt, ...) | 201 | static void message(int device, char *fmt, ...) __attribute__ ((format (printf, 2, 3))); |
204 | __attribute__ ((format (printf, 2, 3))); | ||
205 | static void message(int device, char *fmt, ...) | 202 | static void message(int device, char *fmt, ...) |
206 | { | 203 | { |
207 | va_list arguments; | 204 | va_list arguments; |
@@ -216,7 +213,7 @@ static void message(int device, char *fmt, ...) | |||
216 | va_start(arguments, fmt); | 213 | va_start(arguments, fmt); |
217 | vsnprintf(msg, sizeof(msg), fmt, arguments); | 214 | vsnprintf(msg, sizeof(msg), fmt, arguments); |
218 | va_end(arguments); | 215 | va_end(arguments); |
219 | syslog_msg(LOG_USER, LOG_USER|LOG_INFO, msg); | 216 | syslog_msg(LOG_USER, LOG_INFO, msg); |
220 | } | 217 | } |
221 | #else | 218 | #else |
222 | static int log_fd = -1; | 219 | static int log_fd = -1; |
@@ -247,8 +244,7 @@ static void message(int device, char *fmt, ...) | |||
247 | /* Always send console messages to /dev/console so people will see them. */ | 244 | /* Always send console messages to /dev/console so people will see them. */ |
248 | if ( | 245 | if ( |
249 | (fd = | 246 | (fd = |
250 | device_open(_PATH_CONSOLE, | 247 | device_open(_PATH_CONSOLE, O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0) { |
251 | O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0) { | ||
252 | va_start(arguments, fmt); | 248 | va_start(arguments, fmt); |
253 | vdprintf(fd, fmt, arguments); | 249 | vdprintf(fd, fmt, arguments); |
254 | va_end(arguments); | 250 | va_end(arguments); |
@@ -383,8 +379,8 @@ static void console_init(void) | |||
383 | /* Perhaps we should panic here? */ | 379 | /* Perhaps we should panic here? */ |
384 | safe_strncpy(console, "/dev/null", sizeof(console)); | 380 | safe_strncpy(console, "/dev/null", sizeof(console)); |
385 | } else { | 381 | } else { |
386 | /* check for serial console and disable logging to tty5 & running a | 382 | /* check for serial console and disable logging to tty5 & |
387 | * shell to tty2-4 */ | 383 | * running a shell to tty2-4 */ |
388 | if (ioctl(0, TIOCGSERIAL, &sr) == 0) { | 384 | if (ioctl(0, TIOCGSERIAL, &sr) == 0) { |
389 | log = NULL; | 385 | log = NULL; |
390 | secondConsole = NULL; | 386 | secondConsole = NULL; |
@@ -418,23 +414,41 @@ static void fixup_argv(int argc, char **argv, char *new_argv0) | |||
418 | } | 414 | } |
419 | } | 415 | } |
420 | 416 | ||
421 | 417 | /* Make sure there is enough memory to do something useful. * | |
422 | static pid_t run(char *command, char *terminal, int get_enter) | 418 | * Calls "swapon -a" if needed so be sure /etc/fstab is present... */ |
419 | static void check_memory(void) | ||
423 | { | 420 | { |
424 | int i, j; | 421 | struct stat statBuf; |
425 | int fd; | ||
426 | pid_t pid; | ||
427 | char *tmpCmd, *s; | ||
428 | char *cmd[255], *cmdpath; | ||
429 | char buf[255]; | ||
430 | struct stat sb; | ||
431 | static const char press_enter[] = | ||
432 | 422 | ||
433 | #ifdef CUSTOMIZED_BANNER | 423 | if (check_free_memory() > 1000) |
434 | #include CUSTOMIZED_BANNER | 424 | return; |
425 | |||
426 | #if !defined(__UCLIBC__) || defined(__UCLIBC_HAS_MMU__) | ||
427 | if (stat("/etc/fstab", &statBuf) == 0) { | ||
428 | /* swapon -a requires /proc typically */ | ||
429 | system("/bin/mount -t proc proc /proc"); | ||
430 | /* Try to turn on swap */ | ||
431 | system("/sbin/swapon -a"); | ||
432 | if (check_free_memory() < 1000) | ||
433 | goto goodnight; | ||
434 | } else | ||
435 | goto goodnight; | ||
436 | return; | ||
435 | #endif | 437 | #endif |
436 | 438 | ||
437 | "\nPlease press Enter to activate this console. "; | 439 | goodnight: |
440 | message(CONSOLE, | ||
441 | "Sorry, your computer does not have enough memory.\n"); | ||
442 | loop_forever(); | ||
443 | } | ||
444 | |||
445 | static pid_t run(struct init_action *a) | ||
446 | { | ||
447 | struct stat sb; | ||
448 | int i, j, fd, junk; | ||
449 | pid_t pid, pgrp, tmp_pid; | ||
450 | char *s, *tmpCmd, *cmd[255], *cmdpath, buf[255]; | ||
451 | sigset_t nmask, omask; | ||
438 | char *environment[MAXENV+1] = { | 452 | char *environment[MAXENV+1] = { |
439 | termType, | 453 | termType, |
440 | "HOME=/", | 454 | "HOME=/", |
@@ -443,6 +457,11 @@ static pid_t run(char *command, char *terminal, int get_enter) | |||
443 | "USER=root", | 457 | "USER=root", |
444 | NULL | 458 | NULL |
445 | }; | 459 | }; |
460 | static const char press_enter[] = | ||
461 | #ifdef CUSTOMIZED_BANNER | ||
462 | #include CUSTOMIZED_BANNER | ||
463 | #endif | ||
464 | "\nPlease press Enter to activate this console. "; | ||
446 | 465 | ||
447 | /* inherit environment to the child, merging our values -andy */ | 466 | /* inherit environment to the child, merging our values -andy */ |
448 | for (i=0; environ[i]; i++) { | 467 | for (i=0; environ[i]; i++) { |
@@ -457,57 +476,117 @@ static pid_t run(char *command, char *terminal, int get_enter) | |||
457 | } | 476 | } |
458 | } | 477 | } |
459 | 478 | ||
460 | #if !defined(__UCLIBC__) || defined(__UCLIBC_HAS_MMU__) | 479 | /* Block sigchild while forking. */ |
480 | sigemptyset(&nmask); | ||
481 | sigaddset(&nmask, SIGCHLD); | ||
482 | sigprocmask(SIG_BLOCK, &nmask, &omask); | ||
483 | |||
461 | if ((pid = fork()) == 0) | 484 | if ((pid = fork()) == 0) |
462 | #else | ||
463 | if ((pid = vfork()) == 0) | ||
464 | #endif | ||
465 | { | 485 | { |
466 | /* Clean up */ | 486 | /* Clean up */ |
467 | ioctl(0, TIOCNOTTY, 0); | 487 | ioctl(0, TIOCNOTTY, 0); |
468 | close(0); | 488 | close(0); |
469 | close(1); | 489 | close(1); |
470 | close(2); | 490 | close(2); |
491 | sigprocmask(SIG_SETMASK, &omask, NULL); | ||
492 | |||
493 | /* Create a new session and make ourself the process group leader */ | ||
471 | setsid(); | 494 | setsid(); |
472 | 495 | ||
473 | /* Reset signal handlers set for parent process */ | 496 | /* Reset signal handlers that were set by the parent process */ |
474 | signal(SIGUSR1, SIG_DFL); | 497 | signal(SIGUSR1, SIG_DFL); |
475 | signal(SIGUSR2, SIG_DFL); | 498 | signal(SIGUSR2, SIG_DFL); |
476 | signal(SIGINT, SIG_DFL); | 499 | signal(SIGINT, SIG_DFL); |
477 | signal(SIGTERM, SIG_DFL); | 500 | signal(SIGTERM, SIG_DFL); |
478 | signal(SIGHUP, SIG_DFL); | 501 | signal(SIGHUP, SIG_DFL); |
479 | signal(SIGCONT, SIG_DFL); | 502 | signal(SIGCONT, SIG_DFL); |
480 | signal(SIGSTOP, SIG_DFL); | 503 | signal(SIGSTOP, SIG_DFL); |
481 | signal(SIGTSTP, SIG_DFL); | 504 | signal(SIGTSTP, SIG_DFL); |
482 | 505 | ||
483 | if ((fd = device_open(terminal, O_RDWR)) < 0) { | 506 | /* Open the new terminal device */ |
484 | if (stat(terminal, &sb) != 0) { | 507 | if ((fd = device_open(a->terminal, O_RDWR|O_NOCTTY)) < 0) { |
508 | if (stat(a->terminal, &sb) != 0) { | ||
485 | message(LOG | CONSOLE, "device '%s' does not exist.\n", | 509 | message(LOG | CONSOLE, "device '%s' does not exist.\n", |
486 | terminal); | 510 | a->terminal); |
487 | exit(1); | 511 | _exit(1); |
488 | } | 512 | } |
489 | message(LOG | CONSOLE, "Bummer, can't open %s\n", terminal); | 513 | message(LOG | CONSOLE, "Bummer, can't open %s\n", a->terminal); |
490 | exit(1); | 514 | _exit(1); |
491 | } | 515 | } |
492 | dup2(fd, 0); | 516 | /* Make sure the terminal will act fairly normal for us */ |
493 | dup2(fd, 1); | ||
494 | dup2(fd, 2); | ||
495 | ioctl(0, TIOCSCTTY, 1); | ||
496 | tcsetpgrp(0, getpgrp()); | ||
497 | set_term(0); | 517 | set_term(0); |
498 | 518 | ||
519 | /* If the init Action requires up to wait, then force the | ||
520 | * supplied terminal to be the controlling tty. */ | ||
521 | if (a->action & (SYSINIT|WAIT|CTRLALTDEL|SHUTDOWN|RESTART)) { | ||
522 | |||
523 | /* Take over the controlling tty */ | ||
524 | ioctl(fd, TIOCSCTTY, 1); | ||
525 | /* Setup stdin, stdout, stderr for the new process so | ||
526 | * they point to the supplied terminal */ | ||
527 | dup(fd); | ||
528 | dup(fd); | ||
529 | |||
530 | /* Now fork off another process to just hang around */ | ||
531 | if ((pid = fork()) < 0) { | ||
532 | message(LOG | CONSOLE, "Can't fork!\n"); | ||
533 | _exit(1); | ||
534 | } | ||
535 | |||
536 | if (pid > 0) { | ||
537 | |||
538 | /* We are the parent -- wait till the child is done */ | ||
539 | signal(SIGINT, SIG_IGN); | ||
540 | signal(SIGTSTP, SIG_IGN); | ||
541 | signal(SIGQUIT, SIG_IGN); | ||
542 | signal(SIGCHLD, SIG_DFL); | ||
543 | |||
544 | /* Wait for child to exit */ | ||
545 | while ((tmp_pid = waitpid(pid, &junk, 0)) != pid) { | ||
546 | if (tmp_pid < 0 && errno == ECHILD) | ||
547 | break; | ||
548 | } | ||
549 | |||
550 | /* See if stealing the controlling tty back is necessary */ | ||
551 | pgrp = tcgetpgrp(tmp_pid); | ||
552 | if (pgrp != getpid()) | ||
553 | _exit(0); | ||
554 | |||
555 | /* Use a temporary process to steal the controlling tty. */ | ||
556 | if ((pid = fork()) < 0) { | ||
557 | message(LOG | CONSOLE, "Can't fork!\n"); | ||
558 | _exit(1); | ||
559 | } | ||
560 | if (pid == 0) { | ||
561 | setsid(); | ||
562 | ioctl(tmp_pid, TIOCSCTTY, 1); | ||
563 | _exit(0); | ||
564 | } | ||
565 | while((tmp_pid = waitpid(pid, &junk, 0)) != pid) { | ||
566 | if (tmp_pid < 0 && errno == ECHILD) | ||
567 | break; | ||
568 | } | ||
569 | _exit(0); | ||
570 | } | ||
571 | |||
572 | /* Now fall though to actually execute things */ | ||
573 | } else { | ||
574 | dup(fd); | ||
575 | dup(fd); | ||
576 | } | ||
577 | |||
499 | /* See if any special /bin/sh requiring characters are present */ | 578 | /* See if any special /bin/sh requiring characters are present */ |
500 | if (strpbrk(command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) { | 579 | if (strpbrk(a->command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) { |
501 | cmd[0] = SHELL; | 580 | cmd[0] = SHELL; |
502 | cmd[1] = "-c"; | 581 | cmd[1] = "-c"; |
503 | strcpy(buf, "exec "); | 582 | strcpy(buf, "exec "); |
504 | safe_strncpy(buf + sizeof("exec "), command, | 583 | safe_strncpy(buf + sizeof("exec "), a->command, |
505 | sizeof(buf) - sizeof("exec ")); | 584 | sizeof(buf) - sizeof("exec ")); |
506 | cmd[2] = buf; | 585 | cmd[2] = buf; |
507 | cmd[3] = NULL; | 586 | cmd[3] = NULL; |
508 | } else { | 587 | } else { |
509 | /* Convert command (char*) into cmd (char**, one word per string) */ | 588 | /* Convert command (char*) into cmd (char**, one word per string) */ |
510 | safe_strncpy(buf, command, sizeof(buf)); | 589 | safe_strncpy(buf, a->command, sizeof(buf)); |
511 | s = buf; | 590 | s = buf; |
512 | for (tmpCmd = buf, i = 0; | 591 | for (tmpCmd = buf, i = 0; |
513 | (tmpCmd = strsep(&s, " \t")) != NULL;) { | 592 | (tmpCmd = strsep(&s, " \t")) != NULL;) { |
@@ -547,7 +626,7 @@ static pid_t run(char *command, char *terminal, int get_enter) | |||
547 | } | 626 | } |
548 | } | 627 | } |
549 | 628 | ||
550 | if (get_enter) { | 629 | if (a->action & ASKFIRST) { |
551 | /* | 630 | /* |
552 | * Save memory by not exec-ing anything large (like a shell) | 631 | * Save memory by not exec-ing anything large (like a shell) |
553 | * before the user wants it. This is critical if swap is not | 632 | * before the user wants it. This is critical if swap is not |
@@ -556,15 +635,15 @@ static pid_t run(char *command, char *terminal, int get_enter) | |||
556 | * be allowed to start a shell or whatever an init script | 635 | * be allowed to start a shell or whatever an init script |
557 | * specifies. | 636 | * specifies. |
558 | */ | 637 | */ |
559 | messageND(LOG, "Waiting for enter to start '%s' (pid %d, console %s)\n", | 638 | messageND(LOG, "Waiting for enter to start '%s' (pid %d, terminal %s)\n", |
560 | cmd[0], getpid(), terminal); | 639 | cmdpath, getpid(), a->terminal); |
561 | write(fileno(stdout), press_enter, sizeof(press_enter) - 1); | 640 | write(fileno(stdout), press_enter, sizeof(press_enter) - 1); |
562 | getc(stdin); | 641 | getc(stdin); |
563 | } | 642 | } |
564 | 643 | ||
565 | /* Log the process name and args */ | 644 | /* Log the process name and args */ |
566 | messageND(LOG, "Starting pid %d, console %s: '%s'\n", | 645 | messageND(LOG, "Starting pid %d, console %s: '%s'\n", |
567 | getpid(), terminal, command); | 646 | getpid(), a->terminal, cmdpath); |
568 | 647 | ||
569 | #if defined CONFIG_FEATURE_INIT_COREDUMPS | 648 | #if defined CONFIG_FEATURE_INIT_COREDUMPS |
570 | if (stat (CORE_ENABLE_FLAG_FILE, &sb) == 0) { | 649 | if (stat (CORE_ENABLE_FLAG_FILE, &sb) == 0) { |
@@ -582,16 +661,18 @@ static pid_t run(char *command, char *terminal, int get_enter) | |||
582 | /* We're still here? Some error happened. */ | 661 | /* We're still here? Some error happened. */ |
583 | message(LOG | CONSOLE, "Bummer, could not run '%s': %s\n", cmdpath, | 662 | message(LOG | CONSOLE, "Bummer, could not run '%s': %s\n", cmdpath, |
584 | strerror(errno)); | 663 | strerror(errno)); |
585 | exit(-1); | 664 | _exit(-1); |
586 | } | 665 | } |
666 | sigprocmask(SIG_SETMASK, &omask, NULL); | ||
587 | return pid; | 667 | return pid; |
588 | } | 668 | } |
589 | 669 | ||
590 | static int waitfor(char *command, char *terminal, int get_enter) | 670 | static int waitfor(struct init_action *a) |
591 | { | 671 | { |
672 | int pid; | ||
592 | int status, wpid; | 673 | int status, wpid; |
593 | int pid = run(command, terminal, get_enter); | ||
594 | 674 | ||
675 | pid = run(a); | ||
595 | while (1) { | 676 | while (1) { |
596 | wpid = wait(&status); | 677 | wpid = wait(&status); |
597 | if (wpid > 0 && wpid != pid) { | 678 | if (wpid > 0 && wpid != pid) { |
@@ -603,43 +684,27 @@ static int waitfor(char *command, char *terminal, int get_enter) | |||
603 | return wpid; | 684 | return wpid; |
604 | } | 685 | } |
605 | 686 | ||
606 | /* Make sure there is enough memory to do something useful. * | 687 | /* Run all commands of a particular type */ |
607 | * Calls "swapon -a" if needed so be sure /etc/fstab is present... */ | 688 | static void run_actions(int action) |
608 | static void check_memory(void) | ||
609 | { | 689 | { |
610 | struct stat statBuf; | 690 | struct init_action *a, *tmp; |
611 | 691 | ||
612 | if (check_free_memory() > 1000) | 692 | for (a = init_action_list; a; a = tmp) { |
613 | return; | 693 | tmp = a->next; |
614 | |||
615 | #if !defined(__UCLIBC__) || defined(__UCLIBC_HAS_MMU__) | ||
616 | if (stat("/etc/fstab", &statBuf) == 0) { | ||
617 | /* swapon -a requires /proc typically */ | ||
618 | waitfor("/bin/mount -t proc proc /proc", console, FALSE); | ||
619 | /* Try to turn on swap */ | ||
620 | waitfor("/sbin/swapon -a", console, FALSE); | ||
621 | if (check_free_memory() < 1000) | ||
622 | goto goodnight; | ||
623 | } else | ||
624 | goto goodnight; | ||
625 | return; | ||
626 | #endif | ||
627 | |||
628 | goodnight: | ||
629 | message(CONSOLE, | ||
630 | "Sorry, your computer does not have enough memory.\n"); | ||
631 | loop_forever(); | ||
632 | } | ||
633 | |||
634 | /* Run all commands to be run right before halt/reboot */ | ||
635 | static void run_actions(initActionEnum action) | ||
636 | { | ||
637 | initAction *a, *tmp; | ||
638 | for (a = initActionList; a; a = tmp) { | ||
639 | tmp = a->nextPtr; | ||
640 | if (a->action == action) { | 694 | if (a->action == action) { |
641 | waitfor(a->process, a->console, FALSE); | 695 | if (a->action & (SYSINIT|WAIT|CTRLALTDEL|SHUTDOWN|RESTART)) { |
642 | delete_initAction(a); | 696 | waitfor(a); |
697 | delete_init_action(a); | ||
698 | } else if (a->action & ONCE) { | ||
699 | run(a); | ||
700 | delete_init_action(a); | ||
701 | } else if (a->action & (RESPAWN|ASKFIRST)) { | ||
702 | /* Only run stuff with pid==0. If they have | ||
703 | * a pid, that means it is still running */ | ||
704 | if (a->pid == 0) { | ||
705 | a->pid = run(a); | ||
706 | } | ||
707 | } | ||
643 | } | 708 | } |
644 | } | 709 | } |
645 | } | 710 | } |
@@ -692,16 +757,16 @@ static void shutdown_system(void) | |||
692 | 757 | ||
693 | static void exec_signal(int sig) | 758 | static void exec_signal(int sig) |
694 | { | 759 | { |
695 | initAction *a, *tmp; | 760 | struct init_action *a, *tmp; |
696 | for (a = initActionList; a; a = tmp) { | 761 | for (a = init_action_list; a; a = tmp) { |
697 | tmp = a->nextPtr; | 762 | tmp = a->next; |
698 | if (a->action == RESTART) { | 763 | if (a->action & RESTART) { |
699 | shutdown_system(); | 764 | shutdown_system(); |
700 | message(CONSOLE|LOG, "Trying to re-exec %s\n", a->process); | 765 | message(CONSOLE|LOG, "Trying to re-exec %s\n", a->command); |
701 | execl(a->process, a->process, NULL); | 766 | execl(a->command, a->command, NULL); |
702 | 767 | ||
703 | message(CONSOLE|LOG, "execl of %s failed: %s\n", | 768 | message(CONSOLE|LOG, "execl of %s failed: %s\n", |
704 | a->process, sys_errlist[errno]); | 769 | a->command, sys_errlist[errno]); |
705 | sync(); | 770 | sync(); |
706 | sleep(2); | 771 | sleep(2); |
707 | init_reboot(RB_HALT_SYSTEM); | 772 | init_reboot(RB_HALT_SYSTEM); |
@@ -755,12 +820,10 @@ static void ctrlaltdel_signal(int sig) | |||
755 | run_actions(CTRLALTDEL); | 820 | run_actions(CTRLALTDEL); |
756 | } | 821 | } |
757 | 822 | ||
758 | /* | 823 | /* The SIGSTOP & SIGTSTP handler */ |
759 | * The SIGSTOP & SIGTSTP handler | ||
760 | */ | ||
761 | static void stop_handler(int sig) | 824 | static void stop_handler(int sig) |
762 | { | 825 | { |
763 | int saved_errno = errno; | 826 | int saved_errno = errno; |
764 | 827 | ||
765 | got_cont = 0; | 828 | got_cont = 0; |
766 | while(!got_cont) pause(); | 829 | while(!got_cont) pause(); |
@@ -768,9 +831,7 @@ static void stop_handler(int sig) | |||
768 | errno = saved_errno; | 831 | errno = saved_errno; |
769 | } | 832 | } |
770 | 833 | ||
771 | /* | 834 | /* The SIGCONT handler */ |
772 | * The SIGCONT handler | ||
773 | */ | ||
774 | static void cont_handler(int sig) | 835 | static void cont_handler(int sig) |
775 | { | 836 | { |
776 | got_cont = 1; | 837 | got_cont = 1; |
@@ -778,53 +839,54 @@ static void cont_handler(int sig) | |||
778 | 839 | ||
779 | #endif /* ! DEBUG_INIT */ | 840 | #endif /* ! DEBUG_INIT */ |
780 | 841 | ||
781 | static void new_initAction(initActionEnum action, char *process, char *cons) | 842 | static void new_init_action(int action, char *command, char *cons) |
782 | { | 843 | { |
783 | initAction *newAction; | 844 | struct init_action *new_action, *a; |
784 | initAction *a; | ||
785 | 845 | ||
786 | if (*cons == '\0') | 846 | if (*cons == '\0') |
787 | cons = console; | 847 | cons = console; |
788 | 848 | ||
789 | /* If BusyBox detects that a serial console is in use, | 849 | /* If BusyBox detects that a serial console is in use, then entries |
790 | * then entries not refering to the console or null devices will _not_ be run. | 850 | * not refering to the console or null devices will _not_ be run. |
791 | * The exception to this rule is the null device. | 851 | * The exception to this rule is the null device. |
792 | */ | 852 | */ |
793 | if (secondConsole == NULL && strcmp(cons, console) | 853 | if (secondConsole == NULL && strcmp(cons, console) |
794 | && strcmp(cons, "/dev/null")) | 854 | && strcmp(cons, "/dev/null")) |
795 | return; | 855 | return; |
796 | if (strcmp(cons, "/dev/null") == 0 && action == ASKFIRST) | 856 | if (strcmp(cons, "/dev/null") == 0 && (action & ASKFIRST)) |
797 | return; | 857 | return; |
798 | 858 | ||
799 | newAction = calloc((size_t) (1), sizeof(initAction)); | 859 | new_action = calloc((size_t) (1), sizeof(struct init_action)); |
800 | if (!newAction) { | 860 | if (!new_action) { |
801 | message(LOG | CONSOLE, "Memory allocation failure\n"); | 861 | message(LOG | CONSOLE, "Memory allocation failure\n"); |
802 | loop_forever(); | 862 | loop_forever(); |
803 | } | 863 | } |
804 | for (a = initActionList; a && a->nextPtr; a = a->nextPtr) ; | 864 | |
865 | /* Append to the end of the list */ | ||
866 | for (a = init_action_list; a && a->next; a = a->next) ; | ||
805 | if (a) { | 867 | if (a) { |
806 | a->nextPtr = newAction; | 868 | a->next = new_action; |
807 | } else { | 869 | } else { |
808 | initActionList = newAction; | 870 | init_action_list = new_action; |
809 | } | 871 | } |
810 | safe_strncpy(newAction->process, process, 255); | 872 | safe_strncpy(new_action->command, command, 255); |
811 | newAction->action = action; | 873 | new_action->action = action; |
812 | safe_strncpy(newAction->console, cons, 255); | 874 | safe_strncpy(new_action->terminal, cons, 255); |
813 | newAction->pid = 0; | 875 | new_action->pid = 0; |
814 | // message(LOG|CONSOLE, "process='%s' action='%d' console='%s'\n", | 876 | // message(LOG|CONSOLE, "command='%s' action='%d' terminal='%s'\n", |
815 | // newAction->process, newAction->action, newAction->console); | 877 | // new_action->command, new_action->action, new_action->terminal); |
816 | } | 878 | } |
817 | 879 | ||
818 | static void delete_initAction(initAction * action) | 880 | static void delete_init_action(struct init_action * action) |
819 | { | 881 | { |
820 | initAction *a, *b = NULL; | 882 | struct init_action *a, *b = NULL; |
821 | 883 | ||
822 | for (a = initActionList; a; b = a, a = a->nextPtr) { | 884 | for (a = init_action_list; a; b = a, a = a->next) { |
823 | if (a == action) { | 885 | if (a == action) { |
824 | if (b == NULL) { | 886 | if (b == NULL) { |
825 | initActionList = a->nextPtr; | 887 | init_action_list = a->next; |
826 | } else { | 888 | } else { |
827 | b->nextPtr = a->nextPtr; | 889 | b->next = a->next; |
828 | } | 890 | } |
829 | free(a); | 891 | free(a); |
830 | break; | 892 | break; |
@@ -844,8 +906,8 @@ static void parse_inittab(void) | |||
844 | #ifdef CONFIG_FEATURE_USE_INITTAB | 906 | #ifdef CONFIG_FEATURE_USE_INITTAB |
845 | FILE *file; | 907 | FILE *file; |
846 | char buf[256], lineAsRead[256], tmpConsole[256]; | 908 | char buf[256], lineAsRead[256], tmpConsole[256]; |
847 | char *id, *runlev, *action, *process, *eol; | 909 | char *id, *runlev, *action, *command, *eol; |
848 | const struct initActionType *a = actions; | 910 | const struct init_action_type *a = actions; |
849 | int foundIt; | 911 | int foundIt; |
850 | 912 | ||
851 | 913 | ||
@@ -854,28 +916,28 @@ static void parse_inittab(void) | |||
854 | /* No inittab file -- set up some default behavior */ | 916 | /* No inittab file -- set up some default behavior */ |
855 | #endif | 917 | #endif |
856 | /* Reboot on Ctrl-Alt-Del */ | 918 | /* Reboot on Ctrl-Alt-Del */ |
857 | new_initAction(CTRLALTDEL, "/sbin/reboot", console); | 919 | new_init_action(CTRLALTDEL, "/sbin/reboot", console); |
858 | /* Umount all filesystems on halt/reboot */ | 920 | /* Umount all filesystems on halt/reboot */ |
859 | new_initAction(SHUTDOWN, "/bin/umount -a -r", console); | 921 | new_init_action(SHUTDOWN, "/bin/umount -a -r", console); |
860 | #if !defined(__UCLIBC__) || defined(__UCLIBC_HAS_MMU__) | 922 | #if !defined(__UCLIBC__) || defined(__UCLIBC_HAS_MMU__) |
861 | /* Swapoff on halt/reboot */ | 923 | /* Swapoff on halt/reboot */ |
862 | new_initAction(SHUTDOWN, "/sbin/swapoff -a", console); | 924 | new_init_action(SHUTDOWN, "/sbin/swapoff -a", console); |
863 | #endif | 925 | #endif |
864 | /* Prepare to restart init when a HUP is received */ | 926 | /* Prepare to restart init when a HUP is received */ |
865 | new_initAction(RESTART, "/sbin/init", console); | 927 | new_init_action(RESTART, "/sbin/init", console); |
866 | /* Askfirst shell on tty1 */ | 928 | /* Askfirst shell on tty1 */ |
867 | new_initAction(ASKFIRST, LOGIN_SHELL, console); | 929 | new_init_action(ASKFIRST, LOGIN_SHELL, console); |
868 | /* Askfirst shell on tty2 */ | 930 | /* Askfirst shell on tty2 */ |
869 | if (secondConsole != NULL) | 931 | if (secondConsole != NULL) |
870 | new_initAction(ASKFIRST, LOGIN_SHELL, secondConsole); | 932 | new_init_action(ASKFIRST, LOGIN_SHELL, secondConsole); |
871 | /* Askfirst shell on tty3 */ | 933 | /* Askfirst shell on tty3 */ |
872 | if (thirdConsole != NULL) | 934 | if (thirdConsole != NULL) |
873 | new_initAction(ASKFIRST, LOGIN_SHELL, thirdConsole); | 935 | new_init_action(ASKFIRST, LOGIN_SHELL, thirdConsole); |
874 | /* Askfirst shell on tty4 */ | 936 | /* Askfirst shell on tty4 */ |
875 | if (fourthConsole != NULL) | 937 | if (fourthConsole != NULL) |
876 | new_initAction(ASKFIRST, LOGIN_SHELL, fourthConsole); | 938 | new_init_action(ASKFIRST, LOGIN_SHELL, fourthConsole); |
877 | /* sysinit */ | 939 | /* sysinit */ |
878 | new_initAction(SYSINIT, INIT_SCRIPT, console); | 940 | new_init_action(SYSINIT, INIT_SCRIPT, console); |
879 | 941 | ||
880 | return; | 942 | return; |
881 | #ifdef CONFIG_FEATURE_USE_INITTAB | 943 | #ifdef CONFIG_FEATURE_USE_INITTAB |
@@ -918,14 +980,14 @@ static void parse_inittab(void) | |||
918 | ++action; | 980 | ++action; |
919 | } | 981 | } |
920 | 982 | ||
921 | /* Separate the action from the process */ | 983 | /* Separate the action from the command */ |
922 | process = strchr(action, ':'); | 984 | command = strchr(action, ':'); |
923 | if (process == NULL || *(process + 1) == '\0') { | 985 | if (command == NULL || *(command + 1) == '\0') { |
924 | message(LOG | CONSOLE, "Bad inittab entry: %s\n", lineAsRead); | 986 | message(LOG | CONSOLE, "Bad inittab entry: %s\n", lineAsRead); |
925 | continue; | 987 | continue; |
926 | } else { | 988 | } else { |
927 | *process = '\0'; | 989 | *command = '\0'; |
928 | ++process; | 990 | ++command; |
929 | } | 991 | } |
930 | 992 | ||
931 | /* Ok, now process it */ | 993 | /* Ok, now process it */ |
@@ -937,12 +999,12 @@ static void parse_inittab(void) | |||
937 | strncat(tmpConsole, id, 200); | 999 | strncat(tmpConsole, id, 200); |
938 | id = tmpConsole; | 1000 | id = tmpConsole; |
939 | } | 1001 | } |
940 | new_initAction(a->action, process, id); | 1002 | new_init_action(a->action, command, id); |
941 | foundIt = TRUE; | 1003 | foundIt = TRUE; |
942 | } | 1004 | } |
943 | a++; | 1005 | a++; |
944 | } | 1006 | } |
945 | if (foundIt) | 1007 | if (foundIt == TRUE) |
946 | continue; | 1008 | continue; |
947 | else { | 1009 | else { |
948 | /* Choke on an unknown action */ | 1010 | /* Choke on an unknown action */ |
@@ -957,11 +1019,10 @@ static void parse_inittab(void) | |||
957 | 1019 | ||
958 | extern int init_main(int argc, char **argv) | 1020 | extern int init_main(int argc, char **argv) |
959 | { | 1021 | { |
960 | initAction *a, *tmp; | 1022 | struct init_action *a; |
961 | pid_t wpid; | 1023 | pid_t wpid; |
962 | int status; | 1024 | int status; |
963 | 1025 | ||
964 | |||
965 | if (argc > 1 && !strcmp(argv[1], "-q")) { | 1026 | if (argc > 1 && !strcmp(argv[1], "-q")) { |
966 | /* don't assume init's pid == 1 */ | 1027 | /* don't assume init's pid == 1 */ |
967 | long *pid = find_pid_by_name("init"); | 1028 | long *pid = find_pid_by_name("init"); |
@@ -986,10 +1047,10 @@ extern int init_main(int argc, char **argv) | |||
986 | } | 1047 | } |
987 | /* Set up sig handlers -- be sure to | 1048 | /* Set up sig handlers -- be sure to |
988 | * clear all of these in run() */ | 1049 | * clear all of these in run() */ |
989 | signal(SIGHUP, exec_signal); | 1050 | signal(SIGHUP, exec_signal); |
990 | signal(SIGUSR1, halt_signal); | 1051 | signal(SIGUSR1, halt_signal); |
991 | signal(SIGUSR2, halt_signal); | 1052 | signal(SIGUSR2, halt_signal); |
992 | signal(SIGINT, ctrlaltdel_signal); | 1053 | signal(SIGINT, ctrlaltdel_signal); |
993 | signal(SIGTERM, reboot_signal); | 1054 | signal(SIGTERM, reboot_signal); |
994 | signal(SIGCONT, cont_handler); | 1055 | signal(SIGCONT, cont_handler); |
995 | signal(SIGSTOP, stop_handler); | 1056 | signal(SIGSTOP, stop_handler); |
@@ -1029,13 +1090,13 @@ extern int init_main(int argc, char **argv) | |||
1029 | !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) { | 1090 | !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) { |
1030 | /* Ask first then start a shell on tty2-4 */ | 1091 | /* Ask first then start a shell on tty2-4 */ |
1031 | if (secondConsole != NULL) | 1092 | if (secondConsole != NULL) |
1032 | new_initAction(ASKFIRST, LOGIN_SHELL, secondConsole); | 1093 | new_init_action(ASKFIRST, LOGIN_SHELL, secondConsole); |
1033 | if (thirdConsole != NULL) | 1094 | if (thirdConsole != NULL) |
1034 | new_initAction(ASKFIRST, LOGIN_SHELL, thirdConsole); | 1095 | new_init_action(ASKFIRST, LOGIN_SHELL, thirdConsole); |
1035 | if (fourthConsole != NULL) | 1096 | if (fourthConsole != NULL) |
1036 | new_initAction(ASKFIRST, LOGIN_SHELL, fourthConsole); | 1097 | new_init_action(ASKFIRST, LOGIN_SHELL, fourthConsole); |
1037 | /* Start a shell on tty1 */ | 1098 | /* Start a shell on tty1 */ |
1038 | new_initAction(RESPAWN, LOGIN_SHELL, console); | 1099 | new_init_action(RESPAWN, LOGIN_SHELL, console); |
1039 | } else { | 1100 | } else { |
1040 | /* Not in single user mode -- see what inittab says */ | 1101 | /* Not in single user mode -- see what inittab says */ |
1041 | 1102 | ||
@@ -1053,58 +1114,44 @@ extern int init_main(int argc, char **argv) | |||
1053 | 1114 | ||
1054 | /* First run the sysinit command */ | 1115 | /* First run the sysinit command */ |
1055 | run_actions(SYSINIT); | 1116 | run_actions(SYSINIT); |
1117 | |||
1056 | /* Next run anything that wants to block */ | 1118 | /* Next run anything that wants to block */ |
1057 | run_actions(WAIT); | 1119 | run_actions(WAIT); |
1120 | |||
1058 | /* Next run anything to be run only once */ | 1121 | /* Next run anything to be run only once */ |
1059 | for (a = initActionList; a; a = tmp) { | 1122 | run_actions(ONCE); |
1060 | tmp = a->nextPtr; | 1123 | |
1061 | if (a->action == ONCE) { | ||
1062 | run(a->process, a->console, FALSE); | ||
1063 | /* Now remove the "once" entry from the list */ | ||
1064 | delete_initAction(a); | ||
1065 | } | ||
1066 | } | ||
1067 | /* If there is nothing else to do, stop */ | 1124 | /* If there is nothing else to do, stop */ |
1068 | if (initActionList == NULL) { | 1125 | if (init_action_list == NULL) { |
1069 | message(LOG | CONSOLE, | 1126 | message(LOG | CONSOLE, "No more tasks for init -- sleeping forever.\n"); |
1070 | "No more tasks for init -- sleeping forever.\n"); | ||
1071 | loop_forever(); | 1127 | loop_forever(); |
1072 | } | 1128 | } |
1073 | 1129 | ||
1074 | /* Now run the looping stuff for the rest of forever */ | 1130 | /* Now run the looping stuff for the rest of forever */ |
1075 | while (1) { | 1131 | while (1) { |
1076 | for (a = initActionList; a; a = a->nextPtr) { | 1132 | /* run the respawn stuff */ |
1077 | /* Only run stuff with pid==0. If they have | 1133 | run_actions(RESPAWN); |
1078 | * a pid, that means they are still running */ | 1134 | |
1079 | if (a->pid == 0) { | 1135 | /* run the askfirst stuff */ |
1080 | switch (a->action) { | 1136 | run_actions(ASKFIRST); |
1081 | case RESPAWN: | 1137 | |
1082 | /* run the respawn stuff */ | 1138 | /* Don't consume all CPU time -- sleep a bit */ |
1083 | a->pid = run(a->process, a->console, FALSE); | 1139 | sleep(1); |
1084 | break; | 1140 | |
1085 | case ASKFIRST: | ||
1086 | /* run the askfirst stuff */ | ||
1087 | a->pid = run(a->process, a->console, TRUE); | ||
1088 | break; | ||
1089 | /* silence the compiler's incessant whining */ | ||
1090 | default: | ||
1091 | break; | ||
1092 | } | ||
1093 | } | ||
1094 | } | ||
1095 | /* Wait for a child process to exit */ | 1141 | /* Wait for a child process to exit */ |
1096 | wpid = wait(&status); | 1142 | wpid = wait(&status); |
1097 | if (wpid > 0) { | 1143 | if (wpid > 0) { |
1098 | /* Find out who died and clean up their corpse */ | 1144 | /* Find out who died and clean up their corpse */ |
1099 | for (a = initActionList; a; a = a->nextPtr) { | 1145 | for (a = init_action_list; a; a = a->next) { |
1100 | if (a->pid == wpid) { | 1146 | if (a->pid == wpid) { |
1147 | /* Set the pid to 0 so that the process gets | ||
1148 | * restarted by run_actions() */ | ||
1101 | a->pid = 0; | 1149 | a->pid = 0; |
1102 | message(LOG, "Process '%s' (pid %d) exited. Scheduling it for restart.\n", | 1150 | message(LOG, "Process '%s' (pid %d) exited. " |
1103 | a->process, wpid); | 1151 | "Scheduling it for restart.\n", a->command, wpid); |
1104 | } | 1152 | } |
1105 | } | 1153 | } |
1106 | } | 1154 | } |
1107 | sleep(1); | ||
1108 | } | 1155 | } |
1109 | } | 1156 | } |
1110 | 1157 | ||