aboutsummaryrefslogtreecommitdiff
path: root/init/init.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-02-19 02:57:07 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-02-19 02:57:07 +0000
commita37e7134f76b7661b86bb9cc926f28f81b1e1109 (patch)
tree88c511c1f1094c3c4207523e31db5fdf7bda6069 /init/init.c
parent92657d484f4f95ce4579ad095c9caf596a737e5b (diff)
downloadbusybox-w32-a37e7134f76b7661b86bb9cc926f28f81b1e1109.tar.gz
busybox-w32-a37e7134f76b7661b86bb9cc926f28f81b1e1109.tar.bz2
busybox-w32-a37e7134f76b7661b86bb9cc926f28f81b1e1109.zip
init: fix bug 1111: restart actions were not splitting words:
::restart:/sbin/rc restart resulted in: exec of '/sbin/rc restart' failed: No such file or directory
Diffstat (limited to 'init/init.c')
-rw-r--r--init/init.c189
1 files changed, 87 insertions, 102 deletions
diff --git a/init/init.c b/init/init.c
index 080c5b3af..8d706fe1f 100644
--- a/init/init.c
+++ b/init/init.c
@@ -14,7 +14,7 @@
14#include <paths.h> 14#include <paths.h>
15#include <sys/reboot.h> 15#include <sys/reboot.h>
16 16
17#define INIT_BUFFS_SIZE 256 17#define COMMAND_SIZE 256
18#define CONSOLE_NAME_SIZE 32 18#define CONSOLE_NAME_SIZE 32
19#define MAXENV 16 /* Number of env. vars */ 19#define MAXENV 16 /* Number of env. vars */
20 20
@@ -55,9 +55,9 @@
55struct init_action { 55struct init_action {
56 struct init_action *next; 56 struct init_action *next;
57 pid_t pid; 57 pid_t pid;
58 uint8_t action; 58 uint8_t action_type;
59 char terminal[CONSOLE_NAME_SIZE]; 59 char terminal[CONSOLE_NAME_SIZE];
60 char command[INIT_BUFFS_SIZE]; 60 char command[COMMAND_SIZE];
61}; 61};
62 62
63/* Static variables */ 63/* Static variables */
@@ -294,14 +294,57 @@ static void open_stdio_to_tty(const char* tty_name, int exit_on_failure)
294 set_sane_term(); 294 set_sane_term();
295} 295}
296 296
297/* wrapper around exec:
298 * takes string (max COMMAND_SIZE chars)
299 * runs [-]/bin/sh -c "exec ......." if '>' etc detected.
300 * otherwise splits words on whitespace and deals with leading dash.
301 */
302static void init_exec(const char *command)
303{
304 char *cmd[COMMAND_SIZE / 2];
305 char buf[COMMAND_SIZE + 6]; /* COMMAND_SIZE+strlen("exec ")+1 */
306 int dash = (command[0] == '-');
307
308 /* See if any special /bin/sh requiring characters are present */
309 if (strpbrk(command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) {
310 strcpy(buf, "exec ");
311 strcpy(buf + 5, command + dash); /* excluding "-" */
312 /* LIBBB_DEFAULT_LOGIN_SHELL has leading dash */
313 cmd[0] = (char*)(LIBBB_DEFAULT_LOGIN_SHELL + !dash);
314 cmd[1] = (char*)"-c";
315 cmd[2] = buf;
316 cmd[3] = NULL;
317 } else {
318 /* Convert command (char*) into cmd (char**, one word per string) */
319 char *word, *next;
320 int i = 0;
321 next = strcpy(buf, command); /* including "-" */
322 while ((word = strsep(&next, " \t")) != NULL) {
323 if (*word != '\0') { /* not two spaces/tabs together? */
324 cmd[i] = word;
325 i++;
326 }
327 }
328 cmd[i] = NULL;
329 }
330 /* If we saw leading "-", it is interactive shell.
331 * Try harder to give it a controlling tty.
332 * And skip "-" in actual exec call. */
333 if (dash) {
334 /* _Attempt_ to make stdin a controlling tty. */
335 if (ENABLE_FEATURE_INIT_SCTTY)
336 ioctl(STDIN_FILENO, TIOCSCTTY, 0 /*only try, don't steal*/);
337 }
338 BB_EXECVP(cmd[0] + dash, cmd);
339 message(L_LOG | L_CONSOLE, "Cannot run '%s': %s",
340 cmd[0], strerror(errno));
341 /* returns if execvp fails */
342}
343
297/* Used only by run_actions */ 344/* Used only by run_actions */
298static pid_t run(const struct init_action *a) 345static pid_t run(const struct init_action *a)
299{ 346{
300 int i;
301 pid_t pid; 347 pid_t pid;
302 char *s, *tmpCmd, *cmdpath;
303 char *cmd[INIT_BUFFS_SIZE];
304 char buf[INIT_BUFFS_SIZE + 6]; /* INIT_BUFFS_SIZE+strlen("exec ")+1 */
305 sigset_t nmask, omask; 348 sigset_t nmask, omask;
306 349
307 /* Block sigchild while forking (why?) */ 350 /* Block sigchild while forking (why?) */
@@ -341,7 +384,7 @@ static pid_t run(const struct init_action *a)
341#ifdef BUT_RUN_ACTIONS_ALREADY_DOES_WAITING 384#ifdef BUT_RUN_ACTIONS_ALREADY_DOES_WAITING
342 /* If the init Action requires us to wait, then force the 385 /* If the init Action requires us to wait, then force the
343 * supplied terminal to be the controlling tty. */ 386 * supplied terminal to be the controlling tty. */
344 if (a->action & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) { 387 if (a->action_type & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {
345 /* Now fork off another process to just hang around */ 388 /* Now fork off another process to just hang around */
346 pid = fork(); 389 pid = fork();
347 if (pid < 0) { 390 if (pid < 0) {
@@ -381,58 +424,7 @@ static pid_t run(const struct init_action *a)
381 /* Child - fall though to actually execute things */ 424 /* Child - fall though to actually execute things */
382 } 425 }
383#endif 426#endif
384 427 if (a->action_type & ASKFIRST) {
385 /* See if any special /bin/sh requiring characters are present */
386 if (strpbrk(a->command, "~`!$^&*()=|\\{}[];\"'<>?") != NULL) {
387 cmd[0] = (char*)DEFAULT_SHELL;
388 cmd[1] = (char*)"-c";
389 cmd[2] = strcat(strcpy(buf, "exec "), a->command);
390 cmd[3] = NULL;
391 } else {
392 /* Convert command (char*) into cmd (char**, one word per string) */
393 strcpy(buf, a->command);
394 s = buf;
395 for (tmpCmd = buf, i = 0; (tmpCmd = strsep(&s, " \t")) != NULL;) {
396 if (*tmpCmd != '\0') {
397 cmd[i] = tmpCmd;
398 i++;
399 }
400 }
401 cmd[i] = NULL;
402 }
403
404 cmdpath = cmd[0];
405
406 /*
407 * Interactive shells want to see a dash in argv[0]. This
408 * typically is handled by login, argv will be setup this
409 * way if a dash appears at the front of the command path
410 * (like "-/bin/sh").
411 */
412 if (*cmdpath == '-') {
413 /* skip over the dash */
414 ++cmdpath;
415
416#ifdef WHY_WE_DO_THIS_SHELL_MUST_HANDLE_THIS_ITSELF
417 /* find the last component in the command pathname */
418 s = bb_get_last_path_component_nostrip(cmdpath);
419 /* make a new argv[0] */
420 cmd[0] = malloc(strlen(s) + 2);
421 if (cmd[0] == NULL) {
422 message(L_LOG | L_CONSOLE, bb_msg_memory_exhausted);
423 cmd[0] = cmdpath;
424 } else {
425 cmd[0][0] = '-';
426 strcpy(cmd[0] + 1, s);
427 }
428#endif
429
430 /* _Attempt_ to make stdin a controlling tty. */
431 if (ENABLE_FEATURE_INIT_SCTTY)
432 ioctl(0, TIOCSCTTY, 0 /*only try, don't steal*/);
433 }
434
435 if (a->action & ASKFIRST) {
436 static const char press_enter[] ALIGN1 = 428 static const char press_enter[] ALIGN1 =
437#ifdef CUSTOMIZED_BANNER 429#ifdef CUSTOMIZED_BANNER
438#include CUSTOMIZED_BANNER 430#include CUSTOMIZED_BANNER
@@ -449,58 +441,54 @@ static pid_t run(const struct init_action *a)
449 */ 441 */
450 messageD(L_LOG, "waiting for enter to start '%s'" 442 messageD(L_LOG, "waiting for enter to start '%s'"
451 "(pid %d, tty '%s')\n", 443 "(pid %d, tty '%s')\n",
452 cmdpath, getpid(), a->terminal); 444 a->command, getpid(), a->terminal);
453 full_write(1, press_enter, sizeof(press_enter) - 1); 445 full_write(1, press_enter, sizeof(press_enter) - 1);
454 while (safe_read(0, &c, 1) == 1 && c != '\n') 446 while (safe_read(0, &c, 1) == 1 && c != '\n')
455 continue; 447 continue;
456 } 448 }
457 449
458 /* Log the process name and args */
459 message(L_LOG, "starting pid %d, tty '%s': '%s'",
460 getpid(), a->terminal, cmdpath);
461
462 if (ENABLE_FEATURE_INIT_COREDUMPS) { 450 if (ENABLE_FEATURE_INIT_COREDUMPS) {
463 struct stat sb; 451 struct stat sb;
464 if (stat(CORE_ENABLE_FLAG_FILE, &sb) == 0) { 452 if (stat(CORE_ENABLE_FLAG_FILE, &sb) == 0) {
465 struct rlimit limit; 453 struct rlimit limit;
466
467 limit.rlim_cur = RLIM_INFINITY; 454 limit.rlim_cur = RLIM_INFINITY;
468 limit.rlim_max = RLIM_INFINITY; 455 limit.rlim_max = RLIM_INFINITY;
469 setrlimit(RLIMIT_CORE, &limit); 456 setrlimit(RLIMIT_CORE, &limit);
470 } 457 }
471 } 458 }
472 459
460 /* Log the process name and args */
461 message(L_LOG, "starting pid %d, tty '%s': '%s'",
462 getpid(), a->terminal, a->command);
463
473 /* Now run it. The new program will take over this PID, 464 /* Now run it. The new program will take over this PID,
474 * so nothing further in init.c should be run. */ 465 * so nothing further in init.c should be run. */
475 BB_EXECVP(cmdpath, cmd); 466 init_exec(a->command);
476
477 /* We're still here? Some error happened. */ 467 /* We're still here? Some error happened. */
478 message(L_LOG | L_CONSOLE, "Cannot run '%s': %s",
479 cmdpath, strerror(errno));
480 _exit(-1); 468 _exit(-1);
481} 469}
482 470
483/* Run all commands of a particular type */ 471/* Run all commands of a particular type */
484static void run_actions(int action) 472static void run_actions(int action_type)
485{ 473{
486 struct init_action *a, *tmp; 474 struct init_action *a, *tmp;
487 475
488 for (a = init_action_list; a; a = tmp) { 476 for (a = init_action_list; a; a = tmp) {
489 tmp = a->next; 477 tmp = a->next;
490 if (a->action == action) { 478 if (a->action_type == action_type) {
491 // Pointless: run() will error out if open of device fails. 479 // Pointless: run() will error out if open of device fails.
492 ///* a->terminal of "" means "init's console" */ 480 ///* a->terminal of "" means "init's console" */
493 //if (a->terminal[0] && access(a->terminal, R_OK | W_OK)) { 481 //if (a->terminal[0] && access(a->terminal, R_OK | W_OK)) {
494 // //message(L_LOG | L_CONSOLE, "Device %s cannot be opened in RW mode", a->terminal /*, strerror(errno)*/); 482 // //message(L_LOG | L_CONSOLE, "Device %s cannot be opened in RW mode", a->terminal /*, strerror(errno)*/);
495 // delete_init_action(a); 483 // delete_init_action(a);
496 //} else 484 //} else
497 if (a->action & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) { 485 if (a->action_type & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {
498 waitfor(run(a)); 486 waitfor(run(a));
499 delete_init_action(a); 487 delete_init_action(a);
500 } else if (a->action & ONCE) { 488 } else if (a->action_type & ONCE) {
501 run(a); 489 run(a);
502 delete_init_action(a); 490 delete_init_action(a);
503 } else if (a->action & (RESPAWN | ASKFIRST)) { 491 } else if (a->action_type & (RESPAWN | ASKFIRST)) {
504 /* Only run stuff with pid==0. If they have 492 /* Only run stuff with pid==0. If they have
505 * a pid, that means it is still running */ 493 * a pid, that means it is still running */
506 if (a->pid == 0) { 494 if (a->pid == 0) {
@@ -593,12 +581,11 @@ static void halt_reboot_pwoff(int sig)
593 * else (no such action defined) do nothing */ 581 * else (no such action defined) do nothing */
594static void exec_restart_action(int sig ATTRIBUTE_UNUSED) 582static void exec_restart_action(int sig ATTRIBUTE_UNUSED)
595{ 583{
596 struct init_action *a, *tmp; 584 struct init_action *a;
597 sigset_t unblock_signals; 585 sigset_t unblock_signals;
598 586
599 for (a = init_action_list; a; a = tmp) { 587 for (a = init_action_list; a; a = a->next) {
600 tmp = a->next; 588 if (a->action_type & RESTART) {
601 if (a->action & RESTART) {
602 kill_all_processes(); 589 kill_all_processes();
603 590
604 /* unblock all signals (blocked in kill_all_processes()) */ 591 /* unblock all signals (blocked in kill_all_processes()) */
@@ -620,10 +607,7 @@ static void exec_restart_action(int sig ATTRIBUTE_UNUSED)
620 open_stdio_to_tty(a->terminal, 0 /* - halt if open fails */); 607 open_stdio_to_tty(a->terminal, 0 /* - halt if open fails */);
621 608
622 messageD(L_CONSOLE | L_LOG, "Trying to re-exec %s", a->command); 609 messageD(L_CONSOLE | L_LOG, "Trying to re-exec %s", a->command);
623 BB_EXECLP(a->command, a->command, NULL); 610 init_exec(a->command);
624
625 message(L_CONSOLE | L_LOG, "Cannot run '%s': %s",
626 a->command, strerror(errno));
627 sleep(2); 611 sleep(2);
628 init_reboot(RB_HALT_SYSTEM); 612 init_reboot(RB_HALT_SYSTEM);
629 loop_forever(); 613 loop_forever();
@@ -654,12 +638,13 @@ static void cont_handler(int sig ATTRIBUTE_UNUSED)
654 got_cont = 1; 638 got_cont = 1;
655} 639}
656 640
657static void new_init_action(uint8_t action, const char *command, const char *cons) 641static void new_init_action(uint8_t action_type, const char *command, const char *cons)
658{ 642{
659 struct init_action *new_action, *a, *last; 643 struct init_action *a, *last;
660 644
661 if (strcmp(cons, bb_dev_null) == 0 && (action & ASKFIRST)) 645// Why?
662 return; 646// if (strcmp(cons, bb_dev_null) == 0 && (action & ASKFIRST))
647// return;
663 648
664 /* Append to the end of the list */ 649 /* Append to the end of the list */
665 for (a = last = init_action_list; a; a = a->next) { 650 for (a = last = init_action_list; a; a = a->next) {
@@ -668,23 +653,23 @@ static void new_init_action(uint8_t action, const char *command, const char *con
668 if ((strcmp(a->command, command) == 0) 653 if ((strcmp(a->command, command) == 0)
669 && (strcmp(a->terminal, cons) == 0) 654 && (strcmp(a->terminal, cons) == 0)
670 ) { 655 ) {
671 a->action = action; 656 a->action_type = action_type;
672 return; 657 return;
673 } 658 }
674 last = a; 659 last = a;
675 } 660 }
676 661
677 new_action = xzalloc(sizeof(struct init_action)); 662 a = xzalloc(sizeof(*a));
678 if (last) { 663 if (last) {
679 last->next = new_action; 664 last->next = a;
680 } else { 665 } else {
681 init_action_list = new_action; 666 init_action_list = a;
682 } 667 }
683 strcpy(new_action->command, command); 668 a->action_type = action_type;
684 new_action->action = action; 669 safe_strncpy(a->command, command, sizeof(a->command));
685 strcpy(new_action->terminal, cons); 670 safe_strncpy(a->terminal, cons, sizeof(a->terminal));
686 messageD(L_LOG | L_CONSOLE, "command='%s' action=%d tty='%s'\n", 671 messageD(L_LOG | L_CONSOLE, "command='%s' action=%d tty='%s'\n",
687 new_action->command, new_action->action, new_action->terminal); 672 a->command, a->action_type, a->terminal);
688} 673}
689 674
690static void delete_init_action(struct init_action *action) 675static void delete_init_action(struct init_action *action)
@@ -714,7 +699,7 @@ static void delete_init_action(struct init_action *action)
714static void parse_inittab(void) 699static void parse_inittab(void)
715{ 700{
716 FILE *file; 701 FILE *file;
717 char buf[INIT_BUFFS_SIZE]; 702 char buf[COMMAND_SIZE];
718 703
719 if (ENABLE_FEATURE_USE_INITTAB) 704 if (ENABLE_FEATURE_USE_INITTAB)
720 file = fopen(INITTAB, "r"); 705 file = fopen(INITTAB, "r");
@@ -743,7 +728,7 @@ static void parse_inittab(void)
743 return; 728 return;
744 } 729 }
745 730
746 while (fgets(buf, INIT_BUFFS_SIZE, file) != NULL) { 731 while (fgets(buf, COMMAND_SIZE, file) != NULL) {
747 static const char actions[] = 732 static const char actions[] =
748 STR_SYSINIT "sysinit\0" 733 STR_SYSINIT "sysinit\0"
749 STR_RESPAWN "respawn\0" 734 STR_RESPAWN "respawn\0"
@@ -810,7 +795,7 @@ static void reload_signal(int sig ATTRIBUTE_UNUSED)
810 795
811 /* disable old entrys */ 796 /* disable old entrys */
812 for (a = init_action_list; a; a = a->next) { 797 for (a = init_action_list; a; a = a->next) {
813 a->action = ONCE; 798 a->action_type = ONCE;
814 } 799 }
815 800
816 parse_inittab(); 801 parse_inittab();
@@ -819,7 +804,7 @@ static void reload_signal(int sig ATTRIBUTE_UNUSED)
819 /* Be nice and send SIGTERM first */ 804 /* Be nice and send SIGTERM first */
820 for (a = init_action_list; a; a = a->next) { 805 for (a = init_action_list; a; a = a->next) {
821 pid_t pid = a->pid; 806 pid_t pid = a->pid;
822 if ((a->action & ONCE) && pid != 0) { 807 if ((a->action_type & ONCE) && pid != 0) {
823 kill(pid, SIGTERM); 808 kill(pid, SIGTERM);
824 } 809 }
825 } 810 }
@@ -828,7 +813,7 @@ static void reload_signal(int sig ATTRIBUTE_UNUSED)
828 sleep(CONFIG_FEATURE_KILL_DELAY); 813 sleep(CONFIG_FEATURE_KILL_DELAY);
829 for (a = init_action_list; a; a = a->next) { 814 for (a = init_action_list; a; a = a->next) {
830 pid_t pid = a->pid; 815 pid_t pid = a->pid;
831 if ((a->action & ONCE) && pid != 0) { 816 if ((a->action_type & ONCE) && pid != 0) {
832 kill(pid, SIGKILL); 817 kill(pid, SIGKILL);
833 } 818 }
834 } 819 }
@@ -840,7 +825,7 @@ static void reload_signal(int sig ATTRIBUTE_UNUSED)
840 /* remove unused entrys */ 825 /* remove unused entrys */
841 for (a = init_action_list; a; a = tmp) { 826 for (a = init_action_list; a; a = tmp) {
842 tmp = a->next; 827 tmp = a->next;
843 if ((a->action & (ONCE | SYSINIT | WAIT)) && a->pid == 0) { 828 if ((a->action_type & (ONCE | SYSINIT | WAIT)) && a->pid == 0) {
844 delete_init_action(a); 829 delete_init_action(a);
845 } 830 }
846 } 831 }
@@ -998,7 +983,7 @@ int init_main(int argc, char **argv)
998 * restarted by run_actions() */ 983 * restarted by run_actions() */
999 a->pid = 0; 984 a->pid = 0;
1000 message(L_LOG, "process '%s' (pid %d) exited. " 985 message(L_LOG, "process '%s' (pid %d) exited. "
1001 "Scheduling it for restart.", 986 "Scheduling for restart.",
1002 a->command, wpid); 987 a->command, wpid);
1003 } 988 }
1004 } 989 }