aboutsummaryrefslogtreecommitdiff
path: root/shell/hush.c
diff options
context:
space:
mode:
Diffstat (limited to 'shell/hush.c')
-rw-r--r--shell/hush.c47
1 files changed, 44 insertions, 3 deletions
diff --git a/shell/hush.c b/shell/hush.c
index bced388bf..357a354e2 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -988,6 +988,10 @@ struct globals {
988# define G_fatal_sig_mask 0 988# define G_fatal_sig_mask 0
989#endif 989#endif
990#if ENABLE_HUSH_TRAP 990#if ENABLE_HUSH_TRAP
991 int pre_trap_exitcode;
992# if ENABLE_HUSH_FUNCTIONS
993 int return_exitcode;
994# endif
991 char **traps; /* char *traps[NSIG] */ 995 char **traps; /* char *traps[NSIG] */
992# define G_traps G.traps 996# define G_traps G.traps
993#else 997#else
@@ -2097,25 +2101,35 @@ static int check_and_run_traps(void)
2097 } while (sig < NSIG); 2101 } while (sig < NSIG);
2098 break; 2102 break;
2099 got_sig: 2103 got_sig:
2104#if ENABLE_HUSH_TRAP
2100 if (G_traps && G_traps[sig]) { 2105 if (G_traps && G_traps[sig]) {
2101 debug_printf_exec("%s: sig:%d handler:'%s'\n", __func__, sig, G.traps[sig]); 2106 debug_printf_exec("%s: sig:%d handler:'%s'\n", __func__, sig, G.traps[sig]);
2102 if (G_traps[sig][0]) { 2107 if (G_traps[sig][0]) {
2103 /* We have user-defined handler */ 2108 /* We have user-defined handler */
2104 smalluint save_rcode; 2109 smalluint save_rcode;
2110 int save_pre;
2105 char *argv[3]; 2111 char *argv[3];
2106 /* argv[0] is unused */ 2112 /* argv[0] is unused */
2107 argv[1] = xstrdup(G_traps[sig]); 2113 argv[1] = xstrdup(G_traps[sig]);
2108 /* why strdup? trap can modify itself: trap 'trap "echo oops" INT' INT */ 2114 /* why strdup? trap can modify itself: trap 'trap "echo oops" INT' INT */
2109 argv[2] = NULL; 2115 argv[2] = NULL;
2110 save_rcode = G.last_exitcode; 2116 save_pre = G.pre_trap_exitcode;
2117 G.pre_trap_exitcode = save_rcode = G.last_exitcode;
2111 builtin_eval(argv); 2118 builtin_eval(argv);
2112 free(argv[1]); 2119 free(argv[1]);
2113//FIXME: shouldn't it be set to 128 + sig instead? 2120 G.pre_trap_exitcode = save_pre;
2114 G.last_exitcode = save_rcode; 2121 G.last_exitcode = save_rcode;
2122# if ENABLE_HUSH_FUNCTIONS
2123 if (G.return_exitcode >= 0) {
2124 debug_printf_exec("trap exitcode:%d\n", G.return_exitcode);
2125 G.last_exitcode = G.return_exitcode;
2126 }
2127# endif
2115 last_sig = sig; 2128 last_sig = sig;
2116 } /* else: "" trap, ignoring signal */ 2129 } /* else: "" trap, ignoring signal */
2117 continue; 2130 continue;
2118 } 2131 }
2132#endif
2119 /* not a trap: special action */ 2133 /* not a trap: special action */
2120 switch (sig) { 2134 switch (sig) {
2121 case SIGINT: 2135 case SIGINT:
@@ -8127,6 +8141,10 @@ static int run_function(const struct function *funcp, char **argv)
8127 IF_HUSH_LOCAL(leave_var_nest_level();) 8141 IF_HUSH_LOCAL(leave_var_nest_level();)
8128 8142
8129 G_flag_return_in_progress = sv_flg; 8143 G_flag_return_in_progress = sv_flg;
8144# if ENABLE_HUSH_TRAP
8145 debug_printf_exec("G.return_exitcode=-1\n");
8146 G.return_exitcode = -1; /* invalidate stashed return value */
8147# endif
8130 8148
8131 restore_G_args(&sv, argv); 8149 restore_G_args(&sv, argv);
8132 8150
@@ -9628,6 +9646,9 @@ static int run_list(struct pipe *pi)
9628 debug_printf_exec(": builtin/func exitcode %d\n", rcode); 9646 debug_printf_exec(": builtin/func exitcode %d\n", rcode);
9629 G.last_exitcode = rcode; 9647 G.last_exitcode = rcode;
9630 check_and_run_traps(); 9648 check_and_run_traps();
9649#if ENABLE_HUSH_TRAP && ENABLE_HUSH_FUNCTIONS
9650 rcode = G.last_exitcode; /* "return" in trap can change it, read back */
9651#endif
9631#if ENABLE_HUSH_LOOPS 9652#if ENABLE_HUSH_LOOPS
9632 /* Was it "break" or "continue"? */ 9653 /* Was it "break" or "continue"? */
9633 if (G.flag_break_continue) { 9654 if (G.flag_break_continue) {
@@ -9684,6 +9705,9 @@ static int run_list(struct pipe *pi)
9684 check_traps: 9705 check_traps:
9685 G.last_exitcode = rcode; 9706 G.last_exitcode = rcode;
9686 check_and_run_traps(); 9707 check_and_run_traps();
9708#if ENABLE_HUSH_TRAP && ENABLE_HUSH_FUNCTIONS
9709 rcode = G.last_exitcode; /* "return" in trap can change it, read back */
9710#endif
9687 } 9711 }
9688 9712
9689 /* Handle "set -e" */ 9713 /* Handle "set -e" */
@@ -9907,6 +9931,12 @@ int hush_main(int argc, char **argv)
9907 INIT_G(); 9931 INIT_G();
9908 if (EXIT_SUCCESS != 0) /* if EXIT_SUCCESS == 0, it is already done */ 9932 if (EXIT_SUCCESS != 0) /* if EXIT_SUCCESS == 0, it is already done */
9909 G.last_exitcode = EXIT_SUCCESS; 9933 G.last_exitcode = EXIT_SUCCESS;
9934#if ENABLE_HUSH_TRAP
9935# if ENABLE_HUSH_FUNCTIONS
9936 G.return_exitcode = -1;
9937# endif
9938 G.pre_trap_exitcode = -1;
9939#endif
9910 9940
9911#if ENABLE_HUSH_FAST 9941#if ENABLE_HUSH_FAST
9912 G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */ 9942 G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */
@@ -10552,8 +10582,13 @@ static int FAST_FUNC builtin_exit(char **argv)
10552 10582
10553 /* note: EXIT trap is run by hush_exit */ 10583 /* note: EXIT trap is run by hush_exit */
10554 argv = skip_dash_dash(argv); 10584 argv = skip_dash_dash(argv);
10555 if (argv[0] == NULL) 10585 if (argv[0] == NULL) {
10586#if ENABLE_HUSH_TRAP
10587 if (G.pre_trap_exitcode >= 0) /* "exit" in trap uses $? from before the trap */
10588 hush_exit(G.pre_trap_exitcode);
10589#endif
10556 hush_exit(G.last_exitcode); 10590 hush_exit(G.last_exitcode);
10591 }
10557 /* mimic bash: exit 123abc == exit 255 + error msg */ 10592 /* mimic bash: exit 123abc == exit 255 + error msg */
10558 xfunc_error_retval = 255; 10593 xfunc_error_retval = 255;
10559 /* bash: exit -2 == exit 254, no error msg */ 10594 /* bash: exit -2 == exit 254, no error msg */
@@ -11745,6 +11780,12 @@ static int FAST_FUNC builtin_return(char **argv)
11745 * 255 <== we also do this 11780 * 255 <== we also do this
11746 */ 11781 */
11747 rc = parse_numeric_argv1(argv, G.last_exitcode, 0); 11782 rc = parse_numeric_argv1(argv, G.last_exitcode, 0);
11783# if ENABLE_HUSH_TRAP
11784 if (argv[1]) { /* "return ARG" inside a running trap sets $? */
11785 debug_printf_exec("G.return_exitcode=%d\n", rc);
11786 G.return_exitcode = rc;
11787 }
11788# endif
11748 return rc; 11789 return rc;
11749} 11790}
11750#endif 11791#endif