diff options
author | Erik Andersen <andersen@codepoet.org> | 2000-02-09 04:16:43 +0000 |
---|---|---|
committer | Erik Andersen <andersen@codepoet.org> | 2000-02-09 04:16:43 +0000 |
commit | e132f4b09e5c9aedaef97f65279e8702633fd425 (patch) | |
tree | 50bfe1c027ff760e426ae31442da73e536dd4baa /init.c | |
parent | e49d5ecbbe51718fa925b6890a735e5937cc2aa2 (diff) | |
download | busybox-w32-e132f4b09e5c9aedaef97f65279e8702633fd425.tar.gz busybox-w32-e132f4b09e5c9aedaef97f65279e8702633fd425.tar.bz2 busybox-w32-e132f4b09e5c9aedaef97f65279e8702633fd425.zip |
Fixed the init problem where it wouldn't unmount filesystems
on reboot. Also fixed swapoff -a so it works.
-Erik
Diffstat (limited to 'init.c')
-rw-r--r-- | init.c | 126 |
1 files changed, 84 insertions, 42 deletions
@@ -22,6 +22,11 @@ | |||
22 | * | 22 | * |
23 | */ | 23 | */ |
24 | 24 | ||
25 | /* Turn this on to disable all the dangerous | ||
26 | rebooting stuff when debugging. | ||
27 | #define DEBUG_INIT | ||
28 | */ | ||
29 | |||
25 | #include "internal.h" | 30 | #include "internal.h" |
26 | #include <stdio.h> | 31 | #include <stdio.h> |
27 | #include <string.h> | 32 | #include <string.h> |
@@ -78,7 +83,8 @@ typedef enum { | |||
78 | RESPAWN, | 83 | RESPAWN, |
79 | ASKFIRST, | 84 | ASKFIRST, |
80 | WAIT, | 85 | WAIT, |
81 | ONCE | 86 | ONCE, |
87 | CTRLALTDEL | ||
82 | } initActionEnum; | 88 | } initActionEnum; |
83 | 89 | ||
84 | /* And now a list of the actions we support in the version of init */ | 90 | /* And now a list of the actions we support in the version of init */ |
@@ -93,6 +99,7 @@ static const struct initActionType actions[] = { | |||
93 | {"askfirst", ASKFIRST}, | 99 | {"askfirst", ASKFIRST}, |
94 | {"wait", WAIT}, | 100 | {"wait", WAIT}, |
95 | {"once", ONCE}, | 101 | {"once", ONCE}, |
102 | {"ctrlaltdel", CTRLALTDEL}, | ||
96 | {0} | 103 | {0} |
97 | }; | 104 | }; |
98 | 105 | ||
@@ -113,6 +120,7 @@ static char *log = VT_LOG; | |||
113 | static int kernelVersion = 0; | 120 | static int kernelVersion = 0; |
114 | static char termType[32] = "TERM=ansi"; | 121 | static char termType[32] = "TERM=ansi"; |
115 | static char console[32] = _PATH_CONSOLE; | 122 | static char console[32] = _PATH_CONSOLE; |
123 | static void delete_initAction(initAction * action); | ||
116 | 124 | ||
117 | 125 | ||
118 | /* print a message to the specified device: | 126 | /* print a message to the specified device: |
@@ -131,8 +139,8 @@ void message(int device, char *fmt, ...) | |||
131 | va_start(arguments, fmt); | 139 | va_start(arguments, fmt); |
132 | vsnprintf(msg, sizeof(msg), fmt, arguments); | 140 | vsnprintf(msg, sizeof(msg), fmt, arguments); |
133 | va_end(arguments); | 141 | va_end(arguments); |
134 | openlog("init", 0, LOG_DAEMON); | 142 | openlog("init", 0, LOG_USER); |
135 | syslog(LOG_DAEMON | LOG_NOTICE, msg); | 143 | syslog(LOG_USER|LOG_INFO, msg); |
136 | closelog(); | 144 | closelog(); |
137 | } | 145 | } |
138 | #else | 146 | #else |
@@ -146,11 +154,12 @@ void message(int device, char *fmt, ...) | |||
146 | log_fd = -2; | 154 | log_fd = -2; |
147 | /* log to main console instead */ | 155 | /* log to main console instead */ |
148 | device = CONSOLE; | 156 | device = CONSOLE; |
149 | } else if ((log_fd = device_open(log, O_RDWR | O_NDELAY)) < 0) { | 157 | } else if ((log_fd = device_open(log, O_RDWR|O_NDELAY)) < 0) { |
150 | log_fd = -1; | 158 | log_fd = -2; |
151 | fprintf(stderr, "Bummer, can't write to log on %s!\r\n", log); | 159 | fprintf(stderr, "Bummer, can't write to log on %s!\r\n", log); |
152 | fflush(stderr); | 160 | fflush(stderr); |
153 | return; | 161 | log = NULL; |
162 | device = CONSOLE; | ||
154 | } | 163 | } |
155 | } | 164 | } |
156 | if ((device & LOG) && (log_fd >= 0)) { | 165 | if ((device & LOG) && (log_fd >= 0)) { |
@@ -303,10 +312,10 @@ static void console_init() | |||
303 | /* check for serial console and disable logging to tty3 & running a | 312 | /* check for serial console and disable logging to tty3 & running a |
304 | * shell to tty2 */ | 313 | * shell to tty2 */ |
305 | if (ioctl(0, TIOCGSERIAL, &sr) == 0) { | 314 | if (ioctl(0, TIOCGSERIAL, &sr) == 0) { |
306 | message(LOG | CONSOLE, | ||
307 | "serial console detected. Disabling virtual terminals.\r\n"); | ||
308 | log = NULL; | 315 | log = NULL; |
309 | secondConsole = NULL; | 316 | secondConsole = NULL; |
317 | message(LOG | CONSOLE, | ||
318 | "serial console detected. Disabling virtual terminals.\r\n"); | ||
310 | } | 319 | } |
311 | close(fd); | 320 | close(fd); |
312 | } | 321 | } |
@@ -319,6 +328,7 @@ static pid_t run(char *command, char *terminal, int get_enter) | |||
319 | pid_t pid; | 328 | pid_t pid; |
320 | char *tmpCmd; | 329 | char *tmpCmd; |
321 | char *cmd[255]; | 330 | char *cmd[255]; |
331 | char buf[255]; | ||
322 | static const char press_enter[] = | 332 | static const char press_enter[] = |
323 | 333 | ||
324 | "\nPlease press Enter to activate this console. "; | 334 | "\nPlease press Enter to activate this console. "; |
@@ -333,7 +343,9 @@ static pid_t run(char *command, char *terminal, int get_enter) | |||
333 | 343 | ||
334 | 344 | ||
335 | if ((pid = fork()) == 0) { | 345 | if ((pid = fork()) == 0) { |
346 | #ifdef DEBUG_INIT | ||
336 | pid_t shell_pgid = getpid(); | 347 | pid_t shell_pgid = getpid(); |
348 | #endif | ||
337 | 349 | ||
338 | /* Clean up */ | 350 | /* Clean up */ |
339 | close(0); | 351 | close(0); |
@@ -369,30 +381,40 @@ static pid_t run(char *command, char *terminal, int get_enter) | |||
369 | */ | 381 | */ |
370 | char c; | 382 | char c; |
371 | 383 | ||
384 | #ifdef DEBUG_INIT | ||
372 | message(LOG, "Waiting for enter to start '%s' (pid %d, console %s)\r\n", | 385 | message(LOG, "Waiting for enter to start '%s' (pid %d, console %s)\r\n", |
373 | command, shell_pgid, terminal); | 386 | command, shell_pgid, terminal); |
387 | #endif | ||
374 | write(fileno(stdout), press_enter, sizeof(press_enter) - 1); | 388 | write(fileno(stdout), press_enter, sizeof(press_enter) - 1); |
375 | read(fileno(stdin), &c, 1); | 389 | read(fileno(stdin), &c, 1); |
376 | } | 390 | } |
377 | 391 | ||
392 | #ifdef DEBUG_INIT | ||
378 | /* Log the process name and args */ | 393 | /* Log the process name and args */ |
379 | message(LOG, "Starting pid %d, console %s: '", | 394 | message(LOG, "Starting pid %d, console %s: '%s'\r\n", |
380 | shell_pgid, terminal, command); | 395 | shell_pgid, terminal, command); |
381 | |||
382 | /* Convert command (char*) into cmd (char**, one word per string) */ | ||
383 | for (tmpCmd = command, i = 0; | ||
384 | (tmpCmd = strsep(&command, " \t")) != NULL;) { | ||
385 | if (*tmpCmd != '\0') { | ||
386 | cmd[i] = tmpCmd; | ||
387 | #ifdef DEBUG_INIT | ||
388 | message(LOG, "%s ", tmpCmd); | ||
389 | #endif | 396 | #endif |
390 | tmpCmd++; | 397 | |
391 | i++; | 398 | /* See if any special /bin/sh requiring characters are present */ |
399 | if (strpbrk(command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) { | ||
400 | cmd[0] = SHELL; | ||
401 | cmd[1] = "-c"; | ||
402 | strcpy(buf, "exec "); | ||
403 | strncat(buf, command, sizeof(buf) - strlen(buf) - 1); | ||
404 | cmd[2] = buf; | ||
405 | cmd[3] = NULL; | ||
406 | } else { | ||
407 | /* Convert command (char*) into cmd (char**, one word per string) */ | ||
408 | for (tmpCmd = command, i = 0; | ||
409 | (tmpCmd = strsep(&command, " \t")) != NULL;) { | ||
410 | if (*tmpCmd != '\0') { | ||
411 | cmd[i] = tmpCmd; | ||
412 | tmpCmd++; | ||
413 | i++; | ||
414 | } | ||
392 | } | 415 | } |
416 | cmd[i] = NULL; | ||
393 | } | 417 | } |
394 | cmd[i] = NULL; | ||
395 | message(LOG, "'\r\n"); | ||
396 | 418 | ||
397 | /* Now run it. The new program will take over this PID, | 419 | /* Now run it. The new program will take over this PID, |
398 | * so nothing further in init.c should be run. */ | 420 | * so nothing further in init.c should be run. */ |
@@ -413,9 +435,8 @@ static int waitfor(char *command, char *terminal, int get_enter) | |||
413 | 435 | ||
414 | while (1) { | 436 | while (1) { |
415 | wpid = wait(&status); | 437 | wpid = wait(&status); |
416 | if (wpid > 0) { | 438 | if (wpid > 0 && wpid != pid) { |
417 | message(LOG, "Process '%s' (pid %d) exited.\n", command, wpid); | 439 | continue; |
418 | break; | ||
419 | } | 440 | } |
420 | if (wpid == pid) | 441 | if (wpid == pid) |
421 | break; | 442 | break; |
@@ -424,7 +445,7 @@ static int waitfor(char *command, char *terminal, int get_enter) | |||
424 | } | 445 | } |
425 | 446 | ||
426 | /* Make sure there is enough memory to do something useful. * | 447 | /* Make sure there is enough memory to do something useful. * |
427 | * Calls swapon if needed so be sure /proc is mounted. */ | 448 | * Calls "swapon -a" if needed so be sure /etc/fstab is present... */ |
428 | static void check_memory() | 449 | static void check_memory() |
429 | { | 450 | { |
430 | struct stat statBuf; | 451 | struct stat statBuf; |
@@ -434,7 +455,7 @@ static void check_memory() | |||
434 | 455 | ||
435 | if (stat("/etc/fstab", &statBuf) == 0) { | 456 | if (stat("/etc/fstab", &statBuf) == 0) { |
436 | /* Try to turn on swap */ | 457 | /* Try to turn on swap */ |
437 | waitfor("/bin/swapon swapon -a", log, FALSE); | 458 | system("/sbin/swapon swapon -a"); |
438 | if (mem_total() < 3500) | 459 | if (mem_total() < 3500) |
439 | goto goodnight; | 460 | goto goodnight; |
440 | } else | 461 | } else |
@@ -448,31 +469,45 @@ static void check_memory() | |||
448 | sleep(1); | 469 | sleep(1); |
449 | } | 470 | } |
450 | 471 | ||
472 | /* Run all commands to be run right before halt/reboot */ | ||
473 | static void run_lastAction(void) | ||
474 | { | ||
475 | initAction *a; | ||
476 | for (a = initActionList; a; a = a->nextPtr) { | ||
477 | if (a->action == CTRLALTDEL) { | ||
478 | waitfor(a->process, a->console, FALSE); | ||
479 | delete_initAction(a); | ||
480 | } | ||
481 | } | ||
482 | } | ||
483 | |||
484 | |||
451 | #ifndef DEBUG_INIT | 485 | #ifndef DEBUG_INIT |
452 | static void shutdown_system(void) | 486 | static void shutdown_system(void) |
453 | { | 487 | { |
488 | |||
454 | /* first disable our SIGHUP signal */ | 489 | /* first disable our SIGHUP signal */ |
455 | signal(SIGHUP, SIG_DFL); | 490 | signal(SIGHUP, SIG_DFL); |
456 | 491 | ||
457 | /* Allow Ctrl-Alt-Del to reboot system. */ | 492 | /* Allow Ctrl-Alt-Del to reboot system. */ |
458 | reboot(RB_ENABLE_CAD); | 493 | reboot(RB_ENABLE_CAD); |
459 | message(CONSOLE, "\r\nThe system is going down NOW !!\r\n"); | 494 | |
495 | message(CONSOLE|LOG, "\r\nThe system is going down NOW !!\r\n"); | ||
460 | sync(); | 496 | sync(); |
461 | 497 | ||
462 | /* Send signals to every process _except_ pid 1 */ | 498 | /* Send signals to every process _except_ pid 1 */ |
463 | message(CONSOLE, "Sending SIGTERM to all processes.\r\n"); | 499 | message(CONSOLE|LOG, "Sending SIGTERM to all processes.\r\n"); |
464 | kill(-1, SIGTERM); | 500 | kill(-1, SIGTERM); |
465 | sleep(5); | 501 | sleep(1); |
466 | sync(); | 502 | sync(); |
467 | 503 | ||
468 | message(CONSOLE, "Sending SIGKILL to all processes.\r\n"); | 504 | message(CONSOLE|LOG, "Sending SIGKILL to all processes.\r\n"); |
469 | kill(-1, SIGKILL); | 505 | kill(-1, SIGKILL); |
470 | sleep(5); | 506 | sleep(1); |
507 | |||
508 | /* run everything to be run at "ctrlaltdel" */ | ||
509 | run_lastAction(); | ||
471 | 510 | ||
472 | message(CONSOLE, "Disabling swap.\r\n"); | ||
473 | waitfor("swapoff -a", console, FALSE); | ||
474 | message(CONSOLE, "Unmounting filesystems.\r\n"); | ||
475 | waitfor("umount -a -r", console, FALSE); | ||
476 | sync(); | 511 | sync(); |
477 | if (kernelVersion > 0 && kernelVersion <= 2 * 65536 + 2 * 256 + 11) { | 512 | if (kernelVersion > 0 && kernelVersion <= 2 * 65536 + 2 * 256 + 11) { |
478 | /* bdflush, kupdate not needed for kernels >2.2.11 */ | 513 | /* bdflush, kupdate not needed for kernels >2.2.11 */ |
@@ -484,14 +519,14 @@ static void shutdown_system(void) | |||
484 | static void halt_signal(int sig) | 519 | static void halt_signal(int sig) |
485 | { | 520 | { |
486 | shutdown_system(); | 521 | shutdown_system(); |
487 | message(CONSOLE, | 522 | message(CONSOLE|LOG, |
488 | "The system is halted. Press %s or turn off power\r\n", | 523 | "The system is halted. Press %s or turn off power\r\n", |
489 | (secondConsole == NULL) /* serial console */ | 524 | (secondConsole == NULL) /* serial console */ |
490 | ? "Reset" : "CTRL-ALT-DEL"); | 525 | ? "Reset" : "CTRL-ALT-DEL"); |
491 | sync(); | 526 | sync(); |
492 | 527 | ||
493 | /* allow time for last message to reach serial console */ | 528 | /* allow time for last message to reach serial console */ |
494 | sleep(5); | 529 | sleep(2); |
495 | 530 | ||
496 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) | 531 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) |
497 | if (sig == SIGUSR2) | 532 | if (sig == SIGUSR2) |
@@ -505,7 +540,7 @@ static void halt_signal(int sig) | |||
505 | static void reboot_signal(int sig) | 540 | static void reboot_signal(int sig) |
506 | { | 541 | { |
507 | shutdown_system(); | 542 | shutdown_system(); |
508 | message(CONSOLE, "Please stand by while rebooting the system.\r\n"); | 543 | message(CONSOLE|LOG, "Please stand by while rebooting the system.\r\n"); |
509 | sync(); | 544 | sync(); |
510 | 545 | ||
511 | /* allow time for last message to reach serial console */ | 546 | /* allow time for last message to reach serial console */ |
@@ -631,7 +666,7 @@ void new_initAction(initActionEnum action, char *process, char *cons) | |||
631 | // newAction->process, newAction->action, newAction->console); | 666 | // newAction->process, newAction->action, newAction->console); |
632 | } | 667 | } |
633 | 668 | ||
634 | void delete_initAction(initAction * action) | 669 | static void delete_initAction(initAction * action) |
635 | { | 670 | { |
636 | initAction *a, *b = NULL; | 671 | initAction *a, *b = NULL; |
637 | 672 | ||
@@ -669,6 +704,10 @@ void parse_inittab(void) | |||
669 | if (file == NULL) { | 704 | if (file == NULL) { |
670 | /* No inittab file -- set up some default behavior */ | 705 | /* No inittab file -- set up some default behavior */ |
671 | #endif | 706 | #endif |
707 | /* Swapoff on halt/reboot */ | ||
708 | new_initAction(CTRLALTDEL, "/bin/umount -a -r > /dev/null 2>&1", console); | ||
709 | /* Umount all filesystems on halt/reboot */ | ||
710 | new_initAction(CTRLALTDEL, "/bin/umount -a -r > /dev/null 2>&1", console); | ||
672 | /* Askfirst shell on tty1 */ | 711 | /* Askfirst shell on tty1 */ |
673 | new_initAction(ASKFIRST, SHELL, console); | 712 | new_initAction(ASKFIRST, SHELL, console); |
674 | /* Askfirst shell on tty2 */ | 713 | /* Askfirst shell on tty2 */ |
@@ -756,6 +795,8 @@ void parse_inittab(void) | |||
756 | #endif | 795 | #endif |
757 | } | 796 | } |
758 | 797 | ||
798 | |||
799 | |||
759 | extern int init_main(int argc, char **argv) | 800 | extern int init_main(int argc, char **argv) |
760 | { | 801 | { |
761 | initAction *a; | 802 | initAction *a; |
@@ -768,9 +809,6 @@ extern int init_main(int argc, char **argv) | |||
768 | usage("init\n\nInit is the parent of all processes.\n\n" | 809 | usage("init\n\nInit is the parent of all processes.\n\n" |
769 | "This version of init is designed to be run only by the kernel\n"); | 810 | "This version of init is designed to be run only by the kernel\n"); |
770 | } | 811 | } |
771 | /* Fix up argv[0] to be certain we claim to be init */ | ||
772 | strncpy(argv[0], "init", strlen(argv[0])); | ||
773 | |||
774 | /* Set up sig handlers -- be sure to | 812 | /* Set up sig handlers -- be sure to |
775 | * clear all of these in run() */ | 813 | * clear all of these in run() */ |
776 | signal(SIGUSR1, halt_signal); | 814 | signal(SIGUSR1, halt_signal); |
@@ -838,6 +876,10 @@ extern int init_main(int argc, char **argv) | |||
838 | * of "askfirst" shells */ | 876 | * of "askfirst" shells */ |
839 | parse_inittab(); | 877 | parse_inittab(); |
840 | } | 878 | } |
879 | |||
880 | /* Fix up argv[0] to be certain we claim to be init */ | ||
881 | strncpy(argv[0], "init", strlen(argv[0])+1); | ||
882 | strncpy(argv[1], "\0", strlen(argv[1])+1); | ||
841 | 883 | ||
842 | /* Now run everything that needs to be run */ | 884 | /* Now run everything that needs to be run */ |
843 | 885 | ||