summaryrefslogtreecommitdiff
path: root/init
diff options
context:
space:
mode:
authorGlenn L McGrath <bug1@ihug.co.nz>2003-01-13 22:09:50 +0000
committerGlenn L McGrath <bug1@ihug.co.nz>2003-01-13 22:09:50 +0000
commitb4a1baa312746a1ddc934b1ddb035b64e72e746b (patch)
treec8d05e6e83aba6139f8c91eb1ce3f62c6d96c3b9 /init
parentd66370cd7329d7d1022644c0a8213147adf8e016 (diff)
downloadbusybox-w32-b4a1baa312746a1ddc934b1ddb035b64e72e746b.tar.gz
busybox-w32-b4a1baa312746a1ddc934b1ddb035b64e72e746b.tar.bz2
busybox-w32-b4a1baa312746a1ddc934b1ddb035b64e72e746b.zip
Correct some init issues, update email address, last_patch78 by Vladimir
N. Oleynik
Diffstat (limited to 'init')
-rw-r--r--init/init.c333
1 files changed, 158 insertions, 175 deletions
diff --git a/init/init.c b/init/init.c
index 91a19c5d1..ad9ff9404 100644
--- a/init/init.c
+++ b/init/init.c
@@ -120,6 +120,8 @@ extern int bdflush(int func, long int data);
120 120
121#define MAXENV 16 /* Number of env. vars */ 121#define MAXENV 16 /* Number of env. vars */
122 122
123#define CONSOLE_BUFF_SIZE 32
124
123/* Allowed init action types */ 125/* Allowed init action types */
124#define SYSINIT 0x001 126#define SYSINIT 0x001
125#define RESPAWN 0x002 127#define RESPAWN 0x002
@@ -152,16 +154,15 @@ static const struct init_action_type actions[] = {
152struct init_action { 154struct init_action {
153 pid_t pid; 155 pid_t pid;
154 char command[INIT_BUFFS_SIZE]; 156 char command[INIT_BUFFS_SIZE];
155 char terminal[INIT_BUFFS_SIZE]; 157 char terminal[CONSOLE_BUFF_SIZE];
156 struct init_action *next; 158 struct init_action *next;
157 int action; 159 int action;
158}; 160};
159 161
160/* Static variables */ 162/* Static variables */
161static struct init_action *init_action_list = NULL; 163static struct init_action *init_action_list = NULL;
162static int kernelVersion = 0; 164static int kernelVersion;
163static char termType[32] = "TERM=linux"; 165static char console[CONSOLE_BUFF_SIZE] = _PATH_CONSOLE;
164static char console[32] = _PATH_CONSOLE;
165 166
166#ifndef CONFIG_SYSLOGD 167#ifndef CONFIG_SYSLOGD
167static char *log = VC_5; 168static char *log = VC_5;
@@ -184,9 +185,17 @@ static const int RB_DISABLE_CAD = 0;
184static const int RB_AUTOBOOT = 0x01234567; 185static const int RB_AUTOBOOT = 0x01234567;
185#endif 186#endif
186 187
188static const char * const environment[] = {
189 "HOME=/",
190 "PATH=" _PATH_STDPATH,
191 "SHELL=" SHELL,
192 "USER=root",
193 NULL
194};
195
187/* Function prototypes */ 196/* Function prototypes */
188static void delete_init_action(struct init_action *a); 197static void delete_init_action(struct init_action *a);
189static int waitfor(struct init_action *a); 198static int waitfor(const struct init_action *a);
190 199
191 200
192static void loop_forever(void) 201static void loop_forever(void)
@@ -197,38 +206,44 @@ static void loop_forever(void)
197 206
198/* Print a message to the specified device. 207/* Print a message to the specified device.
199 * Device may be bitwise-or'd from LOG | CONSOLE */ 208 * Device may be bitwise-or'd from LOG | CONSOLE */
200#ifdef DEBUG_INIT 209#ifndef DEBUG_INIT
201static inline messageND(int device, char *fmt, ...) 210static inline void messageD(int device, const char *fmt, ...)
202{ 211{
203} 212}
204#else 213#else
205#define messageND message 214#define messageD message
206#endif 215#endif
207static void message(int device, char *fmt, ...) 216static void message(int device, const char *fmt, ...)
208 __attribute__ ((format(printf, 2, 3))); 217 __attribute__ ((format(printf, 2, 3)));
209static void message(int device, char *fmt, ...) 218static void message(int device, const char *fmt, ...)
210{ 219{
211 va_list arguments; 220 va_list arguments;
212 int fd; 221 int l;
213
214#ifdef CONFIG_SYSLOGD
215
216 /* Log the message to syslogd */
217 if (device & LOG) {
218 char msg[1024]; 222 char msg[1024];
219 223
224 msg[0] = '\r';
220 va_start(arguments, fmt); 225 va_start(arguments, fmt);
221 vsnprintf(msg, sizeof(msg), fmt, arguments); 226 l = vsnprintf(msg + 1, sizeof(msg) - 2, fmt, arguments) + 1;
222 va_end(arguments); 227 va_end(arguments);
223 syslog_msg(LOG_USER, LOG_INFO, msg); 228
229#ifdef CONFIG_SYSLOGD
230 /* Log the message to syslogd */
231 if (device & LOG) {
232 /* don`t out "\r\n" */
233 syslog_msg(LOG_DAEMON, LOG_INFO, msg + 1);
224 } 234 }
235
236 msg[l++] = '\n';
237 msg[l] = 0;
225#else 238#else
226 static int log_fd = -1; 239 static int log_fd = -1;
227 240
241 msg[l++] = '\n';
242 msg[l] = 0;
228 /* Take full control of the log tty, and never close it. 243 /* Take full control of the log tty, and never close it.
229 * It's mine, all mine! Muhahahaha! */ 244 * It's mine, all mine! Muhahahaha! */
230 if (log_fd < 0) { 245 if (log_fd < 0) {
231 if ((log_fd = device_open(log, O_RDWR | O_NDELAY)) < 0) { 246 if ((log_fd = device_open(log, O_RDWR | O_NDELAY | O_NOCTTY)) < 0) {
232 log_fd = -2; 247 log_fd = -2;
233 error_msg("Bummer, can't write to log on %s!", log); 248 error_msg("Bummer, can't write to log on %s!", log);
234 device = CONSOLE; 249 device = CONSOLE;
@@ -237,26 +252,25 @@ static void message(int device, char *fmt, ...)
237 } 252 }
238 } 253 }
239 if ((device & LOG) && (log_fd >= 0)) { 254 if ((device & LOG) && (log_fd >= 0)) {
240 va_start(arguments, fmt); 255 full_write(log_fd, msg, l);
241 vdprintf(log_fd, fmt, arguments);
242 va_end(arguments);
243 } 256 }
244#endif 257#endif
245 258
246 if (device & CONSOLE) { 259 if (device & CONSOLE) {
260 int fd = device_open(_PATH_CONSOLE,
261 O_WRONLY | O_NOCTTY | O_NDELAY);
247 /* Always send console messages to /dev/console so people will see them. */ 262 /* Always send console messages to /dev/console so people will see them. */
248 if ((fd = 263 if (fd >= 0) {
249 device_open(_PATH_CONSOLE, 264 full_write(fd, msg, l);
250 O_WRONLY | O_NOCTTY | O_NDELAY)) >= 0) {
251 va_start(arguments, fmt);
252 vdprintf(fd, fmt, arguments);
253 va_end(arguments);
254 close(fd); 265 close(fd);
266#ifdef DEBUG_INIT
267 /* all descriptors may be closed */
255 } else { 268 } else {
256 error_msg("Bummer, can't print: "); 269 error_msg("Bummer, can't print: ");
257 va_start(arguments, fmt); 270 va_start(arguments, fmt);
258 vfprintf(stderr, fmt, arguments); 271 vfprintf(stderr, fmt, arguments);
259 va_end(arguments); 272 va_end(arguments);
273#endif
260 } 274 }
261 } 275 }
262} 276}
@@ -330,31 +344,23 @@ static int check_free_memory(void)
330static void console_init(void) 344static void console_init(void)
331{ 345{
332 int fd; 346 int fd;
333 int tried_devcons = 0; 347 int tried = 0;
334 int tried_vtprimary = 0;
335 struct vt_stat vt; 348 struct vt_stat vt;
336 struct serial_struct sr; 349 struct serial_struct sr;
337 char *s; 350 char *s;
338 351
339 if ((s = getenv("TERM")) != NULL) { 352 if ((s = getenv("CONSOLE")) != NULL || (s = getenv("console")) != NULL) {
340 snprintf(termType, sizeof(termType) - 1, "TERM=%s", s);
341 }
342
343 if ((s = getenv("CONSOLE")) != NULL) {
344 safe_strncpy(console, s, sizeof(console)); 353 safe_strncpy(console, s, sizeof(console));
345 }
346#if #cpu(sparc) 354#if #cpu(sparc)
347 /* sparc kernel supports console=tty[ab] parameter which is also 355 /* sparc kernel supports console=tty[ab] parameter which is also
348 * passed to init, so catch it here */ 356 * passed to init, so catch it here */
349 else if ((s = getenv("console")) != NULL) {
350 /* remap tty[ab] to /dev/ttyS[01] */ 357 /* remap tty[ab] to /dev/ttyS[01] */
351 if (strcmp(s, "ttya") == 0) 358 if (strcmp(s, "ttya") == 0)
352 safe_strncpy(console, SC_0, sizeof(console)); 359 safe_strncpy(console, SC_0, sizeof(console));
353 else if (strcmp(s, "ttyb") == 0) 360 else if (strcmp(s, "ttyb") == 0)
354 safe_strncpy(console, SC_1, sizeof(console)); 361 safe_strncpy(console, SC_1, sizeof(console));
355 }
356#endif 362#endif
357 else { 363 } else {
358 /* 2.2 kernels: identify the real console backend and try to use it */ 364 /* 2.2 kernels: identify the real console backend and try to use it */
359 if (ioctl(0, TIOCGSERIAL, &sr) == 0) { 365 if (ioctl(0, TIOCGSERIAL, &sr) == 0) {
360 /* this is a serial console */ 366 /* this is a serial console */
@@ -364,39 +370,41 @@ static void console_init(void)
364 snprintf(console, sizeof(console) - 1, VC_FORMAT, vt.v_active); 370 snprintf(console, sizeof(console) - 1, VC_FORMAT, vt.v_active);
365 } else { 371 } else {
366 safe_strncpy(console, _PATH_CONSOLE, sizeof(console)); 372 safe_strncpy(console, _PATH_CONSOLE, sizeof(console));
367 tried_devcons++; 373 tried++;
368 } 374 }
369 } 375 }
370 376
371 while ((fd = open(console, O_RDONLY | O_NONBLOCK)) < 0) { 377 while ((fd = open(console, O_RDONLY | O_NONBLOCK)) < 0 && tried < 2) {
372 /* Can't open selected console -- try /dev/console */ 378 /* Can't open selected console -- try
373 if (!tried_devcons) { 379 logical system console and VT_MASTER */
374 tried_devcons++; 380 safe_strncpy(console, (tried == 0 ? _PATH_CONSOLE : CURRENT_VC),
375 safe_strncpy(console, _PATH_CONSOLE, sizeof(console)); 381 sizeof(console));
376 continue; 382 tried++;
377 }
378 /* Can't open selected console -- try vt1 */
379 if (!tried_vtprimary) {
380 tried_vtprimary++;
381 safe_strncpy(console, VC_1, sizeof(console));
382 continue;
383 }
384 break;
385 } 383 }
386 if (fd < 0) { 384 if (fd < 0) {
387 /* Perhaps we should panic here? */ 385 /* Perhaps we should panic here? */
386#ifndef CONFIG_SYSLOGD
387 log =
388#endif
388 safe_strncpy(console, "/dev/null", sizeof(console)); 389 safe_strncpy(console, "/dev/null", sizeof(console));
389 } else { 390 } else {
391 s = getenv("TERM");
390 /* check for serial console */ 392 /* check for serial console */
391 if (ioctl(0, TIOCGSERIAL, &sr) == 0) { 393 if (ioctl(fd, TIOCGSERIAL, &sr) == 0) {
392 /* Force the TERM setting to vt102 for serial console -- 394 /* Force the TERM setting to vt102 for serial console --
393 * if TERM is set to linux (the default) */ 395 * if TERM is set to linux (the default) */
394 if (strcmp(termType, "TERM=linux") == 0) 396 if (s == NULL || strcmp(s, "linux") == 0)
395 safe_strncpy(termType, "TERM=vt102", sizeof(termType)); 397 putenv("TERM=vt102");
398#ifndef CONFIG_SYSLOGD
399 log = console;
400#endif
401 } else {
402 if (s == NULL)
403 putenv("TERM=linux");
396 } 404 }
397 close(fd); 405 close(fd);
398 } 406 }
399 message(LOG, "console=%s\n", console); 407 messageD(LOG, "console=%s", console);
400} 408}
401 409
402static void fixup_argv(int argc, char **argv, char *new_argv0) 410static void fixup_argv(int argc, char **argv, char *new_argv0)
@@ -416,68 +424,20 @@ static void fixup_argv(int argc, char **argv, char *new_argv0)
416 } 424 }
417} 425}
418 426
419/* Make sure there is enough memory to do something useful. * 427static pid_t run(const struct init_action *a)
420 * Calls "swapon -a" if needed so be sure /etc/fstab is present... */
421static void check_memory(void)
422{
423 struct stat statBuf;
424
425 if (check_free_memory() > 1000)
426 return;
427
428#if !defined(__UCLIBC__) || defined(__UCLIBC_HAS_MMU__)
429 if (stat("/etc/fstab", &statBuf) == 0) {
430 /* swapon -a requires /proc typically */
431 system("/bin/mount -t proc proc /proc");
432 /* Try to turn on swap */
433 system("/sbin/swapon -a");
434 if (check_free_memory() < 1000)
435 goto goodnight;
436 } else
437 goto goodnight;
438 return;
439#endif
440
441 goodnight:
442 message(CONSOLE, "\rSorry, your computer does not have enough memory.\n");
443 loop_forever();
444}
445
446static pid_t run(struct init_action *a)
447{ 428{
448 struct stat sb; 429 struct stat sb;
449 int i, j, junk; 430 int i, junk;
450 pid_t pid, pgrp, tmp_pid; 431 pid_t pid, pgrp, tmp_pid;
451 char *s, *tmpCmd, *cmd[INIT_BUFFS_SIZE], *cmdpath; 432 char *s, *tmpCmd, *cmd[INIT_BUFFS_SIZE], *cmdpath;
452 char buf[INIT_BUFFS_SIZE + 6]; /* INIT_BUFFS_SIZE+strlen("exec ")+1 */ 433 char buf[INIT_BUFFS_SIZE + 6]; /* INIT_BUFFS_SIZE+strlen("exec ")+1 */
453 sigset_t nmask, omask; 434 sigset_t nmask, omask;
454 char *environment[MAXENV + 1] = {
455 termType,
456 "HOME=/",
457 "PATH=" _PATH_STDPATH,
458 "SHELL=" SHELL,
459 "USER=root",
460 NULL
461 };
462 static const char press_enter[] = 435 static const char press_enter[] =
463#ifdef CUSTOMIZED_BANNER 436#ifdef CUSTOMIZED_BANNER
464#include CUSTOMIZED_BANNER 437#include CUSTOMIZED_BANNER
465#endif 438#endif
466 "\nPlease press Enter to activate this console. "; 439 "\nPlease press Enter to activate this console. ";
467 440
468 /* inherit environment to the child, merging our values -andy */
469 for (i = 0; environ[i]; i++) {
470 for (j = 0; environment[j]; j++) {
471 s = strchr(environment[j], '=');
472 if (!strncmp(environ[i], environment[j], s - environment[j]))
473 break;
474 }
475 if (!environment[j]) {
476 environment[j++] = environ[i];
477 environment[j] = NULL;
478 }
479 }
480
481 /* Block sigchild while forking. */ 441 /* Block sigchild while forking. */
482 sigemptyset(&nmask); 442 sigemptyset(&nmask);
483 sigaddset(&nmask, SIGCHLD); 443 sigaddset(&nmask, SIGCHLD);
@@ -507,11 +467,11 @@ static pid_t run(struct init_action *a)
507 /* Open the new terminal device */ 467 /* Open the new terminal device */
508 if ((device_open(a->terminal, O_RDWR)) < 0) { 468 if ((device_open(a->terminal, O_RDWR)) < 0) {
509 if (stat(a->terminal, &sb) != 0) { 469 if (stat(a->terminal, &sb) != 0) {
510 message(LOG | CONSOLE, "\rdevice '%s' does not exist.\n", 470 message(LOG | CONSOLE, "device '%s' does not exist.",
511 a->terminal); 471 a->terminal);
512 _exit(1); 472 _exit(1);
513 } 473 }
514 message(LOG | CONSOLE, "\rBummer, can't open %s\n", a->terminal); 474 message(LOG | CONSOLE, "Bummer, can't open %s", a->terminal);
515 _exit(1); 475 _exit(1);
516 } 476 }
517 477
@@ -528,7 +488,7 @@ static pid_t run(struct init_action *a)
528 488
529 /* Now fork off another process to just hang around */ 489 /* Now fork off another process to just hang around */
530 if ((pid = fork()) < 0) { 490 if ((pid = fork()) < 0) {
531 message(LOG | CONSOLE, "Can't fork!\n"); 491 message(LOG | CONSOLE, "Can't fork!");
532 _exit(1); 492 _exit(1);
533 } 493 }
534 494
@@ -550,7 +510,7 @@ static pid_t run(struct init_action *a)
550 510
551 /* Use a temporary process to steal the controlling tty. */ 511 /* Use a temporary process to steal the controlling tty. */
552 if ((pid = fork()) < 0) { 512 if ((pid = fork()) < 0) {
553 message(LOG | CONSOLE, "\rCan't fork!\n"); 513 message(LOG | CONSOLE, "Can't fork!");
554 _exit(1); 514 _exit(1);
555 } 515 }
556 if (pid == 0) { 516 if (pid == 0) {
@@ -572,8 +532,7 @@ static pid_t run(struct init_action *a)
572 if (strpbrk(a->command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) { 532 if (strpbrk(a->command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) {
573 cmd[0] = SHELL; 533 cmd[0] = SHELL;
574 cmd[1] = "-c"; 534 cmd[1] = "-c";
575 strcat(strcpy(buf, "exec "), a->command); 535 cmd[2] = strcat(strcpy(buf, "exec "), a->command);
576 cmd[2] = buf;
577 cmd[3] = NULL; 536 cmd[3] = NULL;
578 } else { 537 } else {
579 /* Convert command (char*) into cmd (char**, one word per string) */ 538 /* Convert command (char*) into cmd (char**, one word per string) */
@@ -607,7 +566,7 @@ static pid_t run(struct init_action *a)
607 566
608 /* make a new argv[0] */ 567 /* make a new argv[0] */
609 if ((cmd[0] = malloc(strlen(s) + 2)) == NULL) { 568 if ((cmd[0] = malloc(strlen(s) + 2)) == NULL) {
610 message(LOG | CONSOLE, "malloc failed"); 569 message(LOG | CONSOLE, memory_exhausted);
611 cmd[0] = cmdpath; 570 cmd[0] = cmdpath;
612 } else { 571 } else {
613 cmd[0][0] = '-'; 572 cmd[0][0] = '-';
@@ -616,6 +575,7 @@ static pid_t run(struct init_action *a)
616 } 575 }
617 576
618 if (a->action & ASKFIRST) { 577 if (a->action & ASKFIRST) {
578 char c;
619 /* 579 /*
620 * Save memory by not exec-ing anything large (like a shell) 580 * Save memory by not exec-ing anything large (like a shell)
621 * before the user wants it. This is critical if swap is not 581 * before the user wants it. This is critical if swap is not
@@ -624,16 +584,16 @@ static pid_t run(struct init_action *a)
624 * be allowed to start a shell or whatever an init script 584 * be allowed to start a shell or whatever an init script
625 * specifies. 585 * specifies.
626 */ 586 */
627 messageND(LOG, 587 messageD(LOG, "Waiting for enter to start '%s'"
628 "Waiting for enter to start '%s' (pid %d, terminal %s)\n", 588 "(pid %d, terminal %s)\n",
629 cmdpath, getpid(), a->terminal); 589 cmdpath, getpid(), a->terminal);
630 fflush(stdout); 590 full_write(1, press_enter, sizeof(press_enter) - 1);
631 write(fileno(stdout), press_enter, sizeof(press_enter) - 1); 591 while(read(0, &c, 1) == 1 && c != '\n')
632 getc(stdin); 592 ;
633 } 593 }
634 594
635 /* Log the process name and args */ 595 /* Log the process name and args */
636 messageND(LOG, "Starting pid %d, console %s: '%s'\n", 596 message(LOG, "Starting pid %d, console %s: '%s'",
637 getpid(), a->terminal, cmdpath); 597 getpid(), a->terminal, cmdpath);
638 598
639#if defined CONFIG_FEATURE_INIT_COREDUMPS 599#if defined CONFIG_FEATURE_INIT_COREDUMPS
@@ -648,17 +608,17 @@ static pid_t run(struct init_action *a)
648 608
649 /* Now run it. The new program will take over this PID, 609 /* Now run it. The new program will take over this PID,
650 * so nothing further in init.c should be run. */ 610 * so nothing further in init.c should be run. */
651 execve(cmdpath, cmd, environment); 611 execv(cmdpath, cmd);
652 612
653 /* We're still here? Some error happened. */ 613 /* We're still here? Some error happened. */
654 message(LOG | CONSOLE, "\rBummer, could not run '%s': %m\n", cmdpath); 614 message(LOG | CONSOLE, "Bummer, could not run '%s': %m", cmdpath);
655 _exit(-1); 615 _exit(-1);
656 } 616 }
657 sigprocmask(SIG_SETMASK, &omask, NULL); 617 sigprocmask(SIG_SETMASK, &omask, NULL);
658 return pid; 618 return pid;
659} 619}
660 620
661static int waitfor(struct init_action *a) 621static int waitfor(const struct init_action *a)
662{ 622{
663 int pid; 623 int pid;
664 int status, wpid; 624 int status, wpid;
@@ -700,7 +660,6 @@ static void run_actions(int action)
700 } 660 }
701} 661}
702 662
703
704#ifndef DEBUG_INIT 663#ifndef DEBUG_INIT
705static void shutdown_system(void) 664static void shutdown_system(void)
706{ 665{
@@ -727,16 +686,16 @@ static void shutdown_system(void)
727 /* Allow Ctrl-Alt-Del to reboot system. */ 686 /* Allow Ctrl-Alt-Del to reboot system. */
728 init_reboot(RB_ENABLE_CAD); 687 init_reboot(RB_ENABLE_CAD);
729 688
730 message(CONSOLE | LOG, "\n\rThe system is going down NOW !!\n"); 689 message(CONSOLE | LOG, "The system is going down NOW !!");
731 sync(); 690 sync();
732 691
733 /* Send signals to every process _except_ pid 1 */ 692 /* Send signals to every process _except_ pid 1 */
734 message(CONSOLE | LOG, "\rSending SIGTERM to all processes.\n"); 693 message(CONSOLE | LOG, "Sending SIGTERM to all processes.");
735 kill(-1, SIGTERM); 694 kill(-1, SIGTERM);
736 sleep(1); 695 sleep(1);
737 sync(); 696 sync();
738 697
739 message(CONSOLE | LOG, "\rSending SIGKILL to all processes.\n"); 698 message(CONSOLE | LOG, "Sending SIGKILL to all processes.");
740 kill(-1, SIGKILL); 699 kill(-1, SIGKILL);
741 sleep(1); 700 sleep(1);
742 701
@@ -771,10 +730,10 @@ static void exec_signal(int sig)
771 sigaddset(&unblock_signals, SIGTSTP); 730 sigaddset(&unblock_signals, SIGTSTP);
772 sigprocmask(SIG_UNBLOCK, &unblock_signals, NULL); 731 sigprocmask(SIG_UNBLOCK, &unblock_signals, NULL);
773 732
774 message(CONSOLE | LOG, "\rTrying to re-exec %s\n", a->command); 733 messageD(CONSOLE | LOG, "Trying to re-exec %s", a->command);
775 execl(a->command, a->command, NULL); 734 execl(a->command, a->command, NULL);
776 735
777 message(CONSOLE | LOG, "\rexec of '%s' failed: %m\n", 736 message(CONSOLE | LOG, "exec of '%s' failed: %m",
778 a->command); 737 a->command);
779 sync(); 738 sync();
780 sleep(2); 739 sleep(2);
@@ -790,9 +749,9 @@ static void halt_signal(int sig)
790 message(CONSOLE | LOG, 749 message(CONSOLE | LOG,
791#if #cpu(s390) 750#if #cpu(s390)
792 /* Seems the s390 console is Wierd(tm). */ 751 /* Seems the s390 console is Wierd(tm). */
793 "\rThe system is halted. You may reboot now.\n" 752 "The system is halted. You may reboot now."
794#else 753#else
795 "\rThe system is halted. Press Reset or turn off power\n" 754 "The system is halted. Press Reset or turn off power"
796#endif 755#endif
797 ); 756 );
798 sync(); 757 sync();
@@ -811,7 +770,7 @@ static void halt_signal(int sig)
811static void reboot_signal(int sig) 770static void reboot_signal(int sig)
812{ 771{
813 shutdown_system(); 772 shutdown_system();
814 message(CONSOLE | LOG, "\rPlease stand by while rebooting the system.\n"); 773 message(CONSOLE | LOG, "Please stand by while rebooting the system.");
815 sync(); 774 sync();
816 775
817 /* allow time for last message to reach serial console */ 776 /* allow time for last message to reach serial console */
@@ -847,7 +806,7 @@ static void cont_handler(int sig)
847 806
848#endif /* ! DEBUG_INIT */ 807#endif /* ! DEBUG_INIT */
849 808
850static void new_init_action(int action, char *command, char *cons) 809static void new_init_action(int action, char *command, const char *cons)
851{ 810{
852 struct init_action *new_action, *a; 811 struct init_action *new_action, *a;
853 812
@@ -862,7 +821,7 @@ static void new_init_action(int action, char *command, char *cons)
862 821
863 new_action = calloc((size_t) (1), sizeof(struct init_action)); 822 new_action = calloc((size_t) (1), sizeof(struct init_action));
864 if (!new_action) { 823 if (!new_action) {
865 message(LOG | CONSOLE, "\rMemory allocation failure\n"); 824 message(LOG | CONSOLE, "Memory allocation failure");
866 loop_forever(); 825 loop_forever();
867 } 826 }
868 827
@@ -876,9 +835,11 @@ static void new_init_action(int action, char *command, char *cons)
876 strcpy(new_action->command, command); 835 strcpy(new_action->command, command);
877 new_action->action = action; 836 new_action->action = action;
878 strcpy(new_action->terminal, cons); 837 strcpy(new_action->terminal, cons);
838#if 0 /* calloc zeroed always */
879 new_action->pid = 0; 839 new_action->pid = 0;
880/* message(LOG|CONSOLE, "command='%s' action='%d' terminal='%s'\n", 840#endif
881 new_action->command, new_action->action, new_action->terminal); */ 841 messageD(LOG|CONSOLE, "command='%s' action='%d' terminal='%s'\n",
842 new_action->command, new_action->action, new_action->terminal);
882} 843}
883 844
884static void delete_init_action(struct init_action *action) 845static void delete_init_action(struct init_action *action)
@@ -898,6 +859,34 @@ static void delete_init_action(struct init_action *action)
898 } 859 }
899} 860}
900 861
862/* Make sure there is enough memory to do something useful. *
863 * Calls "swapon -a" if needed so be sure /etc/fstab is present... */
864static void check_memory(void)
865{
866 struct stat statBuf;
867
868 if (check_free_memory() > 1000)
869 return;
870
871#if !defined(__UCLIBC__) || defined(__UCLIBC_HAS_MMU__)
872 if (stat("/etc/fstab", &statBuf) == 0) {
873 /* swapon -a requires /proc typically */
874 new_init_action(SYSINIT, "/bin/mount -t proc proc /proc", "");
875 /* Try to turn on swap */
876 new_init_action(SYSINIT, "/sbin/swapon -a", "");
877 run_actions(SYSINIT); /* wait and removing */
878 if (check_free_memory() < 1000)
879 goto goodnight;
880 } else
881 goto goodnight;
882 return;
883#endif
884
885 goodnight:
886 message(CONSOLE, "Sorry, your computer does not have enough memory.");
887 loop_forever();
888}
889
901/* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined, 890/* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined,
902 * then parse_inittab() simply adds in some default 891 * then parse_inittab() simply adds in some default
903 * actions(i.e., runs INIT_SCRIPT and then starts a pair 892 * actions(i.e., runs INIT_SCRIPT and then starts a pair
@@ -909,11 +898,10 @@ static void parse_inittab(void)
909{ 898{
910#ifdef CONFIG_FEATURE_USE_INITTAB 899#ifdef CONFIG_FEATURE_USE_INITTAB
911 FILE *file; 900 FILE *file;
912 char buf[INIT_BUFFS_SIZE], lineAsRead[INIT_BUFFS_SIZE], 901 char buf[INIT_BUFFS_SIZE], lineAsRead[INIT_BUFFS_SIZE];
913 tmpConsole[INIT_BUFFS_SIZE]; 902 char tmpConsole[CONSOLE_BUFF_SIZE];
914 char *id, *runlev, *action, *command, *eol; 903 char *id, *runlev, *action, *command, *eol;
915 const struct init_action_type *a = actions; 904 const struct init_action_type *a = actions;
916 int foundIt;
917 905
918 906
919 file = fopen(INITTAB, "r"); 907 file = fopen(INITTAB, "r");
@@ -921,29 +909,28 @@ static void parse_inittab(void)
921 /* No inittab file -- set up some default behavior */ 909 /* No inittab file -- set up some default behavior */
922#endif 910#endif
923 /* Reboot on Ctrl-Alt-Del */ 911 /* Reboot on Ctrl-Alt-Del */
924 new_init_action(CTRLALTDEL, "/sbin/reboot", console); 912 new_init_action(CTRLALTDEL, "/sbin/reboot", "");
925 /* Umount all filesystems on halt/reboot */ 913 /* Umount all filesystems on halt/reboot */
926 new_init_action(SHUTDOWN, "/bin/umount -a -r", console); 914 new_init_action(SHUTDOWN, "/bin/umount -a -r", "");
927#if !defined(__UCLIBC__) || defined(__UCLIBC_HAS_MMU__) 915#if !defined(__UCLIBC__) || defined(__UCLIBC_HAS_MMU__)
928 /* Swapoff on halt/reboot */ 916 /* Swapoff on halt/reboot */
929 new_init_action(SHUTDOWN, "/sbin/swapoff -a", console); 917 new_init_action(SHUTDOWN, "/sbin/swapoff -a", "");
930#endif 918#endif
931 /* Prepare to restart init when a HUP is received */ 919 /* Prepare to restart init when a HUP is received */
932 new_init_action(RESTART, "/sbin/init", console); 920 new_init_action(RESTART, "/sbin/init", "");
933 /* Askfirst shell on tty1-4 */ 921 /* Askfirst shell on tty1-4 */
934 new_init_action(ASKFIRST, LOGIN_SHELL, console); 922 new_init_action(ASKFIRST, LOGIN_SHELL, "");
935 new_init_action(ASKFIRST, LOGIN_SHELL, VC_2); 923 new_init_action(ASKFIRST, LOGIN_SHELL, VC_2);
936 new_init_action(ASKFIRST, LOGIN_SHELL, VC_3); 924 new_init_action(ASKFIRST, LOGIN_SHELL, VC_3);
937 new_init_action(ASKFIRST, LOGIN_SHELL, VC_4); 925 new_init_action(ASKFIRST, LOGIN_SHELL, VC_4);
938 /* sysinit */ 926 /* sysinit */
939 new_init_action(SYSINIT, INIT_SCRIPT, console); 927 new_init_action(SYSINIT, INIT_SCRIPT, "");
940 928
941 return; 929 return;
942#ifdef CONFIG_FEATURE_USE_INITTAB 930#ifdef CONFIG_FEATURE_USE_INITTAB
943 } 931 }
944 932
945 while (fgets(buf, INIT_BUFFS_SIZE, file) != NULL) { 933 while (fgets(buf, INIT_BUFFS_SIZE, file) != NULL) {
946 foundIt = FALSE;
947 /* Skip leading spaces */ 934 /* Skip leading spaces */
948 for (id = buf; *id == ' ' || *id == '\t'; id++); 935 for (id = buf; *id == ' ' || *id == '\t'; id++);
949 936
@@ -962,7 +949,7 @@ static void parse_inittab(void)
962 /* Separate the ID field from the runlevels */ 949 /* Separate the ID field from the runlevels */
963 runlev = strchr(id, ':'); 950 runlev = strchr(id, ':');
964 if (runlev == NULL || *(runlev + 1) == '\0') { 951 if (runlev == NULL || *(runlev + 1) == '\0') {
965 message(LOG | CONSOLE, "\rBad inittab entry: %s\n", lineAsRead); 952 message(LOG | CONSOLE, "Bad inittab entry: %s", lineAsRead);
966 continue; 953 continue;
967 } else { 954 } else {
968 *runlev = '\0'; 955 *runlev = '\0';
@@ -972,7 +959,7 @@ static void parse_inittab(void)
972 /* Separate the runlevels from the action */ 959 /* Separate the runlevels from the action */
973 action = strchr(runlev, ':'); 960 action = strchr(runlev, ':');
974 if (action == NULL || *(action + 1) == '\0') { 961 if (action == NULL || *(action + 1) == '\0') {
975 message(LOG | CONSOLE, "\rBad inittab entry: %s\n", lineAsRead); 962 message(LOG | CONSOLE, "Bad inittab entry: %s", lineAsRead);
976 continue; 963 continue;
977 } else { 964 } else {
978 *action = '\0'; 965 *action = '\0';
@@ -982,7 +969,7 @@ static void parse_inittab(void)
982 /* Separate the action from the command */ 969 /* Separate the action from the command */
983 command = strchr(action, ':'); 970 command = strchr(action, ':');
984 if (command == NULL || *(command + 1) == '\0') { 971 if (command == NULL || *(command + 1) == '\0') {
985 message(LOG | CONSOLE, "\rBad inittab entry: %s\n", lineAsRead); 972 message(LOG | CONSOLE, "Bad inittab entry: %s", lineAsRead);
986 continue; 973 continue;
987 } else { 974 } else {
988 *command = '\0'; 975 *command = '\0';
@@ -990,24 +977,23 @@ static void parse_inittab(void)
990 } 977 }
991 978
992 /* Ok, now process it */ 979 /* Ok, now process it */
993 a = actions; 980 for (a = actions; a->name != 0; a++) {
994 while (a->name != 0) {
995 if (strcmp(a->name, action) == 0) { 981 if (strcmp(a->name, action) == 0) {
996 if (*id != '\0') { 982 if (*id != '\0') {
983 if(strncmp(id, "/dev/", 5) == 0)
984 id += 5;
997 strcpy(tmpConsole, "/dev/"); 985 strcpy(tmpConsole, "/dev/");
998 strncat(tmpConsole, id, INIT_BUFFS_SIZE - 6); 986 safe_strncpy(tmpConsole + 5, id,
987 CONSOLE_BUFF_SIZE - 5);
999 id = tmpConsole; 988 id = tmpConsole;
1000 } 989 }
1001 new_init_action(a->action, command, id); 990 new_init_action(a->action, command, id);
1002 foundIt = TRUE; 991 break;
1003 } 992 }
1004 a++;
1005 } 993 }
1006 if (foundIt == TRUE) 994 if (a->name == 0) {
1007 continue;
1008 else {
1009 /* Choke on an unknown action */ 995 /* Choke on an unknown action */
1010 message(LOG | CONSOLE, "\rBad inittab entry: %s\n", lineAsRead); 996 message(LOG | CONSOLE, "Bad inittab entry: %s", lineAsRead);
1011 } 997 }
1012 } 998 }
1013 fclose(file); 999 fclose(file);
@@ -1016,7 +1002,6 @@ static void parse_inittab(void)
1016} 1002}
1017 1003
1018 1004
1019
1020extern int init_main(int argc, char **argv) 1005extern int init_main(int argc, char **argv)
1021{ 1006{
1022 struct init_action *a; 1007 struct init_action *a;
@@ -1032,8 +1017,7 @@ extern int init_main(int argc, char **argv)
1032 if (!pid || *pid <= 0) 1017 if (!pid || *pid <= 0)
1033 error_msg_and_die("no process killed"); 1018 error_msg_and_die("no process killed");
1034 } 1019 }
1035 kill(*pid, SIGHUP); 1020 return kill(*pid, SIGHUP);
1036 exit(0);
1037 } 1021 }
1038#ifndef DEBUG_INIT 1022#ifndef DEBUG_INIT
1039 /* Expect to be invoked as init with PID=1 or be invoked as linuxrc */ 1023 /* Expect to be invoked as init with PID=1 or be invoked as linuxrc */
@@ -1078,12 +1062,14 @@ extern int init_main(int argc, char **argv)
1078 1062
1079 chdir("/"); 1063 chdir("/");
1080 setsid(); 1064 setsid();
1081 1065 {
1082 /* Make sure PATH is set to something sane */ 1066 const char * const *e;
1083 putenv("PATH=" _PATH_STDPATH); 1067 /* Make sure environs is set to something sane */
1084 1068 for(e = environment; *e; e++)
1069 putenv(*e);
1070 }
1085 /* Hello world */ 1071 /* Hello world */
1086 message(MAYBE_CONSOLE | LOG, "\rinit started: %s\n", full_version); 1072 message(MAYBE_CONSOLE | LOG, "init started: %s", full_version);
1087 1073
1088 /* Make sure there is enough memory to do something useful. */ 1074 /* Make sure there is enough memory to do something useful. */
1089 check_memory(); 1075 check_memory();
@@ -1091,12 +1077,8 @@ extern int init_main(int argc, char **argv)
1091 /* Check if we are supposed to be in single user mode */ 1077 /* Check if we are supposed to be in single user mode */
1092 if (argc > 1 && (!strcmp(argv[1], "single") || 1078 if (argc > 1 && (!strcmp(argv[1], "single") ||
1093 !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) { 1079 !strcmp(argv[1], "-s") || !strcmp(argv[1], "1"))) {
1094 /* Ask first then start a shell on tty2-4 */ 1080 /* Start a shell on console */
1095 new_init_action(ASKFIRST, LOGIN_SHELL, VC_2); 1081 new_init_action(RESPAWN, LOGIN_SHELL, "");
1096 new_init_action(ASKFIRST, LOGIN_SHELL, VC_3);
1097 new_init_action(ASKFIRST, LOGIN_SHELL, VC_4);
1098 /* Start a shell on tty1 */
1099 new_init_action(RESPAWN, LOGIN_SHELL, console);
1100 } else { 1082 } else {
1101 /* Not in single user mode -- see what inittab says */ 1083 /* Not in single user mode -- see what inittab says */
1102 1084
@@ -1124,7 +1106,7 @@ extern int init_main(int argc, char **argv)
1124 /* If there is nothing else to do, stop */ 1106 /* If there is nothing else to do, stop */
1125 if (init_action_list == NULL) { 1107 if (init_action_list == NULL) {
1126 message(LOG | CONSOLE, 1108 message(LOG | CONSOLE,
1127 "\rNo more tasks for init -- sleeping forever.\n"); 1109 "No more tasks for init -- sleeping forever.");
1128 loop_forever(); 1110 loop_forever();
1129 } 1111 }
1130 1112
@@ -1149,7 +1131,8 @@ extern int init_main(int argc, char **argv)
1149 * restarted by run_actions() */ 1131 * restarted by run_actions() */
1150 a->pid = 0; 1132 a->pid = 0;
1151 message(LOG, "Process '%s' (pid %d) exited. " 1133 message(LOG, "Process '%s' (pid %d) exited. "
1152 "Scheduling it for restart.\n", a->command, wpid); 1134 "Scheduling it for restart.",
1135 a->command, wpid);
1153 } 1136 }
1154 } 1137 }
1155 /* see if anyone else is waiting to be reaped */ 1138 /* see if anyone else is waiting to be reaped */