aboutsummaryrefslogtreecommitdiff
path: root/shell/hush.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2011-05-09 00:52:15 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2011-05-09 00:52:15 +0200
commit54e9e1217c67563d70d6e2b14021293f707d7927 (patch)
treef8cd7fe165e7ac70eef901330fb7f95db68dbdd1 /shell/hush.c
parent80542bad2f1df9d99b579c9eeb3c2675c14c72c0 (diff)
downloadbusybox-w32-54e9e1217c67563d70d6e2b14021293f707d7927.tar.gz
busybox-w32-54e9e1217c67563d70d6e2b14021293f707d7927.tar.bz2
busybox-w32-54e9e1217c67563d70d6e2b14021293f707d7927.zip
hush: code shrink
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to '')
-rw-r--r--shell/hush.c125
1 files changed, 66 insertions, 59 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 0b17b222d..71972f751 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -1379,6 +1379,11 @@ enum {
1379#endif 1379#endif
1380}; 1380};
1381 1381
1382static void sigprocmask_set(sigset_t *set)
1383{
1384 sigprocmask(SIG_SETMASK, set, NULL);
1385}
1386
1382#if ENABLE_HUSH_FAST 1387#if ENABLE_HUSH_FAST
1383static void SIGCHLD_handler(int sig UNUSED_PARAM) 1388static void SIGCHLD_handler(int sig UNUSED_PARAM)
1384{ 1389{
@@ -5378,18 +5383,15 @@ static void reset_traps_to_defaults(void)
5378 * Stupid. It can be done with *single* &= op, but we can't use 5383 * Stupid. It can be done with *single* &= op, but we can't use
5379 * the fact that G.blocked_set is implemented as a bitmask 5384 * the fact that G.blocked_set is implemented as a bitmask
5380 * in libc... */ 5385 * in libc... */
5381 mask = (SPECIAL_INTERACTIVE_SIGS >> 1); 5386 mask = SPECIAL_INTERACTIVE_SIGS;
5382 sig = 1; 5387 sig = 0;
5383 while (1) { 5388 while ((mask >>= 1) != 0) {
5389 sig++;
5384 if (mask & 1) { 5390 if (mask & 1) {
5385 /* Careful. Only if no trap or trap is not "" */ 5391 /* Careful. Only if no trap or trap is not "" */
5386 if (!G.traps || !G.traps[sig] || G.traps[sig][0]) 5392 if (!G.traps || !G.traps[sig] || G.traps[sig][0])
5387 sigdelset(&G.blocked_set, sig); 5393 sigdelset(&G.blocked_set, sig);
5388 } 5394 }
5389 mask >>= 1;
5390 if (!mask)
5391 break;
5392 sig++;
5393 } 5395 }
5394 /* Our homegrown sig mask is saner to work with :) */ 5396 /* Our homegrown sig mask is saner to work with :) */
5395 G.non_DFL_mask &= ~SPECIAL_INTERACTIVE_SIGS; 5397 G.non_DFL_mask &= ~SPECIAL_INTERACTIVE_SIGS;
@@ -5411,7 +5413,7 @@ static void reset_traps_to_defaults(void)
5411 continue; 5413 continue;
5412 sigdelset(&G.blocked_set, sig); 5414 sigdelset(&G.blocked_set, sig);
5413 } 5415 }
5414 sigprocmask(SIG_SETMASK, &G.blocked_set, NULL); 5416 sigprocmask_set(&G.blocked_set);
5415} 5417}
5416 5418
5417#else /* !BB_MMU */ 5419#else /* !BB_MMU */
@@ -5541,7 +5543,7 @@ static void re_execute_shell(char ***to_free, const char *s,
5541 5543
5542 do_exec: 5544 do_exec:
5543 debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s); 5545 debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s);
5544 sigprocmask(SIG_SETMASK, &G.inherited_set, NULL); 5546 sigprocmask_set(&G.inherited_set);
5545 execve(bb_busybox_exec_path, argv, pp); 5547 execve(bb_busybox_exec_path, argv, pp);
5546 /* Fallback. Useful for init=/bin/hush usage etc */ 5548 /* Fallback. Useful for init=/bin/hush usage etc */
5547 if (argv[0][0] == '/') 5549 if (argv[0][0] == '/')
@@ -6195,7 +6197,7 @@ static void execvp_or_die(char **argv) NORETURN;
6195static void execvp_or_die(char **argv) 6197static void execvp_or_die(char **argv)
6196{ 6198{
6197 debug_printf_exec("execing '%s'\n", argv[0]); 6199 debug_printf_exec("execing '%s'\n", argv[0]);
6198 sigprocmask(SIG_SETMASK, &G.inherited_set, NULL); 6200 sigprocmask_set(&G.inherited_set);
6199 execvp(argv[0], argv); 6201 execvp(argv[0], argv);
6200 bb_perror_msg("can't execute '%s'", argv[0]); 6202 bb_perror_msg("can't execute '%s'", argv[0]);
6201 _exit(127); /* bash compat */ 6203 _exit(127); /* bash compat */
@@ -6327,7 +6329,7 @@ static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save,
6327# endif 6329# endif
6328 /* Re-exec ourselves */ 6330 /* Re-exec ourselves */
6329 debug_printf_exec("re-execing applet '%s'\n", argv[0]); 6331 debug_printf_exec("re-execing applet '%s'\n", argv[0]);
6330 sigprocmask(SIG_SETMASK, &G.inherited_set, NULL); 6332 sigprocmask_set(&G.inherited_set);
6331 execv(bb_busybox_exec_path, argv); 6333 execv(bb_busybox_exec_path, argv);
6332 /* If they called chroot or otherwise made the binary no longer 6334 /* If they called chroot or otherwise made the binary no longer
6333 * executable, fall through */ 6335 * executable, fall through */
@@ -7435,84 +7437,89 @@ static void init_sigmasks(void)
7435{ 7437{
7436 unsigned sig; 7438 unsigned sig;
7437 unsigned mask; 7439 unsigned mask;
7438 sigset_t old_blocked_set;
7439 7440
7441 /* POSIX allows shell to re-enable SIGCHLD
7442 * even if it was SIG_IGN on entry */
7443#if ENABLE_HUSH_FAST
7444 G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */
7445#endif
7440 if (!G.inherited_set_is_saved) { 7446 if (!G.inherited_set_is_saved) {
7447#if ENABLE_HUSH_FAST
7448 signal(SIGCHLD, SIGCHLD_handler);
7449#else
7450 signal(SIGCHLD, SIG_DFL);
7451#endif
7441 sigprocmask(SIG_SETMASK, NULL, &G.blocked_set); 7452 sigprocmask(SIG_SETMASK, NULL, &G.blocked_set);
7442 G.inherited_set = G.blocked_set; 7453 G.inherited_set = G.blocked_set;
7443 } 7454 }
7444 old_blocked_set = G.blocked_set;
7445 7455
7456 /* Which signals are shell-special? */
7446 mask = (1 << SIGQUIT); 7457 mask = (1 << SIGQUIT);
7447 if (G_interactive_fd) { 7458 if (G_interactive_fd) {
7448 mask = (1 << SIGQUIT) | SPECIAL_INTERACTIVE_SIGS; 7459 mask |= SPECIAL_INTERACTIVE_SIGS;
7449 if (G_saved_tty_pgrp) /* we have ctty, job control sigs work */ 7460 if (G_saved_tty_pgrp) /* we have ctty, job control sigs work */
7450 mask |= SPECIAL_JOB_SIGS; 7461 mask |= SPECIAL_JOB_SIGS;
7451 } 7462 }
7452 G.non_DFL_mask = mask; 7463 G.non_DFL_mask = mask;
7453 7464
7465 /* Block them. And unblock SIGCHLD */
7454 sig = 0; 7466 sig = 0;
7455 while (mask) { 7467 while ((mask >>= 1) != 0) {
7468 sig++;
7456 if (mask & 1) 7469 if (mask & 1)
7457 sigaddset(&G.blocked_set, sig); 7470 sigaddset(&G.blocked_set, sig);
7458 mask >>= 1;
7459 sig++;
7460 } 7471 }
7461 sigdelset(&G.blocked_set, SIGCHLD); 7472 sigdelset(&G.blocked_set, SIGCHLD);
7462 7473
7463 if (memcmp(&old_blocked_set, &G.blocked_set, sizeof(old_blocked_set)) != 0) 7474 if (memcmp(&G.inherited_set, &G.blocked_set, sizeof(G.inherited_set)) != 0)
7464 sigprocmask(SIG_SETMASK, &G.blocked_set, NULL); 7475 sigprocmask_set(&G.blocked_set);
7465
7466 /* POSIX allows shell to re-enable SIGCHLD
7467 * even if it was SIG_IGN on entry */
7468#if ENABLE_HUSH_FAST
7469 G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */
7470 if (!G.inherited_set_is_saved)
7471 signal(SIGCHLD, SIGCHLD_handler);
7472#else
7473 if (!G.inherited_set_is_saved)
7474 signal(SIGCHLD, SIG_DFL);
7475#endif
7476 7476
7477 G.inherited_set_is_saved = 1; 7477 G.inherited_set_is_saved = 1;
7478} 7478}
7479 7479
7480#if ENABLE_HUSH_JOB 7480#if ENABLE_HUSH_JOB
7481/* helper */ 7481/* helper */
7482static void maybe_set_to_sigexit(int sig) 7482/* Set handlers to restore tty pgrp and exit */
7483static void set_fatal_handlers_to_sigexit(void)
7483{ 7484{
7484 void (*handler)(int); 7485 void (*handler)(int);
7486 unsigned fatal_sigs, sig;
7487
7488 /* We will restore tty pgrp on these signals */
7489 fatal_sigs = 0
7490 + (1 << SIGILL ) * HUSH_DEBUG
7491 + (1 << SIGFPE ) * HUSH_DEBUG
7492 + (1 << SIGBUS ) * HUSH_DEBUG
7493 + (1 << SIGSEGV) * HUSH_DEBUG
7494 + (1 << SIGTRAP) * HUSH_DEBUG
7495 + (1 << SIGABRT)
7496 /* bash 3.2 seems to handle these just like 'fatal' ones */
7497 + (1 << SIGPIPE)
7498 + (1 << SIGALRM)
7499 /* if we are interactive, SIGHUP, SIGTERM and SIGINT are masked.
7500 * if we aren't interactive... but in this case
7501 * we never want to restore pgrp on exit, and this fn is not called */
7502 /*+ (1 << SIGHUP )*/
7503 /*+ (1 << SIGTERM)*/
7504 /*+ (1 << SIGINT )*/
7505 ;
7506
7485 /* non_DFL_mask'ed signals are, well, masked, 7507 /* non_DFL_mask'ed signals are, well, masked,
7486 * no need to set handler for them. 7508 * no need to set handler for them.
7487 */ 7509 */
7488 if (!((G.non_DFL_mask >> sig) & 1)) { 7510 fatal_sigs &= ~G.non_DFL_mask;
7511
7512 /* For each sig in fatal_sigs... */
7513 sig = 0;
7514 while ((fatal_sigs >>= 1) != 0) {
7515 sig++;
7516 if (!(fatal_sigs & 1))
7517 continue;
7489 handler = signal(sig, sigexit); 7518 handler = signal(sig, sigexit);
7490 if (handler == SIG_IGN) /* oops... restore back to IGN! */ 7519 if (handler == SIG_IGN) /* oops... restore back to IGN! */
7491 signal(sig, handler); 7520 signal(sig, handler);
7492 } 7521 }
7493} 7522}
7494/* Set handlers to restore tty pgrp and exit */
7495static void set_fatal_handlers(void)
7496{
7497 /* We _must_ restore tty pgrp on fatal signals */
7498 if (HUSH_DEBUG) {
7499 maybe_set_to_sigexit(SIGILL );
7500 maybe_set_to_sigexit(SIGFPE );
7501 maybe_set_to_sigexit(SIGBUS );
7502 maybe_set_to_sigexit(SIGSEGV);
7503 maybe_set_to_sigexit(SIGTRAP);
7504 } /* else: hush is perfect. what SEGV? */
7505 maybe_set_to_sigexit(SIGABRT);
7506 /* bash 3.2 seems to handle these just like 'fatal' ones */
7507 maybe_set_to_sigexit(SIGPIPE);
7508 maybe_set_to_sigexit(SIGALRM);
7509 /* if we are interactive, SIGHUP, SIGTERM and SIGINT are masked.
7510 * if we aren't interactive... but in this case
7511 * we never want to restore pgrp on exit, and this fn is not called */
7512 /*maybe_set_to_sigexit(SIGHUP );*/
7513 /*maybe_set_to_sigexit(SIGTERM);*/
7514 /*maybe_set_to_sigexit(SIGINT );*/
7515}
7516#endif 7523#endif
7517 7524
7518static int set_mode(int state, char mode, const char *o_opt) 7525static int set_mode(int state, char mode, const char *o_opt)
@@ -7769,7 +7776,7 @@ int hush_main(int argc, char **argv)
7769 sigaddset(&G.blocked_set, sig); 7776 sigaddset(&G.blocked_set, sig);
7770 } 7777 }
7771 } 7778 }
7772 sigprocmask(SIG_SETMASK, &G.blocked_set, NULL); 7779 sigprocmask_set(&G.blocked_set);
7773 } 7780 }
7774# if ENABLE_HUSH_LOOPS 7781# if ENABLE_HUSH_LOOPS
7775 optarg++; 7782 optarg++;
@@ -7910,7 +7917,7 @@ int hush_main(int argc, char **argv)
7910 7917
7911 if (G_saved_tty_pgrp) { 7918 if (G_saved_tty_pgrp) {
7912 /* Set other signals to restore saved_tty_pgrp */ 7919 /* Set other signals to restore saved_tty_pgrp */
7913 set_fatal_handlers(); 7920 set_fatal_handlers_to_sigexit();
7914 /* Put ourselves in our own process group 7921 /* Put ourselves in our own process group
7915 * (bash, too, does this only if ctty is available) */ 7922 * (bash, too, does this only if ctty is available) */
7916 bb_setpgrp(); /* is the same as setpgid(our_pid, our_pid); */ 7923 bb_setpgrp(); /* is the same as setpgid(our_pid, our_pid); */
@@ -8301,7 +8308,7 @@ static int FAST_FUNC builtin_trap(char **argv)
8301 sigdelset(&G.blocked_set, sig); 8308 sigdelset(&G.blocked_set, sig);
8302 } 8309 }
8303 } 8310 }
8304 sigprocmask(SIG_SETMASK, &G.blocked_set, NULL); 8311 sigprocmask_set(&G.blocked_set);
8305 return ret; 8312 return ret;
8306 } 8313 }
8307 8314
@@ -8858,7 +8865,7 @@ static int FAST_FUNC builtin_wait(char **argv)
8858 * $ 8865 * $
8859 */ 8866 */
8860 sigaddset(&G.blocked_set, SIGCHLD); 8867 sigaddset(&G.blocked_set, SIGCHLD);
8861 sigprocmask(SIG_SETMASK, &G.blocked_set, NULL); 8868 sigprocmask_set(&G.blocked_set);
8862 while (1) { 8869 while (1) {
8863 checkjobs(NULL); 8870 checkjobs(NULL);
8864 if (errno == ECHILD) 8871 if (errno == ECHILD)
@@ -8875,7 +8882,7 @@ static int FAST_FUNC builtin_wait(char **argv)
8875 } 8882 }
8876 } 8883 }
8877 sigdelset(&G.blocked_set, SIGCHLD); 8884 sigdelset(&G.blocked_set, SIGCHLD);
8878 sigprocmask(SIG_SETMASK, &G.blocked_set, NULL); 8885 sigprocmask_set(&G.blocked_set);
8879 return ret; 8886 return ret;
8880 } 8887 }
8881 8888