Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/init/init.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 983 by niro, Fri Apr 24 18:33:46 2009 UTC revision 984 by niro, Sun May 30 11:32:42 2010 UTC
# Line 13  Line 13 
13  #include <syslog.h>  #include <syslog.h>
14  #include <paths.h>  #include <paths.h>
15  #include <sys/reboot.h>  #include <sys/reboot.h>
16    #include <sys/resource.h>
17    #include <linux/vt.h>
18    
19    
20  /* Was a CONFIG_xxx option. A lot of people were building  /* Was a CONFIG_xxx option. A lot of people were building
21   * not fully functional init by switching it on! */   * not fully functional init by switching it on! */
22  #define DEBUG_INIT 0  #define DEBUG_INIT 0
23    
24  #define COMMAND_SIZE 256  #define COMMAND_SIZE      256
25  #define CONSOLE_NAME_SIZE 32  #define CONSOLE_NAME_SIZE 32
 #define MAXENV 16 /* Number of env. vars */  
   
 /*  
  * When a file named CORE_ENABLE_FLAG_FILE exists, setrlimit is called  
  * before processes are spawned to set core file size as unlimited.  
  * This is for debugging only.  Don't use this is production, unless  
  * you want core dumps lying about....  
  */  
 #define CORE_ENABLE_FLAG_FILE "/.init_enable_core"  
 #include <sys/resource.h>  
26    
27  #define INITTAB      "/etc/inittab" /* inittab file location */  /* Default sysinit script. */
28  #ifndef INIT_SCRIPT  #ifndef INIT_SCRIPT
29  #define INIT_SCRIPT  "/etc/init.d/rcS" /* Default sysinit script. */  #define INIT_SCRIPT  "/etc/init.d/rcS"
30  #endif  #endif
31    
32  /* Allowed init action types */  /* Each type of actions can appear many times. They will be
33     * handled in order. RESTART is an exception, only 1st is used.
34     */
35    /* Start these actions first and wait for completion */
36  #define SYSINIT     0x01  #define SYSINIT     0x01
37  #define RESPAWN     0x02  /* Start these after SYSINIT and wait for completion */
38  /* like respawn, but wait for <Enter> to be pressed on tty: */  #define WAIT        0x02
39  #define ASKFIRST    0x04  /* Start these after WAIT and *dont* wait for completion */
40  #define WAIT        0x08  #define ONCE        0x04
41  #define ONCE        0x10  /*
42     * NB: while SYSINIT/WAIT/ONCE are being processed,
43     * SIGHUP ("reread /etc/inittab") will be processed only after
44     * each group of actions. If new inittab adds, say, a SYSINIT action,
45     * it will not be run, since init is already "past SYSINIT stage".
46     */
47    /* Start these after ONCE are started, restart on exit */
48    #define RESPAWN     0x08
49    /* Like RESPAWN, but wait for <Enter> to be pressed on tty */
50    #define ASKFIRST    0x10
51    /*
52     * Start these on SIGINT, and wait for completion.
53     * Then go back to respawning RESPAWN and ASKFIRST actions.
54     * NB: kernel sends SIGINT to us if Ctrl-Alt-Del was pressed.
55     */
56  #define CTRLALTDEL  0x20  #define CTRLALTDEL  0x20
57    /*
58     * Start these before killing all processes in preparation for
59     * running RESTART actions or doing low-level halt/reboot/poweroff
60     * (initiated by SIGUSR1/SIGTERM/SIGUSR2).
61     * Wait for completion before proceeding.
62     */
63  #define SHUTDOWN    0x40  #define SHUTDOWN    0x40
64    /*
65     * exec() on SIGQUIT. SHUTDOWN actions are started and waited for,
66     * then all processes are killed, then init exec's 1st RESTART action,
67     * replacing itself by it. If no RESTART action specified,
68     * SIGQUIT has no effect.
69     */
70  #define RESTART     0x80  #define RESTART     0x80
71    
72  /* Set up a linked list of init_actions, to be read from inittab */  
73    /* A linked list of init_actions, to be read from inittab */
74  struct init_action {  struct init_action {
75   struct init_action *next;   struct init_action *next;
76   pid_t pid;   pid_t pid;
# Line 56  struct init_action { Line 79  struct init_action {
79   char command[COMMAND_SIZE];   char command[COMMAND_SIZE];
80  };  };
81    
 /* Static variables */  
82  static struct init_action *init_action_list = NULL;  static struct init_action *init_action_list = NULL;
83    
84  static const char *log_console = VC_5;  static const char *log_console = VC_5;
# Line 64  static const char *log_console = VC_5; Line 86  static const char *log_console = VC_5;
86  enum {  enum {
87   L_LOG = 0x1,   L_LOG = 0x1,
88   L_CONSOLE = 0x2,   L_CONSOLE = 0x2,
   
 #if ENABLE_FEATURE_EXTRA_QUIET  
  MAYBE_CONSOLE = 0x0,  
 #else  
  MAYBE_CONSOLE = L_CONSOLE,  
 #endif  
   
89  #ifndef RB_HALT_SYSTEM  #ifndef RB_HALT_SYSTEM
90   RB_HALT_SYSTEM = 0xcdef0123, /* FIXME: this overflows enum */   RB_HALT_SYSTEM = 0xcdef0123, /* FIXME: this overflows enum */
91   RB_ENABLE_CAD = 0x89abcdef,   RB_ENABLE_CAD = 0x89abcdef,
# Line 80  enum { Line 95  enum {
95  #endif  #endif
96  };  };
97    
 /* Function prototypes */  
 static void halt_reboot_pwoff(int sig) NORETURN;  
   
 static void waitfor(pid_t pid)  
 {  
  /* waitfor(run(x)): protect against failed fork inside run() */  
  if (pid <= 0)  
  return;  
   
  /* Wait for any child (prevent zombies from exiting orphaned processes)  
  * but exit the loop only when specified one has exited. */  
  while (wait(NULL) != pid)  
  continue;  
 }  
   
 static void loop_forever(void) NORETURN;  
 static void loop_forever(void)  
 {  
  while (1)  
  sleep(1);  
 }  
   
