top: remove GCCisms
[oweals/busybox.git] / init / init.c
index 5b9820b4a05a2cdc5c9a1d68c9cae4d8031d6573..6bee8f35ca5bf49c3c3879ddaa2b48a917ef3703 100644 (file)
@@ -14,6 +14,7 @@
 #include <paths.h>
 #include <sys/reboot.h>
 #include <sys/resource.h>
+#include <linux/vt.h>
 
 
 /* Was a CONFIG_xxx option. A lot of people were building
@@ -161,33 +162,9 @@ static void message(int where, const char *fmt, ...)
        }
 }
 
-/* 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];
-};
 static void console_init(void)
 {
-       struct serial_struct sr;
+       int vtno;
        char *s;
 
        s = getenv("CONSOLE");
@@ -211,8 +188,9 @@ static void console_init(void)
        }
 
        s = getenv("TERM");
-       if (ioctl(STDIN_FILENO, TIOCGSERIAL, &sr) == 0) {
-               /* Force the TERM setting to vt102 for serial console
+       if (ioctl(STDIN_FILENO, VT_OPENQRY, &vtno) != 0) {
+               /* Not a linux terminal, probably serial console.
+                * Force the TERM setting to vt102
                 * if TERM is set to linux (the default) */
                if (!s || strcmp(s, "linux") == 0)
                        putenv((char*)"TERM=vt102");
@@ -336,20 +314,22 @@ static pid_t run(const struct init_action *a)
 {
        pid_t pid;
 
+       /* Careful: don't be affected by a signal in vforked child */
+       sigprocmask_allsigs(SIG_BLOCK);
        if (BB_MMU && (a->action_type & ASKFIRST))
                pid = fork();
        else
                pid = vfork();
        if (pid < 0)
                message(L_LOG | L_CONSOLE, "can't fork");
-       if (pid)
+       if (pid) {
+               sigprocmask_allsigs(SIG_UNBLOCK);
                return pid; /* Parent or error */
+       }
 
        /* Child */
 
        /* Reset signal handlers that were set by the parent process */
-//TODO: block signals across fork(), prevent them to affect child before
-//signals are reset?
        bb_signals(0
                + (1 << SIGUSR1)
                + (1 << SIGUSR2)
@@ -359,6 +339,7 @@ static pid_t run(const struct init_action *a)
                + (1 << SIGHUP)
                + (1 << SIGTSTP)
                , SIG_DFL);
+       sigprocmask_allsigs(SIG_UNBLOCK);
 
        /* Create a new session and make ourself the process group leader */
        setsid();
@@ -881,7 +862,7 @@ int init_main(int argc UNUSED_PARAM, char **argv)
                struct sysinfo info;
 
                if (sysinfo(&info) == 0
-                && (info.mem_unit ? : 1) * (long long)info.totalram < 1024*1024
+                && (info.mem_unit ? info.mem_unit : 1) * (long long)info.totalram < 1024*1024
                ) {
                        message(L_CONSOLE, "Low memory, forcing swapon");
                        /* swapon -a requires /proc typically */
@@ -979,43 +960,48 @@ int init_main(int argc UNUSED_PARAM, char **argv)
                bb_signals_recursive_norestart((1 << SIGHUP), record_signo);
 
        /* Now run the looping stuff for the rest of forever.
-        * NB: if delayed signal happened, avoid blocking in wait().
         */
        while (1) {
-               pid_t wpid;
-               int got_sigs;
+               int maybe_WNOHANG;
 
-               got_sigs = check_delayed_sigs();
+               maybe_WNOHANG = check_delayed_sigs();
 
                /* (Re)run the respawn/askfirst stuff */
                run_actions(RESPAWN | ASKFIRST);
-
-               got_sigs |= check_delayed_sigs();
+               maybe_WNOHANG |= check_delayed_sigs();
 
                /* Don't consume all CPU time - sleep a bit */
                sleep(1);
-
-               got_sigs |= check_delayed_sigs();
-
-               if (got_sigs)
-                       goto dont_block;
-               /* Wait for any child process to exit.
-                * NB: "delayed" signals will also interrupt this wait(),
-                * bb_signals_recursive_norestart() set them up for that.
-                * This guarantees we won't be stuck here
-                * till next orphan dies.
+               maybe_WNOHANG |= check_delayed_sigs();
+
+               /* Wait for any child process(es) to exit.
+                *
+                * If check_delayed_sigs above reported that a signal
+                * was caught, wait will be nonblocking. This ensures
+                * that if SIGHUP has reloaded inittab, respawn and askfirst
+                * actions will not be delayed until next child death.
                 */
-               wpid = wait(NULL);
-               while (wpid > 0) {
-                       struct init_action *a = mark_terminated(wpid);
+               if (maybe_WNOHANG)
+                       maybe_WNOHANG = WNOHANG;
+               while (1) {
+                       pid_t wpid;
+                       struct init_action *a;
+
+                       /* If signals happen _in_ the wait, they interrupt it,
+                        * bb_signals_recursive_norestart set them up that way
+                        */
+                       wpid = waitpid(-1, NULL, maybe_WNOHANG);
+                       if (wpid <= 0)
+                               break;
+
+                       a = mark_terminated(wpid);
                        if (a) {
                                message(L_LOG, "process '%s' (pid %d) exited. "
                                                "Scheduling for restart.",
                                                a->command, wpid);
                        }
                        /* See if anyone else is waiting to be reaped */
- dont_block:
-                       wpid = wait_any_nohang(NULL);
+                       maybe_WNOHANG = WNOHANG;
                }
        } /* while (1) */
 }