aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2002-03-05 15:12:19 +0000
committerEric Andersen <andersen@codepoet.org>2002-03-05 15:12:19 +0000
commit0298be88aece2a10b04c71db34fb154bdbbc45c9 (patch)
tree1cf3eb885a205ee40713b468a0b9a7687fa84cc5
parent684d745bf3551a0539b4e678b3d3de4f4f800c7a (diff)
downloadbusybox-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.c491
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> */
52struct vt_stat { 55struct 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
86static const int RB_HALT_SYSTEM = 0xcdef0123;
87static const int RB_ENABLE_CAD = 0x89abcdef;
88static const int RB_DISABLE_CAD = 0;
89#define RB_POWER_OFF 0x4321fedc
90static 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 */
128static const int LOG = 0x1;
129static const int CONSOLE = 0x2;
130#if defined BB_FEATURE_EXTRA_QUIET
131static 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 */
138typedef 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. */
150typedef struct initActionType { 132struct init_action_type {
151 const char *name; 133 const char *name;
152 initActionEnum action; 134 int action;
153} initActionType; 135};
154 136
155static const struct initActionType actions[] = { 137static 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 */
168typedef struct initActionTag initAction; 150struct init_action {
169struct 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};
176static initAction *initActionList = NULL;
177
178 157
158/* Static variables */
159static struct init_action *init_action_list = NULL;
179static char *secondConsole = VC_2; 160static char *secondConsole = VC_2;
180static char *thirdConsole = VC_3; 161static char *thirdConsole = VC_3;
181static char *fourthConsole = VC_4; 162static char *fourthConsole = VC_4;
@@ -183,9 +164,26 @@ static char *log = VC_5;
183static int kernelVersion = 0; 164static int kernelVersion = 0;
184static char termType[32] = "TERM=linux"; 165static char termType[32] = "TERM=linux";
185static char console[32] = _PATH_CONSOLE; 166static char console[32] = _PATH_CONSOLE;
186sig_atomic_t got_cont = 0; 167static sig_atomic_t got_cont = 0;
168static const int LOG = 0x1;
169static const int CONSOLE = 0x2;
170#if defined BB_FEATURE_EXTRA_QUIET
171static const int MAYBE_CONSOLE = 0x0;
172#else
173#define MAYBE_CONSOLE CONSOLE
174#endif
175#ifndef RB_HALT_SYSTEM
176static const int RB_HALT_SYSTEM = 0xcdef0123;
177static const int RB_ENABLE_CAD = 0x89abcdef;
178static const int RB_DISABLE_CAD = 0;
179#define RB_POWER_OFF 0x4321fedc
180static const int RB_AUTOBOOT = 0x01234567;
181#endif
182
183/* Function prototypes */
184static void delete_init_action(struct init_action *a);
185static int waitfor(struct init_action *a);
187 186
188static void delete_initAction(initAction * action);
189 187
190static void loop_forever(void) 188static 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
203static void message(int device, char *fmt, ...) 201static void message(int device, char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
204 __attribute__ ((format (printf, 2, 3)));
205static void message(int device, char *fmt, ...) 202static 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. *
422static pid_t run(char *command, char *terminal, int get_enter) 418 * Calls "swapon -a" if needed so be sure /etc/fstab is present... */
419static 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
445static 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
590static int waitfor(char *command, char *terminal, int get_enter) 670static 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... */ 688static void run_actions(int action)
608static 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 */
635static 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
693static void exec_signal(int sig) 758static 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 */
761static void stop_handler(int sig) 824static 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 */
774static void cont_handler(int sig) 835static 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
781static void new_initAction(initActionEnum action, char *process, char *cons) 842static 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
818static void delete_initAction(initAction * action) 880static 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
958extern int init_main(int argc, char **argv) 1020extern 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