98  /* Print a message to the specified device.  /* Print a message to the specified device.
99   * "where" may be bitwise-or'd from L_LOG | L_CONSOLE   * "where" may be bitwise-or'd from L_LOG | L_CONSOLE
100   * NB: careful, we can be called after vfork!   * NB: careful, we can be called after vfork!
101   */   */
102  #define messageD(...) do { if (DEBUG_INIT) message(__VA_ARGS__); } while (0)  #define dbg_message(...) do { if (DEBUG_INIT) message(__VA_ARGS__); } while (0)
103  static void message(int where, const char *fmt, ...)  static void message(int where, const char *fmt, ...)
104   __attribute__ ((format(printf, 2, 3)));   __attribute__ ((format(printf, 2, 3)));
105  static void message(int where, const char *fmt, ...)  static void message(int where, const char *fmt, ...)
106  {  {
  static int log_fd = -1;  
107   va_list arguments;   va_list arguments;
108   unsigned l;   unsigned l;
109   char msg[128];   char msg[128];
# Line 121  static void message(int where, const cha Line 113  static void message(int where, const cha
113   l = 1 + vsnprintf(msg + 1, sizeof(msg) - 2, fmt, arguments);   l = 1 + vsnprintf(msg + 1, sizeof(msg) - 2, fmt, arguments);
114   if (l > sizeof(msg) - 1)   if (l > sizeof(msg) - 1)
115   l = sizeof(msg) - 1;   l = sizeof(msg) - 1;
  msg[l] = '\0';  
116   va_end(arguments);   va_end(arguments);
117    
118   if (ENABLE_FEATURE_INIT_SYSLOG) {  #if ENABLE_FEATURE_INIT_SYSLOG
119   if (where & L_LOG) {   msg[l] = '\0';
120   /* Log the message to syslogd */   if (where & L_LOG) {
121   openlog("init", 0, LOG_DAEMON);   /* Log the message to syslogd */
122   /* don't print "\r" */   openlog(applet_name, 0, LOG_DAEMON);
123   syslog(LOG_INFO, "%s", msg + 1);   /* don't print "\r" */
124   closelog();   syslog(LOG_INFO, "%s", msg + 1);
125   }   closelog();
126   msg[l++] = '\n';   }
127   msg[l] = '\0';   msg[l++] = '\n';
128   } else {   msg[l] = '\0';
129    #else
130     {
131     static int log_fd = -1;
132    
133   msg[l++] = '\n';   msg[l++] = '\n';
134   msg[l] = '\0';   msg[l] = '\0';
135   /* Take full control of the log tty, and never close it.   /* Take full control of the log tty, and never close it.
# Line 158  static void message(int where, const cha Line 153  static void message(int where, const cha
153   return; /* don't print dup messages */   return; /* don't print dup messages */
154   }   }
155   }   }
156    #endif
157    
158   if (where & L_CONSOLE) {   if (where & L_CONSOLE) {
159   /* Send console messages to console so people will see them. */   /* Send console messages to console so people will see them. */
# Line 165  static void message(int where, const cha Line 161  static void message(int where, const cha
161   }   }
162  }  }
163    
 /* From <linux/serial.h> */  
 struct serial_struct {  
  int type;  
  int line;  
  unsigned int port;  
  int irq;  
  int flags;  
  int xmit_fifo_size;  
  int custom_divisor;  
  int baud_base;  
  unsigned short close_delay;  
  char io_type;  
  char reserved_char[1];  
  int hub6;  
  unsigned short closing_wait; /* time to wait before closing */  
  unsigned short closing_wait2; /* no longer used... */  
  unsigned char *iomem_base;  
  unsigned short iomem_reg_shift;  
  unsigned int port_high;  
  unsigned long iomap_base; /* cookie passed into ioremap */  
  int reserved[1];  
  /* Paranoia (imagine 64bit kernel overwriting 32bit userspace stack) */  
  uint32_t bbox_reserved[16];  
 };  
