diff options
-rw-r--r-- | shell/hush.c | 44 | ||||
-rw-r--r-- | shell/hush_test/hush-trap/savetrap.right | 3 | ||||
-rwxr-xr-x | shell/hush_test/hush-trap/savetrap.tests | 6 |
3 files changed, 52 insertions, 1 deletions
diff --git a/shell/hush.c b/shell/hush.c index 6b176c388..eaf911458 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -5180,6 +5180,47 @@ static FILE *generate_stream_from_string(const char *s) xmove_fd(channel[1], 1); /* Prevent it from trying to handle ctrl-z etc */ IF_HUSH_JOB(G.run_list_level = 1;) + /* Awful hack for `trap` or $(trap). + * + * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html + * contains an example where "trap" is executed in a subshell: + * + * save_traps=$(trap) + * ... + * eval "$save_traps" + * + * Standard does not say that "trap" in subshell shall print + * parent shell's traps. It only says that its output + * must have suitable form, but then, in the above example + * (which is not supposed to be normative), it implies that. + * + * bash (and probably other shell) does implement it + * (traps are reset to defaults, but "trap" still shows them), + * but as a result, "trap" logic is hopelessly messed up: + * + * # trap + * trap -- 'echo Ho' SIGWINCH <--- we have a handler + * # (trap) <--- trap is in subshell - no output (correct, traps are reset) + * # true | trap <--- trap is in subshell - no output (ditto) + * # echo `true | trap` <--- in subshell - output (but traps are reset!) + * trap -- 'echo Ho' SIGWINCH + * # echo `(trap)` <--- in subshell in subshell - output + * trap -- 'echo Ho' SIGWINCH + * # echo `true | (trap)` <--- in subshell in subshell in subshell - output! + * trap -- 'echo Ho' SIGWINCH + * + * The rules when to forget and when to not forget traps + * get really complex and nonsensical. + * + * Our solution: ONLY bare $(trap) or `trap` is special. + */ + s = skip_whitespace(s); + if (strncmp(s, "trap", 4) == 0 && (*skip_whitespace(s + 4) == '\0')) + { + static const char *const argv[] = { NULL, NULL }; + builtin_trap((char**)argv); + exit(0); /* not _exit() - we need to fflush */ + } #if BB_MMU reset_traps_to_defaults(); parse_and_run_string(s); @@ -7057,7 +7098,8 @@ static int FAST_FUNC builtin_trap(char **argv) if (G.traps[i]) { printf("trap -- "); print_escaped(G.traps[i]); - printf(" %s\n", get_signame(i)); + /* bash compat: it says SIGxxx, not just xxx */ + printf(" SIG%s\n", get_signame(i)); } } /*fflush(stdout); - done after each builtin anyway */ diff --git a/shell/hush_test/hush-trap/savetrap.right b/shell/hush_test/hush-trap/savetrap.right new file mode 100644 index 000000000..2d33427aa --- /dev/null +++ b/shell/hush_test/hush-trap/savetrap.right @@ -0,0 +1,3 @@ +trap -- 'echo WINCH!' SIGWINCH +trap -- 'echo WINCH!' SIGWINCH +Done diff --git a/shell/hush_test/hush-trap/savetrap.tests b/shell/hush_test/hush-trap/savetrap.tests new file mode 100755 index 000000000..6492e86a2 --- /dev/null +++ b/shell/hush_test/hush-trap/savetrap.tests @@ -0,0 +1,6 @@ +trap 'echo WINCH!' SIGWINCH +v=` trap ` +echo $v +v=`trap` +echo $v +echo Done |