hush: code shrink
authorDenys Vlasenko <vda.linux@googlemail.com>
Sun, 8 May 2011 22:52:15 +0000 (00:52 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sun, 8 May 2011 22:52:15 +0000 (00:52 +0200)
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
shell/hush.c

index 0b17b22..71972f7 100644 (file)
@@ -1379,6 +1379,11 @@ enum {
 #endif
 };
 
+static void sigprocmask_set(sigset_t *set)
+{
+       sigprocmask(SIG_SETMASK, set, NULL);
+}
+
 #if ENABLE_HUSH_FAST
 static void SIGCHLD_handler(int sig UNUSED_PARAM)
 {
@@ -5378,18 +5383,15 @@ static void reset_traps_to_defaults(void)
         * Stupid. It can be done with *single* &= op, but we can't use
         * the fact that G.blocked_set is implemented as a bitmask
         * in libc... */
-       mask = (SPECIAL_INTERACTIVE_SIGS >> 1);
-       sig = 1;
-       while (1) {
+       mask = SPECIAL_INTERACTIVE_SIGS;
+       sig = 0;
+       while ((mask >>= 1) != 0) {
+               sig++;
                if (mask & 1) {
                        /* Careful. Only if no trap or trap is not "" */
                        if (!G.traps || !G.traps[sig] || G.traps[sig][0])
                                sigdelset(&G.blocked_set, sig);
                }
-               mask >>= 1;
-               if (!mask)
-                       break;
-               sig++;
        }
        /* Our homegrown sig mask is saner to work with :) */
        G.non_DFL_mask &= ~SPECIAL_INTERACTIVE_SIGS;
@@ -5411,7 +5413,7 @@ static void reset_traps_to_defaults(void)
                        continue;
                sigdelset(&G.blocked_set, sig);
        }
-       sigprocmask(SIG_SETMASK, &G.blocked_set, NULL);
+       sigprocmask_set(&G.blocked_set);
 }
 
 #else /* !BB_MMU */
@@ -5541,7 +5543,7 @@ static void re_execute_shell(char ***to_free, const char *s,
 
  do_exec:
        debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s);
-       sigprocmask(SIG_SETMASK, &G.inherited_set, NULL);
+       sigprocmask_set(&G.inherited_set);
        execve(bb_busybox_exec_path, argv, pp);
        /* Fallback. Useful for init=/bin/hush usage etc */
        if (argv[0][0] == '/')
@@ -6195,7 +6197,7 @@ static void execvp_or_die(char **argv) NORETURN;
 static void execvp_or_die(char **argv)
 {
        debug_printf_exec("execing '%s'\n", argv[0]);
-       sigprocmask(SIG_SETMASK, &G.inherited_set, NULL);
+       sigprocmask_set(&G.inherited_set);
        execvp(argv[0], argv);
        bb_perror_msg("can't execute '%s'", argv[0]);
        _exit(127); /* bash compat */
@@ -6327,7 +6329,7 @@ static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save,
 # endif
                        /* Re-exec ourselves */
                        debug_printf_exec("re-execing applet '%s'\n", argv[0]);
-                       sigprocmask(SIG_SETMASK, &G.inherited_set, NULL);
+                       sigprocmask_set(&G.inherited_set);
                        execv(bb_busybox_exec_path, argv);
                        /* If they called chroot or otherwise made the binary no longer
                         * executable, fall through */
@@ -7435,84 +7437,89 @@ static void init_sigmasks(void)
 {
        unsigned sig;
        unsigned mask;
-       sigset_t old_blocked_set;
 
+       /* POSIX allows shell to re-enable SIGCHLD
+        * even if it was SIG_IGN on entry */
+#if ENABLE_HUSH_FAST
+       G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */
+#endif
        if (!G.inherited_set_is_saved) {
+#if ENABLE_HUSH_FAST
+               signal(SIGCHLD, SIGCHLD_handler);
+#else
+               signal(SIGCHLD, SIG_DFL);
+#endif
                sigprocmask(SIG_SETMASK, NULL, &G.blocked_set);
                G.inherited_set = G.blocked_set;
        }
-       old_blocked_set = G.blocked_set;
 
+       /* Which signals are shell-special? */
        mask = (1 << SIGQUIT);
        if (G_interactive_fd) {
-               mask = (1 << SIGQUIT) | SPECIAL_INTERACTIVE_SIGS;
+               mask |= SPECIAL_INTERACTIVE_SIGS;
                if (G_saved_tty_pgrp) /* we have ctty, job control sigs work */
                        mask |= SPECIAL_JOB_SIGS;
        }
        G.non_DFL_mask = mask;
 
+       /* Block them. And unblock SIGCHLD */
        sig = 0;
-       while (mask) {
+       while ((mask >>= 1) != 0) {
+               sig++;
                if (mask & 1)
                        sigaddset(&G.blocked_set, sig);
-               mask >>= 1;
-               sig++;
        }
        sigdelset(&G.blocked_set, SIGCHLD);
 
-       if (memcmp(&old_blocked_set, &G.blocked_set, sizeof(old_blocked_set)) != 0)
-               sigprocmask(SIG_SETMASK, &G.blocked_set, NULL);
-
-       /* POSIX allows shell to re-enable SIGCHLD
-        * even if it was SIG_IGN on entry */
-#if ENABLE_HUSH_FAST
-       G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */
-       if (!G.inherited_set_is_saved)
-               signal(SIGCHLD, SIGCHLD_handler);
-#else
-       if (!G.inherited_set_is_saved)
-               signal(SIGCHLD, SIG_DFL);
-#endif
+       if (memcmp(&G.inherited_set, &G.blocked_set, sizeof(G.inherited_set)) != 0)
+               sigprocmask_set(&G.blocked_set);
 
        G.inherited_set_is_saved = 1;
 }
 
 #if ENABLE_HUSH_JOB
 /* helper */
-static void maybe_set_to_sigexit(int sig)
+/* Set handlers to restore tty pgrp and exit */
+static void set_fatal_handlers_to_sigexit(void)
 {
        void (*handler)(int);
+       unsigned fatal_sigs, sig;
+
+       /* We will restore tty pgrp on these signals */
+       fatal_sigs = 0
+               + (1 << SIGILL ) * HUSH_DEBUG
+               + (1 << SIGFPE ) * HUSH_DEBUG
+               + (1 << SIGBUS ) * HUSH_DEBUG
+               + (1 << SIGSEGV) * HUSH_DEBUG
+               + (1 << SIGTRAP) * HUSH_DEBUG
+               + (1 << SIGABRT)
+       /* bash 3.2 seems to handle these just like 'fatal' ones */
+               + (1 << SIGPIPE)
+               + (1 << SIGALRM)
+       /* if we are interactive, SIGHUP, SIGTERM and SIGINT are masked.
+        * if we aren't interactive... but in this case
+        * we never want to restore pgrp on exit, and this fn is not called */
+               /*+ (1 << SIGHUP )*/
+               /*+ (1 << SIGTERM)*/
+               /*+ (1 << SIGINT )*/
+       ;
+
        /* non_DFL_mask'ed signals are, well, masked,
         * no need to set handler for them.
         */
-       if (!((G.non_DFL_mask >> sig) & 1)) {
+       fatal_sigs &= ~G.non_DFL_mask;
+
+        /* For each sig in fatal_sigs... */
+       sig = 0;
+       while ((fatal_sigs >>= 1) != 0) {
+               sig++;
+               if (!(fatal_sigs & 1))
+                       continue;
                handler = signal(sig, sigexit);
                if (handler == SIG_IGN) /* oops... restore back to IGN! */
                        signal(sig, handler);
        }
 }
-/* Set handlers to restore tty pgrp and exit */
-static void set_fatal_handlers(void)
-{
-       /* We _must_ restore tty pgrp on fatal signals */
-       if (HUSH_DEBUG) {
-               maybe_set_to_sigexit(SIGILL );
-               maybe_set_to_sigexit(SIGFPE );
-               maybe_set_to_sigexit(SIGBUS );
-               maybe_set_to_sigexit(SIGSEGV);
-               maybe_set_to_sigexit(SIGTRAP);
-       } /* else: hush is perfect. what SEGV? */
-       maybe_set_to_sigexit(SIGABRT);
-       /* bash 3.2 seems to handle these just like 'fatal' ones */
-       maybe_set_to_sigexit(SIGPIPE);
-       maybe_set_to_sigexit(SIGALRM);
-       /* if we are interactive, SIGHUP, SIGTERM and SIGINT are masked.
-        * if we aren't interactive... but in this case
-        * we never want to restore pgrp on exit, and this fn is not called */
-       /*maybe_set_to_sigexit(SIGHUP );*/
-       /*maybe_set_to_sigexit(SIGTERM);*/
-       /*maybe_set_to_sigexit(SIGINT );*/
-}
 #endif
 
 static int set_mode(int state, char mode, const char *o_opt)
@@ -7769,7 +7776,7 @@ int hush_main(int argc, char **argv)
                                                sigaddset(&G.blocked_set, sig);
                                        }
                                }
-                               sigprocmask(SIG_SETMASK, &G.blocked_set, NULL);
+                               sigprocmask_set(&G.blocked_set);
                        }
 # if ENABLE_HUSH_LOOPS
                        optarg++;
@@ -7910,7 +7917,7 @@ int hush_main(int argc, char **argv)
 
                if (G_saved_tty_pgrp) {
                        /* Set other signals to restore saved_tty_pgrp */
-                       set_fatal_handlers();
+                       set_fatal_handlers_to_sigexit();
                        /* Put ourselves in our own process group
                         * (bash, too, does this only if ctty is available) */
                        bb_setpgrp(); /* is the same as setpgid(our_pid, our_pid); */
@@ -8301,7 +8308,7 @@ static int FAST_FUNC builtin_trap(char **argv)
                                sigdelset(&G.blocked_set, sig);
                        }
                }
-               sigprocmask(SIG_SETMASK, &G.blocked_set, NULL);
+               sigprocmask_set(&G.blocked_set);
                return ret;
        }
 
@@ -8858,7 +8865,7 @@ static int FAST_FUNC builtin_wait(char **argv)
                 * $
                 */
                sigaddset(&G.blocked_set, SIGCHLD);
-               sigprocmask(SIG_SETMASK, &G.blocked_set, NULL);
+               sigprocmask_set(&G.blocked_set);
                while (1) {
                        checkjobs(NULL);
                        if (errno == ECHILD)
@@ -8875,7 +8882,7 @@ static int FAST_FUNC builtin_wait(char **argv)
                        }
                }
                sigdelset(&G.blocked_set, SIGCHLD);
-               sigprocmask(SIG_SETMASK, &G.blocked_set, NULL);
+               sigprocmask_set(&G.blocked_set);
                return ret;
        }