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 /shell | |
| 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>
Diffstat (limited to 'shell')
| -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 | ||