164  static void console_init(void)  static void console_init(void)
165  {  {
166   struct serial_struct sr;   int vtno;
167   char *s;   char *s;
168    
169   s = getenv("CONSOLE");   s = getenv("CONSOLE");
# Line 204  static void console_init(void) Line 176  static void console_init(void)
176   dup2(fd, STDOUT_FILENO);   dup2(fd, STDOUT_FILENO);
177   xmove_fd(fd, STDERR_FILENO);   xmove_fd(fd, STDERR_FILENO);
178   }   }
179   messageD(L_LOG, "console='%s'", s);   dbg_message(L_LOG, "console='%s'", s);
180   } else {   } else {
181   /* Make sure fd 0,1,2 are not closed   /* Make sure fd 0,1,2 are not closed
182   * (so that they won't be used by future opens) */   * (so that they won't be used by future opens) */
# Line 215  static void console_init(void) Line 187  static void console_init(void)
187   }   }
188    
189   s = getenv("TERM");   s = getenv("TERM");
190   if (ioctl(STDIN_FILENO, TIOCGSERIAL, &sr) == 0) {   if (ioctl(STDIN_FILENO, VT_OPENQRY, &vtno) != 0) {
191   /* Force the TERM setting to vt102 for serial console   /* Not a linux terminal, probably serial console.
192     * Force the TERM setting to vt102
193   * if TERM is set to linux (the default) */   * if TERM is set to linux (the default) */
194   if (!s || strcmp(s, "linux") == 0)   if (!s || strcmp(s, "linux") == 0)
195   putenv((char*)"TERM=vt102");   putenv((char*)"TERM=vt102");
# Line 266  static void set_sane_term(void) Line 239  static void set_sane_term(void)
239    
240  /* Open the new terminal device.  /* Open the new terminal device.
241   * NB: careful, we can be called after vfork! */   * NB: careful, we can be called after vfork! */
242  static void open_stdio_to_tty(const char* tty_name, int exit_on_failure)  static int open_stdio_to_tty(const char* tty_name)
243  {  {
244   /* empty tty_name means "use init's tty", else... */   /* empty tty_name means "use init's tty", else... */
245   if (tty_name[0]) {   if (tty_name[0]) {
246   int fd;   int fd;
247    
248   close(STDIN_FILENO);   close(STDIN_FILENO);
249   /* fd can be only < 0 or 0: */   /* fd can be only < 0 or 0: */
250   fd = device_open(tty_name, O_RDWR);   fd = device_open(tty_name, O_RDWR);
251   if (fd) {   if (fd) {
252   message(L_LOG | L_CONSOLE, "can't open %s: %s",   message(L_LOG | L_CONSOLE, "can't open %s: %s",
253   tty_name, strerror(errno));   tty_name, strerror(errno));
254   if (exit_on_failure)   return 0; /* failure */
  _exit(EXIT_FAILURE);  
  if (DEBUG_INIT)  
  _exit(2);  
  /* NB: we don't reach this if we were called after vfork.  
  * Thus halt_reboot_pwoff() itself need not be vfork-safe. */  
  halt_reboot_pwoff(SIGUSR1); /* halt the system */  
255   }   }
256   dup2(STDIN_FILENO, STDOUT_FILENO);   dup2(STDIN_FILENO, STDOUT_FILENO);
257   dup2(STDIN_FILENO, STDERR_FILENO);   dup2(STDIN_FILENO, STDERR_FILENO);
258   }   }
259   set_sane_term();   set_sane_term();
260     return 1; /* success */
261    }
262    
263    static void reset_sighandlers_and_unblock_sigs(void)
264    {
265     bb_signals(0
266     + (1 << SIGUSR1)
267     + (1 << SIGUSR2)
268     + (1 << SIGTERM)
269     + (1 << SIGQUIT)
270     + (1 << SIGINT)
271     + (1 << SIGHUP)
272     + (1 << SIGTSTP)
273     + (1 << SIGSTOP)
274     , SIG_DFL);
275     sigprocmask_allsigs(SIG_UNBLOCK);
276  }  }
277    
278  /* Wrapper around exec:  /* Wrapper around exec:
# Line 335  static void init_exec(const char *comman Line 319  static void init_exec(const char *comman
319   ioctl(STDIN_FILENO, TIOCSCTTY, 0 /*only try, don't steal*/);   ioctl(STDIN_FILENO, TIOCSCTTY, 0 /*only try, don't steal*/);
320   }   }
321   BB_EXECVP(cmd[0] + dash, cmd);   BB_EXECVP(cmd[0] + dash, cmd);
322   message(L_LOG | L_CONSOLE, "cannot run '%s': %s", cmd[0], strerror(errno));   message(L_LOG | L_CONSOLE, "can't run '%s': %s", cmd[0], strerror(errno));
323   /* returns if execvp fails */   /* returns if execvp fails */
324  }  }
325    
# Line 343  static void init_exec(const char *comman Line 327  static void init_exec(const char *comman
327  static pid_t run(const struct init_action *a)  static pid_t run(const struct init_action *a)
328  {  {
329   pid_t pid;   pid_t pid;
  sigset_t nmask, omask;  
330    
331   /* Block sigchild while forking (why?) */   /* Careful: don't be affected by a signal in vforked child */
332   sigemptyset(&nmask);   sigprocmask_allsigs(SIG_BLOCK);
  sigaddset(&nmask, SIGCHLD);  
  sigprocmask(SIG_BLOCK, &nmask, &omask);  
333   if (BB_MMU && (a->action_type & ASKFIRST))   if (BB_MMU && (a->action_type & ASKFIRST))
334   pid = fork();   pid = fork();
335   else   else
336   pid = vfork();   pid = vfork();
  sigprocmask(SIG_SETMASK, &omask, NULL);  
   
337   if (pid < 0)   if (pid < 0)
338   message(L_LOG | L_CONSOLE, "can't fork");   message(L_LOG | L_CONSOLE, "can't fork");
339   if (pid)   if (pid) {
340   return pid;   sigprocmask_allsigs(SIG_UNBLOCK);
341     return pid; /* Parent or error */
342     }
343    
344   /* Child */   /* Child */
345    
346   /* Reset signal handlers that were set by the parent process */   /* Reset signal handlers that were set by the parent process */
347   bb_signals(0   reset_sighandlers_and_unblock_sigs();
  + (1 << SIGUSR1)  
  + (1 << SIGUSR2)  
  + (1 << SIGINT)  
  + (1 << SIGTERM)  
  + (1 << SIGHUP)  
  + (1 << SIGQUIT)  
  + (1 << SIGCONT)  
  + (1 << SIGSTOP)  
  + (1 << SIGTSTP)  
  , SIG_DFL);  
348    
349   /* Create a new session and make ourself the process   /* Create a new session and make ourself the process group leader */
  * group leader */  
350   setsid();   setsid();
351    
352   /* Open the new terminal device */   /* Open the new terminal device */
353   open_stdio_to_tty(a->terminal, 1 /* - exit if open fails */);   if (!open_stdio_to_tty(a->terminal))
354     _exit(EXIT_FAILURE);
 // NB: do not enable unless you change vfork to fork above  
 #ifdef BUT_RUN_ACTIONS_ALREADY_DOES_WAITING  
  /* If the init Action requires us to wait, then force the  
  * supplied terminal to be the controlling tty. */  
  if (a->action_type & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {  
  /* Now fork off another process to just hang around */  
  pid = fork();  
  if (pid < 0) {  
  message(L_LOG | L_CONSOLE, "can't fork");  
  _exit(EXIT_FAILURE);  
  }  
   
  if (pid > 0) {  
  /* Parent - wait till the child is done */  
  bb_signals(0  
  + (1 << SIGINT)  
  + (1 << SIGTSTP)  
  + (1 << SIGQUIT)  
  , SIG_IGN);  
  signal(SIGCHLD, SIG_DFL);  
   
  waitfor(pid);  
  /* See if stealing the controlling tty back is necessary */  
  if (tcgetpgrp(0) != getpid())  
  _exit(EXIT_SUCCESS);  
   
  /* Use a temporary process to steal the controlling tty. */  
  pid = fork();  
  if (pid < 0) {  
  message(L_LOG | L_CONSOLE, "can't fork");  
  _exit(EXIT_FAILURE);  
  }  
  if (pid == 0) {  
  setsid();  
  ioctl(0, TIOCSCTTY, 1);  
  _exit(EXIT_SUCCESS);  
  }  
  waitfor(pid);  
  _exit(EXIT_SUCCESS);  
  }  
  /* Child - fall though to actually execute things */  
  }  
 #endif  
355    
356   /* NB: on NOMMU we can't wait for input in child, so   /* NB: on NOMMU we can't wait for input in child, so
357   * "askfirst" will work the same as "respawn". */   * "askfirst" will work the same as "respawn". */
# Line 443  static pid_t run(const struct init_actio Line 370  static pid_t run(const struct init_actio
370   * be allowed to start a shell or whatever an init script   * be allowed to start a shell or whatever an init script
371   * specifies.   * specifies.
372   */   */
373   messageD(L_LOG, "waiting for enter to start '%s'"   dbg_message(L_LOG, "waiting for enter to start '%s'"
374   "(pid %d, tty '%s')\n",   "(pid %d, tty '%s')\n",
375   a->command, getpid(), a->terminal);   a->command, getpid(), a->terminal);
376   full_write(STDOUT_FILENO, press_enter, sizeof(press_enter) - 1);   full_write(STDOUT_FILENO, press_enter, sizeof(press_enter) - 1);
# Line 451  static pid_t run(const struct init_actio Line 378  static pid_t run(const struct init_actio
378   continue;   continue;
379   }   }
380    
381     /*
382     * When a file named /.init_enable_core exists, setrlimit is called
383     * before processes are spawned to set core file size as unlimited.
384     * This is for debugging only.  Don't use this is production, unless
385     * you want core dumps lying about....
386     */
387   if (ENABLE_FEATURE_INIT_COREDUMPS) {   if (ENABLE_FEATURE_INIT_COREDUMPS) {
388   struct stat sb;   if (access("/.init_enable_core", F_OK) == 0) {
  if (stat(CORE_ENABLE_FLAG_FILE, &sb) == 0) {  
389   struct rlimit limit;   struct rlimit limit;
390   limit.rlim_cur = RLIM_INFINITY;   limit.rlim_cur = RLIM_INFINITY;
391   limit.rlim_max = RLIM_INFINITY;   limit.rlim_max = RLIM_INFINITY;
# Line 472  static pid_t run(const struct init_actio Line 404  static pid_t run(const struct init_actio
404   _exit(-1);   _exit(-1);
405  }  }
406    
407  static void delete_init_action(struct init_action *action)  static struct init_action *mark_terminated(pid_t pid)
408  {  {
409   struct init_action *a, *b = NULL;   struct init_action *a;
   
  for (a = init_action_list; a; b = a, a = a->next) {  
  if (a == action) {  
  if (b == NULL) {  
  init_action_list = a->next;  
  } else {  
  b->next = a->next;  
  }  
  free(a);  
  break;  
  }  
  }  
 }  
   
 /* Run all commands of a particular type */  
 static void run_actions(int action_type)  
 {  
  struct init_action *a, *tmp;  
410    
411   for (a = init_action_list; a; a = tmp) {   if (pid > 0) {
412   tmp = a->next;   for (a = init_action_list; a; a = a->next) {
413   if (a->action_type & action_type) {   if (a->pid == pid) {
414   // Pointless: run() will error out if open of device fails.   a->pid = 0;
415   ///* a->terminal of "" means "init's console" */   return a;
  //if (a->terminal[0] && access(a->terminal, R_OK | W_OK)) {  
  // //message(L_LOG | L_CONSOLE, "Device %s cannot be opened in RW mode", a->terminal /*, strerror(errno)*/);  
  // delete_init_action(a);  
  //} else  
  if (a->action_type & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN | RESTART)) {  
  waitfor(run(a));  
  delete_init_action(a);  
  } else if (a->action_type & ONCE) {  
  run(a);  
  delete_init_action(a);  
  } else if (a->action_type & (RESPAWN | ASKFIRST)) {  
  /* Only run stuff with pid==0.  If they have  
  * a pid, that means it is still running */  
  if (a->pid == 0) {  
  a->pid = run(a);  
  }  
416   }   }
417   }   }
418   }   }
419     return NULL;
420  }  }
421    
422  static void init_reboot(unsigned long magic)  static void waitfor(pid_t pid)
 {  
  pid_t pid;  
  /* We have to fork here, since the kernel calls do_exit(EXIT_SUCCESS) in  
  * linux/kernel/sys.c, which can cause the machine to panic when  
  * the init process is killed.... */  
  pid = vfork();  
  if (pid == 0) { /* child */  
  reboot(magic);  
  _exit(EXIT_SUCCESS);  
  }  
  waitfor(pid);  
 }  
   
 static void kill_all_processes(void)  
 {  
  /* run everything to be run at "shutdown".  This is done _prior_  
  * to killing everything, in case people wish to use scripts to  
  * shut things down gracefully... */  
  run_actions(SHUTDOWN);  
   
  /* first disable all our signals */  
  sigprocmask_allsigs(SIG_BLOCK);  
   
  message(L_CONSOLE | L_LOG, "The system is going down NOW!");  
   
  /* Allow Ctrl-Alt-Del to reboot system. */  
  init_reboot(RB_ENABLE_CAD);  
   
  /* Send signals to every process _except_ pid 1 */  
  message(L_CONSOLE | L_LOG, "Sending SIG%s to all processes", "TERM");  
  kill(-1, SIGTERM);  
  sync();  
  sleep(1);  
   
  message(L_CONSOLE | L_LOG, "Sending SIG%s to all processes", "KILL");  
  kill(-1, SIGKILL);  
  sync();  
  sleep(1);  
 }  
   
 static void halt_reboot_pwoff(int sig)  
423  {  {
424   const char *m = "halt";   /* waitfor(run(x)): protect against failed fork inside run() */
425   int rb;   if (pid <= 0)
426     return;
  kill_all_processes();  
427    
428   rb = RB_HALT_SYSTEM;   /* Wait for any child (prevent zombies from exiting orphaned processes)
429   if (sig == SIGTERM) {   * but exit the loop only when specified one has exited. */
430   m = "reboot";   while (1) {
431   rb = RB_AUTOBOOT;   pid_t wpid = wait(NULL);
432   } else if (sig == SIGUSR2) {   mark_terminated(wpid);
433   m = "poweroff";   /* Unsafe. SIGTSTP handler might have wait'ed it already */
434   rb = RB_POWER_OFF;   /*if (wpid == pid) break;*/
435     /* More reliable: */
436     if (kill(pid, 0))
437     break;
438   }   }
  message(L_CONSOLE | L_LOG, "Requesting system %s", m);  
  /* allow time for last message to reach serial console */  
  sleep(2);  
  init_reboot(rb);  
  loop_forever();  
439  }  }
440    
441  /* Handler for QUIT - exec "restart" action,  /* Run all commands of a particular type */
442   * else (no such action defined) do nothing */  static void run_actions(int action_type)
 static void exec_restart_action(int sig UNUSED_PARAM)  
443  {  {
444   struct init_action *a;   struct init_action *a;
445    
446   for (a = init_action_list; a; a = a->next) {   for (a = init_action_list; a; a = a->next) {
447   if (a->action_type & RESTART) {   if (!(a->action_type & action_type))
448   kill_all_processes();   continue;
   
  /* unblock all signals (blocked in kill_all_processes()) */  
  sigprocmask_allsigs(SIG_UNBLOCK);  
   
  /* Open the new terminal device */  
  open_stdio_to_tty(a->terminal, 0 /* - halt if open fails */);  
449    
450   messageD(L_CONSOLE | L_LOG, "Trying to re-exec %s", a->command);   if (a->action_type & (SYSINIT | WAIT | ONCE | CTRLALTDEL | SHUTDOWN)) {
451   init_exec(a->command);   pid_t pid = run(a);
452   sleep(2);   if (a->action_type & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN))
453   init_reboot(RB_HALT_SYSTEM);   waitfor(pid);
454   loop_forever();   }
455     if (a->action_type & (RESPAWN | ASKFIRST)) {
456     /* Only run stuff with pid == 0. If pid != 0,
457     * it is already running
458     */
459     if (a->pid == 0)
460     a->pid = run(a);
461   }   }
462   }   }
463  }  }
464    
 static void ctrlaltdel_signal(int sig UNUSED_PARAM)  
 {  
  run_actions(CTRLALTDEL);  
 }  
   
 /* The SIGCONT handler is set to record_signo().  
  * It just sets bb_got_signal = SIGCONT.  */  
   
 /* The SIGSTOP & SIGTSTP handler */  
 static void stop_handler(int sig UNUSED_PARAM)  
 {  
  int saved_errno = errno;  
   
  bb_got_signal = 0;  
  while (bb_got_signal == 0)  
  pause();  
   
  errno = saved_errno;  
 }  
   
