aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2011-05-12 02:10:33 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2011-05-12 02:10:33 +0200
commitf58f705c5812cec5d5308ae29baceeb648d08e24 (patch)
tree8028164dcbc39a2cc18afce67e7ef5d72926f060 /shell
parent9d6cbafe728c9100a35e29ba7a3729c5303e73ea (diff)
downloadbusybox-w32-f58f705c5812cec5d5308ae29baceeb648d08e24.tar.gz
busybox-w32-f58f705c5812cec5d5308ae29baceeb648d08e24.tar.bz2
busybox-w32-f58f705c5812cec5d5308ae29baceeb648d08e24.zip
hush: fix login shell's signal handling; add -l option so that it's easier to test
function old new delta hush_main 958 1001 +43 install_special_sighandlers 47 52 +5 packed_usage 28752 28741 -11 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 48/-11) Total: 37 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r--shell/hush.c67
1 files changed, 35 insertions, 32 deletions
diff --git a/shell/hush.c b/shell/hush.c
index b2c3a752e..cdd4be4e3 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -260,7 +260,7 @@ typedef void (*hush_sighandler_t)(int);
260 * therefore we don't show them either. 260 * therefore we don't show them either.
261 */ 261 */
262//usage:#define hush_trivial_usage 262//usage:#define hush_trivial_usage
263//usage: "[-nx] [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]" 263//usage: "[-nxl] [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
264//usage:#define hush_full_usage "\n\n" 264//usage:#define hush_full_usage "\n\n"
265//usage: "Unix shell interpreter" 265//usage: "Unix shell interpreter"
266 266
@@ -1493,8 +1493,8 @@ static sighandler_t pick_sighandler(unsigned sig)
1493 handler = record_pending_signo; 1493 handler = record_pending_signo;
1494 /* TTIN/TTOU/TSTS can't be set to record_pending_signo 1494 /* TTIN/TTOU/TSTS can't be set to record_pending_signo
1495 * in order to ignore them: they will be raised 1495 * in order to ignore them: they will be raised
1496 * in an endless loop then when we try to do some 1496 * in an endless loop when we try to do some
1497 * terminal ioctls! We do nave to _ignore_ these. 1497 * terminal ioctls! We do have to _ignore_ these.
1498 */ 1498 */
1499 if (SPECIAL_JOBSTOP_SIGS & sigmask) 1499 if (SPECIAL_JOBSTOP_SIGS & sigmask)
1500 handler = SIG_IGN; 1500 handler = SIG_IGN;
@@ -1508,9 +1508,6 @@ static void hush_exit(int exitcode)
1508{ 1508{
1509 fflush_all(); 1509 fflush_all();
1510 if (G.exiting <= 0 && G.traps && G.traps[0] && G.traps[0][0]) { 1510 if (G.exiting <= 0 && G.traps && G.traps[0] && G.traps[0][0]) {
1511 /* Prevent recursion:
1512 * trap "echo Hi; exit" EXIT; exit
1513 */
1514 char *argv[3]; 1511 char *argv[3];
1515 /* argv[0] is unused */ 1512 /* argv[0] is unused */
1516 argv[1] = G.traps[0]; 1513 argv[1] = G.traps[0];
@@ -5474,7 +5471,8 @@ static void reset_traps_to_defaults(void)
5474 G_fatal_sig_mask = 0; 5471 G_fatal_sig_mask = 0;
5475#endif 5472#endif
5476 G.special_sig_mask &= ~SPECIAL_INTERACTIVE_SIGS; 5473 G.special_sig_mask &= ~SPECIAL_INTERACTIVE_SIGS;
5477 /* SIGQUIT and maybe SPECIAL_JOBSTOP_SIGS remain set in G.special_sig_mask */ 5474 /* SIGQUIT,SIGCHLD and maybe SPECIAL_JOBSTOP_SIGS
5475 * remain set in G.special_sig_mask */
5478 5476
5479 if (!G.traps) 5477 if (!G.traps)
5480 return; 5478 return;
@@ -5537,7 +5535,6 @@ static void re_execute_shell(char ***to_free, const char *s,
5537 for (sig = 1; sig < NSIG; sig++) { 5535 for (sig = 1; sig < NSIG; sig++) {
5538 if (G.traps[sig] && !G.traps[sig][0]) 5536 if (G.traps[sig] && !G.traps[sig][0])
5539 empty_trap_mask |= 1LL << sig; 5537 empty_trap_mask |= 1LL << sig;
5540///vda: optimize
5541 } 5538 }
5542 } 5539 }
5543 5540
@@ -7540,9 +7537,6 @@ static void install_special_sighandlers(void)
7540{ 7537{
7541 unsigned mask; 7538 unsigned mask;
7542 7539
7543 if (G.special_sig_mask != 0)
7544 return;
7545
7546 /* Which signals are shell-special? */ 7540 /* Which signals are shell-special? */
7547 mask = (1 << SIGQUIT) | (1 << SIGCHLD); 7541 mask = (1 << SIGQUIT) | (1 << SIGCHLD);
7548 if (G_interactive_fd) { 7542 if (G_interactive_fd) {
@@ -7550,9 +7544,12 @@ static void install_special_sighandlers(void)
7550 if (G_saved_tty_pgrp) /* we have ctty, job control sigs work */ 7544 if (G_saved_tty_pgrp) /* we have ctty, job control sigs work */
7551 mask |= SPECIAL_JOBSTOP_SIGS; 7545 mask |= SPECIAL_JOBSTOP_SIGS;
7552 } 7546 }
7553 G.special_sig_mask = mask; 7547 /* Careful, do not re-install handlers we already installed */
7554 7548 if (G.special_sig_mask != mask) {
7555 install_sighandlers(mask); 7549 unsigned diff = mask & ~G.special_sig_mask;
7550 G.special_sig_mask = mask;
7551 install_sighandlers(diff);
7552 }
7556} 7553}
7557 7554
7558#if ENABLE_HUSH_JOB 7555#if ENABLE_HUSH_JOB
@@ -7573,17 +7570,14 @@ static void install_fatal_sighandlers(void)
7573 /* bash 3.2 seems to handle these just like 'fatal' ones */ 7570 /* bash 3.2 seems to handle these just like 'fatal' ones */
7574 + (1 << SIGPIPE) 7571 + (1 << SIGPIPE)
7575 + (1 << SIGALRM) 7572 + (1 << SIGALRM)
7576 /* if we are interactive, SIGHUP, SIGTERM and SIGINT are masked. 7573 /* if we are interactive, SIGHUP, SIGTERM and SIGINT are special sigs.
7577 * if we aren't interactive... but in this case 7574 * if we aren't interactive... but in this case
7578 * we never want to restore pgrp on exit, and this fn is not called */ 7575 * we never want to restore pgrp on exit, and this fn is not called
7576 */
7579 /*+ (1 << SIGHUP )*/ 7577 /*+ (1 << SIGHUP )*/
7580 /*+ (1 << SIGTERM)*/ 7578 /*+ (1 << SIGTERM)*/
7581 /*+ (1 << SIGINT )*/ 7579 /*+ (1 << SIGINT )*/
7582 ; 7580 ;
7583 /* special_sig_mask'ed signals are set to record_pending_signo
7584 * no need to set handler for them.
7585 */
7586 /*mask &= ~G.special_sig_mask; - they never overlap */
7587 G_fatal_sig_mask = mask; 7581 G_fatal_sig_mask = mask;
7588 7582
7589 install_sighandlers(mask); 7583 install_sighandlers(mask);
@@ -7632,6 +7626,10 @@ static int set_mode(int state, char mode, const char *o_opt)
7632int hush_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 7626int hush_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
7633int hush_main(int argc, char **argv) 7627int hush_main(int argc, char **argv)
7634{ 7628{
7629 enum {
7630 OPT_login = (1 << 0),
7631 };
7632 unsigned flags;
7635 int opt; 7633 int opt;
7636 unsigned builtin_argc; 7634 unsigned builtin_argc;
7637 char **e; 7635 char **e;
@@ -7735,8 +7733,6 @@ int hush_main(int argc, char **argv)
7735# endif 7733# endif
7736#endif 7734#endif
7737 7735
7738 G.global_argc = argc;
7739 G.global_argv = argv;
7740 /* Initialize some more globals to non-zero values */ 7736 /* Initialize some more globals to non-zero values */
7741 cmdedit_update_prompt(); 7737 cmdedit_update_prompt();
7742 7738
@@ -7752,14 +7748,14 @@ int hush_main(int argc, char **argv)
7752 * "sh -c <cmds>" or login shell's /etc/profile and friends. 7748 * "sh -c <cmds>" or login shell's /etc/profile and friends.
7753 * If we later decide that we are interactive, we run install_special_sighandlers() 7749 * If we later decide that we are interactive, we run install_special_sighandlers()
7754 * in order to intercept (more) signals. 7750 * in order to intercept (more) signals.
7755//FIXME: re-running is currently most likely broken, it's a no-op.
7756 */ 7751 */
7757 7752
7758 /* Parse options */ 7753 /* Parse options */
7759 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */ 7754 /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */
7755 flags = (argv[0] && argv[0][0] == '-') ? OPT_login : 0;
7760 builtin_argc = 0; 7756 builtin_argc = 0;
7761 while (1) { 7757 while (1) {
7762 opt = getopt(argc, argv, "+c:xins" 7758 opt = getopt(argc, argv, "+c:xinsl"
7763#if !BB_MMU 7759#if !BB_MMU
7764 "<:$:R:V:" 7760 "<:$:R:V:"
7765# if ENABLE_HUSH_FUNCTIONS 7761# if ENABLE_HUSH_FUNCTIONS
@@ -7820,6 +7816,9 @@ int hush_main(int argc, char **argv)
7820 /* "-s" means "read from stdin", but this is how we always 7816 /* "-s" means "read from stdin", but this is how we always
7821 * operate, so simply do nothing here. */ 7817 * operate, so simply do nothing here. */
7822 break; 7818 break;
7819 case 'l':
7820 flags |= OPT_login;
7821 break;
7823#if !BB_MMU 7822#if !BB_MMU
7824 case '<': /* "big heredoc" support */ 7823 case '<': /* "big heredoc" support */
7825 full_write1_str(optarg); 7824 full_write1_str(optarg);
@@ -7843,7 +7842,6 @@ int hush_main(int argc, char **argv)
7843 install_special_sighandlers(); 7842 install_special_sighandlers();
7844 G.traps = xzalloc(sizeof(G.traps[0]) * NSIG); 7843 G.traps = xzalloc(sizeof(G.traps[0]) * NSIG);
7845 for (sig = 1; sig < NSIG; sig++) { 7844 for (sig = 1; sig < NSIG; sig++) {
7846///vda: fixme: more efficient code
7847 if (empty_trap_mask & (1LL << sig)) { 7845 if (empty_trap_mask & (1LL << sig)) {
7848 G.traps[sig] = xzalloc(1); /* == xstrdup(""); */ 7846 G.traps[sig] = xzalloc(1); /* == xstrdup(""); */
7849 signal(sig, SIG_IGN); 7847 signal(sig, SIG_IGN);
@@ -7886,13 +7884,18 @@ int hush_main(int argc, char **argv)
7886 } 7884 }
7887 } /* option parsing loop */ 7885 } /* option parsing loop */
7888 7886
7887 /* Skip options. Try "hush -l": $1 should not be "-l"! */
7888 G.global_argc = argc - (optind - 1);
7889 G.global_argv = argv + (optind - 1);
7890 G.global_argv[0] = argv[0];
7891
7889 if (!G.root_pid) { 7892 if (!G.root_pid) {
7890 G.root_pid = getpid(); 7893 G.root_pid = getpid();
7891 G.root_ppid = getppid(); 7894 G.root_ppid = getppid();
7892 } 7895 }
7893 7896
7894 /* If we are login shell... */ 7897 /* If we are login shell... */
7895 if (argv[0] && argv[0][0] == '-') { 7898 if (flags & OPT_login) {
7896 FILE *input; 7899 FILE *input;
7897 debug_printf("sourcing /etc/profile\n"); 7900 debug_printf("sourcing /etc/profile\n");
7898 input = fopen_for_read("/etc/profile"); 7901 input = fopen_for_read("/etc/profile");
@@ -7911,17 +7914,17 @@ int hush_main(int argc, char **argv)
7911 */ 7914 */
7912 } 7915 }
7913 7916
7914 if (argv[optind]) { 7917 if (G.global_argv[1]) {
7915 FILE *input; 7918 FILE *input;
7916 /* 7919 /*
7917 * "bash <script>" (which is never interactive (unless -i?)) 7920 * "bash <script>" (which is never interactive (unless -i?))
7918 * sources $BASH_ENV here (without scanning $PATH). 7921 * sources $BASH_ENV here (without scanning $PATH).
7919 * If called as sh, does the same but with $ENV. 7922 * If called as sh, does the same but with $ENV.
7920 */ 7923 */
7921 debug_printf("running script '%s'\n", argv[optind]); 7924 G.global_argc--;
7922 G.global_argv = argv + optind; 7925 G.global_argv++;
7923 G.global_argc = argc - optind; 7926 debug_printf("running script '%s'\n", G.global_argv[0]);
7924 input = xfopen_for_read(argv[optind]); 7927 input = xfopen_for_read(G.global_argv[0]);
7925 close_on_exec_on(fileno(input)); 7928 close_on_exec_on(fileno(input));
7926 install_special_sighandlers(); 7929 install_special_sighandlers();
7927 parse_and_run_file(input); 7930 parse_and_run_file(input);
@@ -7984,7 +7987,7 @@ int hush_main(int argc, char **argv)
7984 } 7987 }
7985 } 7988 }
7986 7989
7987 /* Block some signals */ 7990 /* Install more signal handlers */
7988 install_special_sighandlers(); 7991 install_special_sighandlers();
7989 7992
7990 if (G_saved_tty_pgrp) { 7993 if (G_saved_tty_pgrp) {