diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-09-23 01:46:19 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-09-23 01:46:19 +0200 |
commit | 91836baf85ce6980a33c6ce38730928a4edc3c5a (patch) | |
tree | 4bb9751804629463dc9f8e3ff8aac7abd28815df | |
parent | af3fd14e4df87d8af833d5e7b97d285b4d137d60 (diff) | |
download | busybox-w32-91836baf85ce6980a33c6ce38730928a4edc3c5a.tar.gz busybox-w32-91836baf85ce6980a33c6ce38730928a4edc3c5a.tar.bz2 busybox-w32-91836baf85ce6980a33c6ce38730928a4edc3c5a.zip |
hush: fix `trap`
function old new delta
expand_variables 2217 2280 +63
static.argv - 8 +8
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-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) | |||
5180 | xmove_fd(channel[1], 1); | 5180 | xmove_fd(channel[1], 1); |
5181 | /* Prevent it from trying to handle ctrl-z etc */ | 5181 | /* Prevent it from trying to handle ctrl-z etc */ |
5182 | IF_HUSH_JOB(G.run_list_level = 1;) | 5182 | IF_HUSH_JOB(G.run_list_level = 1;) |
5183 | /* Awful hack for `trap` or $(trap). | ||
5184 | * | ||
5185 | * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html | ||
5186 | * contains an example where "trap" is executed in a subshell: | ||
5187 | * | ||
5188 | * save_traps=$(trap) | ||
5189 | * ... | ||
5190 | * eval "$save_traps" | ||
5191 | * | ||
5192 | * Standard does not say that "trap" in subshell shall print | ||
5193 | * parent shell's traps. It only says that its output | ||
5194 | * must have suitable form, but then, in the above example | ||
5195 | * (which is not supposed to be normative), it implies that. | ||
5196 | * | ||
5197 | * bash (and probably other shell) does implement it | ||
5198 | * (traps are reset to defaults, but "trap" still shows them), | ||
5199 | * but as a result, "trap" logic is hopelessly messed up: | ||
5200 | * | ||
5201 | * # trap | ||
5202 | * trap -- 'echo Ho' SIGWINCH <--- we have a handler | ||
5203 | * # (trap) <--- trap is in subshell - no output (correct, traps are reset) | ||
5204 | * # true | trap <--- trap is in subshell - no output (ditto) | ||
5205 | * # echo `true | trap` <--- in subshell - output (but traps are reset!) | ||
5206 | * trap -- 'echo Ho' SIGWINCH | ||
5207 | * # echo `(trap)` <--- in subshell in subshell - output | ||
5208 | * trap -- 'echo Ho' SIGWINCH | ||
5209 | * # echo `true | (trap)` <--- in subshell in subshell in subshell - output! | ||
5210 | * trap -- 'echo Ho' SIGWINCH | ||
5211 | * | ||
5212 | * The rules when to forget and when to not forget traps | ||
5213 | * get really complex and nonsensical. | ||
5214 | * | ||
5215 | * Our solution: ONLY bare $(trap) or `trap` is special. | ||
5216 | */ | ||
5217 | s = skip_whitespace(s); | ||
5218 | if (strncmp(s, "trap", 4) == 0 && (*skip_whitespace(s + 4) == '\0')) | ||
5219 | { | ||
5220 | static const char *const argv[] = { NULL, NULL }; | ||
5221 | builtin_trap((char**)argv); | ||
5222 | exit(0); /* not _exit() - we need to fflush */ | ||
5223 | } | ||
5183 | #if BB_MMU | 5224 | #if BB_MMU |
5184 | reset_traps_to_defaults(); | 5225 | reset_traps_to_defaults(); |
5185 | parse_and_run_string(s); | 5226 | parse_and_run_string(s); |
@@ -7057,7 +7098,8 @@ static int FAST_FUNC builtin_trap(char **argv) | |||
7057 | if (G.traps[i]) { | 7098 | if (G.traps[i]) { |
7058 | printf("trap -- "); | 7099 | printf("trap -- "); |
7059 | print_escaped(G.traps[i]); | 7100 | print_escaped(G.traps[i]); |
7060 | printf(" %s\n", get_signame(i)); | 7101 | /* bash compat: it says SIGxxx, not just xxx */ |
7102 | printf(" SIG%s\n", get_signame(i)); | ||
7061 | } | 7103 | } |
7062 | } | 7104 | } |
7063 | /*fflush(stdout); - done after each builtin anyway */ | 7105 | /*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 @@ | |||
1 | trap -- 'echo WINCH!' SIGWINCH | ||
2 | trap -- 'echo WINCH!' SIGWINCH | ||
3 | 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 @@ | |||
1 | trap 'echo WINCH!' SIGWINCH | ||
2 | v=` trap ` | ||
3 | echo $v | ||
4 | v=`trap` | ||
5 | echo $v | ||
6 | echo Done | ||