465  static void new_init_action(uint8_t action_type, const char *command, const char *cons)  static void new_init_action(uint8_t action_type, const char *command, const char *cons)
466  {  {
467   struct init_action *a, *last;   struct init_action *a, **nextp;
   
 // Why?  
 // if (strcmp(cons, bb_dev_null) == 0 && (action & ASKFIRST))  
 // return;  
468    
469   /* Append to the end of the list */   /* Scenario:
470   for (a = last = init_action_list; a; a = a->next) {   * old inittab:
471   /* don't enter action if it's already in the list,   * ::shutdown:umount -a -r
472   * but do overwrite existing actions */   * ::shutdown:swapoff -a
473   if ((strcmp(a->command, command) == 0)   * new inittab:
474   && (strcmp(a->terminal, cons) == 0)   * ::shutdown:swapoff -a
475     * ::shutdown:umount -a -r
476     * On reload, we must ensure entries end up in correct order.
477     * To achieve that, if we find a matching entry, we move it
478     * to the end.
479     */
480     nextp = &init_action_list;
481     while ((a = *nextp) != NULL) {
482     /* Don't enter action if it's already in the list,
483     * This prevents losing running RESPAWNs.
484     */
485     if (strcmp(a->command, command) == 0
486     && strcmp(a->terminal, cons) == 0
487   ) {   ) {
488   a->action_type = action_type;   /* Remove from list */
489   return;   *nextp = a->next;
490     /* Find the end of the list */
491     while (*nextp != NULL)
492     nextp = &(*nextp)->next;
493     a->next = NULL;
494     break;
495   }   }
496   last = a;   nextp = &a->next;
497   }   }
498    
499   a = xzalloc(sizeof(*a));   if (!a)
500   if (last) {   a = xzalloc(sizeof(*a));
501   last->next = a;   /* Append to the end of the list */
502   } else {   *nextp = a;
  init_action_list = a;  
  }  
503   a->action_type = action_type;   a->action_type = action_type;
504   safe_strncpy(a->command, command, sizeof(a->command));   safe_strncpy(a->command, command, sizeof(a->command));
505   safe_strncpy(a->terminal, cons, sizeof(a->terminal));   safe_strncpy(a->terminal, cons, sizeof(a->terminal));
506   messageD(L_LOG | L_CONSOLE, "command='%s' action=%d tty='%s'\n",   dbg_message(L_LOG | L_CONSOLE, "command='%s' action=%d tty='%s'\n",
507   a->command, a->action_type, a->terminal);   a->command, a->action_type, a->terminal);
508  }  }
509    
# Line 678  static void parse_inittab(void) Line 523  static void parse_inittab(void)
523   if (parser == NULL)   if (parser == NULL)
524  #endif  #endif
525   {   {
526   /* No inittab file -- set up some default behavior */   /* No inittab file - set up some default behavior */
527   /* Reboot on Ctrl-Alt-Del */   /* Reboot on Ctrl-Alt-Del */
528   new_init_action(CTRLALTDEL, "reboot", "");   new_init_action(CTRLALTDEL, "reboot", "");
529   /* Umount all filesystems on halt/reboot */   /* Umount all filesystems on halt/reboot */
# Line 707  static void parse_inittab(void) Line 552  static void parse_inittab(void)
552   PARSE_NORMAL & ~(PARSE_TRIM | PARSE_COLLAPSE))) {   PARSE_NORMAL & ~(PARSE_TRIM | PARSE_COLLAPSE))) {
553   /* order must correspond to SYSINIT..RESTART constants */   /* order must correspond to SYSINIT..RESTART constants */
554   static const char actions[] ALIGN1 =   static const char actions[] ALIGN1 =
555   "sysinit\0""respawn\0""askfirst\0""wait\0""once\0"   "sysinit\0""wait\0""once\0""respawn\0""askfirst\0"
556   "ctrlaltdel\0""shutdown\0""restart\0";   "ctrlaltdel\0""shutdown\0""restart\0";
557   int action;   int action;
558   char *tty = token[0];   char *tty = token[0];
# Line 735  static void parse_inittab(void) Line 580  static void parse_inittab(void)
580  #endif  #endif
581  }  }
582    
583  #if ENABLE_FEATURE_USE_INITTAB  static void pause_and_low_level_reboot(unsigned magic) NORETURN;
584  static void reload_signal(int sig UNUSED_PARAM)  static void pause_and_low_level_reboot(unsigned magic)
585  {  {
586   struct init_action *a, *tmp;   pid_t pid;
587    
588   message(L_LOG, "reloading /etc/inittab");   /* Allow time for last message to reach serial console, etc */
589     sleep(1);
590    
591     /* We have to fork here, since the kernel calls do_exit(EXIT_SUCCESS)
592     * in linux/kernel/sys.c, which can cause the machine to panic when
593     * the init process exits... */
594     pid = vfork();
595     if (pid == 0) { /* child */
596     reboot(magic);
597     _exit(EXIT_SUCCESS);
598     }
599     while (1)
600     sleep(1);
601    }
602    
603    static void run_shutdown_and_kill_processes(void)
604    {
605     /* Run everything to be run at "shutdown".  This is done _prior_
606     * to killing everything, in case people wish to use scripts to
607     * shut things down gracefully... */
608     run_actions(SHUTDOWN);
609    
610     message(L_CONSOLE | L_LOG, "The system is going down NOW!");
611    
612     /* Send signals to every process _except_ pid 1 */
613     kill(-1, SIGTERM);
614     message(L_CONSOLE | L_LOG, "Sent SIG%s to all processes", "TERM");
615     sync();
616     sleep(1);
617    
618     kill(-1, SIGKILL);
619     message(L_CONSOLE, "Sent SIG%s to all processes", "KILL");
620     sync();
621     /*sleep(1); - callers take care about making a pause */
622    }
623    
624    /* Signal handling by init:
625     *
626     * For process with PID==1, on entry kernel sets all signals to SIG_DFL
627     * and unmasks all signals. However, for process with PID==1,
628     * default action (SIG_DFL) on any signal is to ignore it,
629     * even for special signals SIGKILL and SIGCONT.
630     * Also, any signal can be caught or blocked.
631     * (but SIGSTOP is still handled specially, at least in 2.6.20)
632     *
633     * We install two kinds of handlers, "immediate" and "delayed".
634     *
635     * Immediate handlers execute at any time, even while, say, sysinit
636     * is running.
637     *
638     * Delayed handlers just set a flag variable. The variable is checked
639     * in the main loop and acted upon.
640     *
641     * halt/poweroff/reboot and restart have immediate handlers.
642     * They only traverse linked list of struct action's, never modify it,
643     * this should be safe to do even in signal handler. Also they
644     * never return.
645     *
646     * SIGSTOP and SIGTSTP have immediate handlers. They just wait
647     * for SIGCONT to happen.
648     *
649     * SIGHUP has a delayed handler, because modifying linked list
650     * of struct action's from a signal handler while it is manipulated
651     * by the program may be disastrous.
652     *
653     * Ctrl-Alt-Del has a delayed handler. Not a must, but allowing
654     * it to happen even somewhere inside "sysinit" would be a bit awkward.
655     *
656     * There is a tiny probability that SIGHUP and Ctrl-Alt-Del will collide
657     * and only one will be remembered and acted upon.
658     */
659    
660    /* The SIGUSR[12]/SIGTERM handler */
661    static void halt_reboot_pwoff(int sig) NORETURN;
662    static void halt_reboot_pwoff(int sig)
663    {
664     const char *m;
665     unsigned rb;
666    
667     /* We may call run() and it unmasks signals,
668     * including the one masked inside this signal handler.
669     * Testcase which would start multiple reboot scripts:
670     *  while true; do reboot; done
671     * Preventing it:
672     */
673     reset_sighandlers_and_unblock_sigs();
674    
675     run_shutdown_and_kill_processes();
676    
677     m = "halt";
678     rb = RB_HALT_SYSTEM;
679     if (sig == SIGTERM) {
680     m = "reboot";
681     rb = RB_AUTOBOOT;
682     } else if (sig == SIGUSR2) {
683     m = "poweroff";
684     rb = RB_POWER_OFF;
685     }
686     message(L_CONSOLE, "Requesting system %s", m);
687     pause_and_low_level_reboot(rb);
688     /* not reached */
689    }
690    
691    /* Handler for QUIT - exec "restart" action,
692     * else (no such action defined) do nothing */
693    static void restart_handler(int sig UNUSED_PARAM)
694    {
695     struct init_action *a;
696    
  /* disable old entrys */  
697   for (a = init_action_list; a; a = a->next) {   for (a = init_action_list; a; a = a->next) {
698   a->action_type = ONCE;   if (!(a->action_type & RESTART))
699     continue;
700    
701     /* Starting from here, we won't return.
702     * Thus don't need to worry about preserving errno
703     * and such.
704     */
705    
706     reset_sighandlers_and_unblock_sigs();
707    
708     run_shutdown_and_kill_processes();
709    
710     /* Allow Ctrl-Alt-Del to reboot the system.
711     * This is how kernel sets it up for init, we follow suit.
712     */
713     reboot(RB_ENABLE_CAD); /* misnomer */
714    
715     if (open_stdio_to_tty(a->terminal)) {
716     dbg_message(L_CONSOLE, "Trying to re-exec %s", a->command);
717     /* Theoretically should be safe.
718     * But in practice, kernel bugs may leave
719     * unkillable processes, and wait() may block forever.
720     * Oh well. Hoping "new" init won't be too surprised
721     * by having children it didn't create.
722     */
723     //while (wait(NULL) > 0)
724     // continue;
725     init_exec(a->command);
726     }
727     /* Open or exec failed */
728     pause_and_low_level_reboot(RB_HALT_SYSTEM);
729     /* not reached */
730     }
731    }
732    
733    /* The SIGSTOP/SIGTSTP handler
734     * NB: inside it, all signals except SIGCONT are masked
735     * via appropriate setup in sigaction().
736     */
737    static void stop_handler(int sig UNUSED_PARAM)
738    {
739     smallint saved_bb_got_signal;
740     int saved_errno;
741    
742     saved_bb_got_signal = bb_got_signal;
743     saved_errno = errno;
744     signal(SIGCONT, record_signo);
745    
746     while (1) {
747     pid_t wpid;
748    
749     if (bb_got_signal == SIGCONT)
750     break;
751     /* NB: this can accidentally wait() for a process
752     * which we waitfor() elsewhere! waitfor() must have
753     * code which is resilient against this.
754     */
755     wpid = wait_any_nohang(NULL);
756     mark_terminated(wpid);
757     sleep(1);
758   }   }
759    
760     signal(SIGCONT, SIG_DFL);
761     errno = saved_errno;
762     bb_got_signal = saved_bb_got_signal;
763    }
764    
765    #if ENABLE_FEATURE_USE_INITTAB
766    static void reload_inittab(void)
767    {
768     struct init_action *a, **nextp;
769    
770     message(L_LOG, "reloading /etc/inittab");
771    
772     /* Disable old entries */
773     for (a = init_action_list; a; a = a->next)
774     a->action_type = 0;
775    
776     /* Append new entries, or modify existing entries
777     * (incl. setting a->action_type) if cmd and device name
778     * match new ones. End result: only entries with
779     * a->action_type == 0 are stale.
780     */
781   parse_inittab();   parse_inittab();
782    
783   if (ENABLE_FEATURE_KILL_REMOVED) {  #if ENABLE_FEATURE_KILL_REMOVED
784   /* Be nice and send SIGTERM first */   /* Kill stale entries */
785   for (a = init_action_list; a; a = a->next) {   /* Be nice and send SIGTERM first */
786   pid_t pid = a->pid;   for (a = init_action_list; a; a = a->next)
787   if ((a->action_type & ONCE) && pid != 0) {   if (a->action_type == 0 && a->pid != 0)
788   kill(pid, SIGTERM);   kill(a->pid, SIGTERM);
789   }   if (CONFIG_FEATURE_KILL_DELAY) {
  }  
 #if CONFIG_FEATURE_KILL_DELAY  
790   /* NB: parent will wait in NOMMU case */   /* NB: parent will wait in NOMMU case */
791   if ((BB_MMU ? fork() : vfork()) == 0) { /* child */   if ((BB_MMU ? fork() : vfork()) == 0) { /* child */
792   sleep(CONFIG_FEATURE_KILL_DELAY);   sleep(CONFIG_FEATURE_KILL_DELAY);
793   for (a = init_action_list; a; a = a->next) {   for (a = init_action_list; a; a = a->next)
794   pid_t pid = a->pid;   if (a->action_type == 0 && a->pid != 0)
795   if ((a->action_type & ONCE) && pid != 0) {   kill(a->pid, SIGKILL);
  kill(pid, SIGKILL);  
  }  
  }  
796   _exit(EXIT_SUCCESS);   _exit(EXIT_SUCCESS);
797   }   }
 #endif  
798   }   }
799    #endif
800    
801   /* remove unused entrys */   /* Remove stale entries and SYSINIT entries.
802   for (a = init_action_list; a; a = tmp) {   * We never rerun SYSINIT entries anyway,
803   tmp = a->next;   * removing them too saves a few bytes */
804   if ((a->action_type & (ONCE | SYSINIT | WAIT)) && a->pid == 0) {   nextp = &init_action_list;
805   delete_init_action(a);   while ((a = *nextp) != NULL) {
806     if ((a->action_type & ~SYSINIT) == 0) {
807     *nextp = a->next;
808     free(a);
809     } else {
810     nextp = &a->next;
811   }   }
812   }   }
813   run_actions(RESPAWN | ASKFIRST);  
814     /* Not needed: */
815     /* run_actions(RESPAWN | ASKFIRST); */
816     /* - we return to main loop, which does this automagically */
817  }  }
818  #endif  #endif
819    
820    static int check_delayed_sigs(void)
821    {
822     int sigs_seen = 0;
823    
824     while (1) {
825     smallint sig = bb_got_signal;
826    
827     if (!sig)
828     return sigs_seen;
829     bb_got_signal = 0;
830     sigs_seen = 1;
831    #if ENABLE_FEATURE_USE_INITTAB
832     if (sig == SIGHUP)
833     reload_inittab();
834    #endif
835     if (sig == SIGINT)
836     run_actions(CTRLALTDEL);
837     }
838    }
839    
840  int init_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;  int init_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
841  int init_main(int argc UNUSED_PARAM, char **argv)  int init_main(int argc UNUSED_PARAM, char **argv)
842  {  {
843   struct init_action *a;   die_sleep = 30 * 24*60*60; /* if xmalloc would ever die... */
  pid_t wpid;  
844    
845   die_sleep = 30 * 24*60*60; /* if xmalloc will ever die... */   if (argv[1] && strcmp(argv[1], "-q") == 0) {
   
  if (argv[1] && !strcmp(argv[1], "-q")) {  
846   return kill(1, SIGHUP);   return kill(1, SIGHUP);
847   }   }
848    
# Line 802  int init_main(int argc UNUSED_PARAM, cha Line 853  int init_main(int argc UNUSED_PARAM, cha
853   ) {   ) {
854   bb_show_usage();   bb_show_usage();
855   }   }
856   /* Set up sig handlers  -- be sure to   /* Turn off rebooting via CTL-ALT-DEL - we get a
  * clear all of these in run() */  
  signal(SIGQUIT, exec_restart_action);  
  bb_signals(0  
  + (1 << SIGUSR1)  /* halt */  
  + (1 << SIGUSR2)  /* poweroff */  
  + (1 << SIGTERM)  /* reboot */  
  , halt_reboot_pwoff);  
  signal(SIGINT, ctrlaltdel_signal);  
  signal(SIGCONT, record_signo);  
  bb_signals(0  
  + (1 << SIGSTOP)  
  + (1 << SIGTSTP)  
  , stop_handler);  
   
  /* Turn off rebooting via CTL-ALT-DEL -- we get a  
857   * SIGINT on CAD so we can shut things down gracefully... */   * SIGINT on CAD so we can shut things down gracefully... */
858   init_reboot(RB_DISABLE_CAD);   reboot(RB_DISABLE_CAD); /* misnomer */
859   }   }
860    
861   /* Figure out where the default console should be */   /* Figure out where the default console should be */
# Line 837  int init_main(int argc UNUSED_PARAM, cha Line 873  int init_main(int argc UNUSED_PARAM, cha
873   if (argv[1])   if (argv[1])
874   xsetenv("RUNLEVEL", argv[1]);   xsetenv("RUNLEVEL", argv[1]);
875    
876    #if !ENABLE_FEATURE_EXTRA_QUIET
877   /* Hello world */   /* Hello world */
878   message(MAYBE_CONSOLE | L_LOG, "init started: %s", bb_banner);   message(L_CONSOLE | L_LOG, "init started: %s", bb_banner);
879    #endif
880    
881   /* Make sure there is enough memory to do something useful. */   /* Make sure there is enough memory to do something useful. */
882   if (ENABLE_SWAPONOFF) {   if (ENABLE_SWAPONOFF) {
883   struct sysinfo info;   struct sysinfo info;
884    
885   if (!sysinfo(&info) &&   if (sysinfo(&info) == 0
886   (info.mem_unit ? : 1) * (long long)info.totalram < 1024*1024)   && (info.mem_unit ? info.mem_unit : 1) * (long long)info.totalram < 1024*1024
887   {   ) {
888   message(L_CONSOLE, "Low memory, forcing swapon");   message(L_CONSOLE, "Low memory, forcing swapon");
889   /* swapon -a requires /proc typically */   /* swapon -a requires /proc typically */
890   new_init_action(SYSINIT, "mount -t proc proc /proc", "");   new_init_action(SYSINIT, "mount -t proc proc /proc", "");
# Line 858  int init_main(int argc UNUSED_PARAM, cha Line 896  int init_main(int argc UNUSED_PARAM, cha
896    
897   /* Check if we are supposed to be in single user mode */   /* Check if we are supposed to be in single user mode */
898   if (argv[1]   if (argv[1]
899   && (!strcmp(argv[1], "single") || !strcmp(argv[1], "-s") || LONE_CHAR(argv[1], '1'))   && (strcmp(argv[1], "single") == 0 || strcmp(argv[1], "-s") == 0 || LONE_CHAR(argv[1], '1'))
900   ) {   ) {
901   /* ??? shouldn't we set RUNLEVEL="b" here? */   /* ??? shouldn't we set RUNLEVEL="b" here? */
902   /* Start a shell on console */   /* Start a shell on console */
903   new_init_action(RESPAWN, bb_default_login_shell, "");   new_init_action(RESPAWN, bb_default_login_shell, "");
904   } else {   } else {
905   /* Not in single user mode -- see what inittab says */   /* Not in single user mode - see what inittab says */
906    
907   /* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined,   /* NOTE that if CONFIG_FEATURE_USE_INITTAB is NOT defined,
908   * then parse_inittab() simply adds in some default   * then parse_inittab() simply adds in some default
909   * actions(i.e., runs INIT_SCRIPT and then starts a pair   * actions(i.e., INIT_SCRIPT and a pair
910   * of "askfirst" shells */   * of "askfirst" shells */
911   parse_inittab();   parse_inittab();
912   }   }
# Line 882  int init_main(int argc UNUSED_PARAM, cha Line 920  int init_main(int argc UNUSED_PARAM, cha
920   BB_EXECVP(argv[0], argv);   BB_EXECVP(argv[0], argv);
921   } else if (enforce > 0) {   } else if (enforce > 0) {
922   /* SELinux in enforcing mode but load_policy failed */   /* SELinux in enforcing mode but load_policy failed */
923   message(L_CONSOLE, "cannot load SELinux Policy. "   message(L_CONSOLE, "can't load SELinux Policy. "
924   "Machine is in enforcing mode. Halting now.");   "Machine is in enforcing mode. Halting now.");
925   exit(EXIT_FAILURE);   exit(EXIT_FAILURE);
926   }   }
927   }   }
928  #endif /* CONFIG_SELINUX */  #endif
929    
930   /* Make the command line just say "init"  - thats all, nothing else */   /* Make the command line just say "init"  - thats all, nothing else */
931   strncpy(argv[0], "init", strlen(argv[0]));   strncpy(argv[0], "init", strlen(argv[0]));
# Line 895  int init_main(int argc UNUSED_PARAM, cha Line 933  int init_main(int argc UNUSED_PARAM, cha
933   while (*++argv)   while (*++argv)
934   memset(*argv, 0, strlen(*argv));   memset(*argv, 0, strlen(*argv));
935    
936   /* Now run everything that needs to be run */   /* Set up signal handlers */
937     if (!DEBUG_INIT) {
938     struct sigaction sa;
939    
940     bb_signals(0
941     + (1 << SIGUSR1) /* halt */
942     + (1 << SIGTERM) /* reboot */
943     + (1 << SIGUSR2) /* poweroff */
944     , halt_reboot_pwoff);
945     signal(SIGQUIT, restart_handler); /* re-exec another init */
946    
947     /* Stop handler must allow only SIGCONT inside itself */
948     memset(&sa, 0, sizeof(sa));
949     sigfillset(&sa.sa_mask);
950     sigdelset(&sa.sa_mask, SIGCONT);
951     sa.sa_handler = stop_handler;
952     /* NB: sa_flags doesn't have SA_RESTART.
953     * It must be able to interrupt wait().
954     */
955     sigaction_set(SIGTSTP, &sa); /* pause */
956     /* Does not work as intended, at least in 2.6.20.
957     * SIGSTOP is simply ignored by init:
958     */
959     sigaction_set(SIGSTOP, &sa); /* pause */
960    
961     /* SIGINT (Ctrl-Alt-Del) must interrupt wait(),
962     * setting handler without SA_RESTART flag.
963     */
964     bb_signals_recursive_norestart((1 << SIGINT), record_signo);
965     }
966    
967     /* Set up "reread /etc/inittab" handler.
968     * Handler is set up without SA_RESTART, it will interrupt syscalls.
969     */
970     if (!DEBUG_INIT && ENABLE_FEATURE_USE_INITTAB)
971     bb_signals_recursive_norestart((1 << SIGHUP), record_signo);
972    
973     /* Now run everything that needs to be run */
974   /* First run the sysinit command */   /* First run the sysinit command */
975   run_actions(SYSINIT);   run_actions(SYSINIT);
976     check_delayed_sigs();
977   /* Next run anything that wants to block */   /* Next run anything that wants to block */
978   run_actions(WAIT);   run_actions(WAIT);
979     check_delayed_sigs();
980   /* Next run anything to be run only once */   /* Next run anything to be run only once */
981   run_actions(ONCE);   run_actions(ONCE);
982    
983   /* Redefine SIGHUP to reread /etc/inittab */   /* Now run the looping stuff for the rest of forever.
984  #if ENABLE_FEATURE_USE_INITTAB   */
  signal(SIGHUP, reload_signal);  
 #else  
  signal(SIGHUP, SIG_IGN);  
 #endif  
   
  /* Now run the looping stuff for the rest of forever */  
985   while (1) {   while (1) {
986   /* run the respawn/askfirst stuff */   int maybe_WNOHANG;
987    
988     maybe_WNOHANG = check_delayed_sigs();
989    
990     /* (Re)run the respawn/askfirst stuff */
991   run_actions(RESPAWN | ASKFIRST);   run_actions(RESPAWN | ASKFIRST);
992     maybe_WNOHANG |= check_delayed_sigs();
993    
994   /* Don't consume all CPU time -- sleep a bit */   /* Don't consume all CPU time - sleep a bit */
995   sleep(1);   sleep(1);
996     maybe_WNOHANG |= check_delayed_sigs();
997    
998   /* Wait for any child process to exit */   /* Wait for any child process(es) to exit.
999   wpid = wait(NULL);   *
1000   while (wpid > 0) {   * If check_delayed_sigs above reported that a signal
1001   /* Find out who died and clean up their corpse */   * was caught, wait will be nonblocking. This ensures
1002   for (a = init_action_list; a; a = a->next) {   * that if SIGHUP has reloaded inittab, respawn and askfirst
1003   if (a->pid == wpid) {   * actions will not be delayed until next child death.
1004   /* Set the pid to 0 so that the process gets   */
1005   * restarted by run_actions() */   if (maybe_WNOHANG)
1006   a->pid = 0;   maybe_WNOHANG = WNOHANG;
1007   message(L_LOG, "process '%s' (pid %d) exited. "   while (1) {
1008   "Scheduling for restart.",   pid_t wpid;
1009   a->command, wpid);   struct init_action *a;
1010   }  
1011     /* If signals happen _in_ the wait, they interrupt it,
1012     * bb_signals_recursive_norestart set them up that way
1013     */
1014     wpid = waitpid(-1, NULL, maybe_WNOHANG);
1015     if (wpid <= 0)
1016     break;
1017    
1018     a = mark_terminated(wpid);
1019     if (a) {
1020     message(L_LOG, "process '%s' (pid %d) exited. "
1021     "Scheduling for restart.",
1022     a->command, wpid);
1023   }   }
1024   /* see if anyone else is waiting to be reaped */   /* See if anyone else is waiting to be reaped */
1025   wpid = wait_any_nohang(NULL);   maybe_WNOHANG = WNOHANG;
1026   }   }
1027   }   } /* while (1) */
1028  }  }

Legend:
Removed from v.983  
changed lines
  Added in v.984