diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-05 20:33:27 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-05 20:33:27 +0000 |
commit | c4a7af55e9c3cec111e34ac443fcc229004e2840 (patch) | |
tree | 10dc67d8669a507afa7fcfb03d9f721ce9c9c3eb /shell | |
parent | f9375285719035dbf2f7003d582c22447ed579f0 (diff) | |
download | busybox-w32-c4a7af55e9c3cec111e34ac443fcc229004e2840.tar.gz busybox-w32-c4a7af55e9c3cec111e34ac443fcc229004e2840.tar.bz2 busybox-w32-c4a7af55e9c3cec111e34ac443fcc229004e2840.zip |
hush: fix trap clearing in subshells on MMU; simplify NOMMU a bit:
function old new delta
parse_stream_dquoted 335 324 -11
handle_dollar 849 800 -49
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-60) Total: -60 bytes
Diffstat (limited to 'shell')
-rw-r--r-- | shell/hush.c | 124 |
1 files changed, 92 insertions, 32 deletions
diff --git a/shell/hush.c b/shell/hush.c index a3f80d512..f8f7482b1 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -1603,10 +1603,10 @@ static int process_command_subs(o_string *dest, const char *s); | |||
1603 | #endif | 1603 | #endif |
1604 | static char *expand_string_to_string(const char *str); | 1604 | static char *expand_string_to_string(const char *str); |
1605 | #if BB_MMU | 1605 | #if BB_MMU |
1606 | #define parse_stream_dquoted(ctx, dest, input, dquote_end) \ | 1606 | #define parse_stream_dquoted(as_string, dest, input, dquote_end) \ |
1607 | parse_stream_dquoted(dest, input, dquote_end) | 1607 | parse_stream_dquoted(dest, input, dquote_end) |
1608 | #endif | 1608 | #endif |
1609 | static int parse_stream_dquoted(struct parse_context *ctx, | 1609 | static int parse_stream_dquoted(o_string *as_string, |
1610 | o_string *dest, | 1610 | o_string *dest, |
1611 | struct in_str *input, | 1611 | struct in_str *input, |
1612 | int dquote_end); | 1612 | int dquote_end); |
@@ -2275,7 +2275,38 @@ static void pseudo_exec_argv(nommu_save_t *nommu_save, | |||
2275 | _exit(EXIT_FAILURE); | 2275 | _exit(EXIT_FAILURE); |
2276 | } | 2276 | } |
2277 | 2277 | ||
2278 | #if !BB_MMU | 2278 | #if BB_MMU |
2279 | static void reset_traps_to_defaults(void) | ||
2280 | { | ||
2281 | unsigned sig; | ||
2282 | int dirty; | ||
2283 | |||
2284 | if (!G.traps) | ||
2285 | return; | ||
2286 | dirty = 0; | ||
2287 | for (sig = 0; sig < NSIG; sig++) { | ||
2288 | if (!G.traps[sig]) | ||
2289 | continue; | ||
2290 | free(G.traps[sig]); | ||
2291 | G.traps[sig] = NULL; | ||
2292 | /* There is no signal for 0 (EXIT) */ | ||
2293 | if (sig == 0) | ||
2294 | continue; | ||
2295 | /* there was a trap handler, we are removing it | ||
2296 | * (if sig has non-DFL handling, | ||
2297 | * we don't need to do anything) */ | ||
2298 | if (sig < 32 && (G.non_DFL_mask & (1 << sig))) | ||
2299 | continue; | ||
2300 | sigdelset(&G.blocked_set, sig); | ||
2301 | dirty = 1; | ||
2302 | } | ||
2303 | if (dirty) | ||
2304 | sigprocmask(SIG_SETMASK, &G.blocked_set, NULL); | ||
2305 | } | ||
2306 | #define clean_up_after_re_execute() ((void)0) | ||
2307 | |||
2308 | #else /* !BB_MMU */ | ||
2309 | |||
2279 | static void re_execute_shell(const char *s) NORETURN; | 2310 | static void re_execute_shell(const char *s) NORETURN; |
2280 | static void re_execute_shell(const char *s) | 2311 | static void re_execute_shell(const char *s) |
2281 | { | 2312 | { |
@@ -2310,13 +2341,32 @@ static void re_execute_shell(const char *s) | |||
2310 | *pp++ = cur->varstr; | 2341 | *pp++ = cur->varstr; |
2311 | } | 2342 | } |
2312 | } | 2343 | } |
2344 | //TODO: pass functions | ||
2345 | /* We can pass activated traps here. Say, -Tnn:trap_string | ||
2346 | * | ||
2347 | * However, POSIX says that subshells reset signals with traps | ||
2348 | * to SIG_DFL. | ||
2349 | * I tested bash-3.2 and it not only does that with true subshells | ||
2350 | * of the form ( list ), but with any forked children shells. | ||
2351 | * I set trap "echo W" WINCH; and then tried: | ||
2352 | * | ||
2353 | * { echo 1; sleep 20; echo 2; } & | ||
2354 | * while true; do echo 1; sleep 20; echo 2; break; done & | ||
2355 | * true | { echo 1; sleep 20; echo 2; } | cat | ||
2356 | * | ||
2357 | * In all these cases sending SIGWINCH to the child shell | ||
2358 | * did not run the trap. If I add trap "echo V" WINCH; | ||
2359 | * _inside_ group (just before echo 1), it works. | ||
2360 | * | ||
2361 | * I conclude it means we don't need to pass active traps here. | ||
2362 | * exec syscall below resets them to SIG_DFL for us. | ||
2363 | */ | ||
2313 | *pp++ = (char *) "-c"; | 2364 | *pp++ = (char *) "-c"; |
2314 | *pp++ = (char *) s; | 2365 | *pp++ = (char *) s; |
2315 | pp2 = G.global_argv; | 2366 | pp2 = G.global_argv; |
2316 | while (*pp2) | 2367 | while (*pp2) |
2317 | *pp++ = *pp2++; | 2368 | *pp++ = *pp2++; |
2318 | /* *pp = NULL; - is already there */ | 2369 | /* *pp = NULL; - is already there */ |
2319 | //TODO: pass traps and functions | ||
2320 | 2370 | ||
2321 | debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s); | 2371 | debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s); |
2322 | sigprocmask(SIG_SETMASK, &G.inherited_set, NULL); | 2372 | sigprocmask(SIG_SETMASK, &G.inherited_set, NULL); |
@@ -2343,8 +2393,6 @@ static void clean_up_after_re_execute(void) | |||
2343 | G.argv_from_re_execing = NULL; | 2393 | G.argv_from_re_execing = NULL; |
2344 | } | 2394 | } |
2345 | } | 2395 | } |
2346 | #else | ||
2347 | #define clean_up_after_re_execute() ((void)0) | ||
2348 | #endif | 2396 | #endif |
2349 | 2397 | ||
2350 | static int run_list(struct pipe *pi); | 2398 | static int run_list(struct pipe *pi); |
@@ -2373,6 +2421,7 @@ static void pseudo_exec(nommu_save_t *nommu_save, | |||
2373 | #if BB_MMU | 2421 | #if BB_MMU |
2374 | int rcode; | 2422 | int rcode; |
2375 | debug_printf_exec("pseudo_exec: run_list\n"); | 2423 | debug_printf_exec("pseudo_exec: run_list\n"); |
2424 | reset_traps_to_defaults(); | ||
2376 | rcode = run_list(command->group); | 2425 | rcode = run_list(command->group); |
2377 | /* OK to leak memory by not calling free_pipe_list, | 2426 | /* OK to leak memory by not calling free_pipe_list, |
2378 | * since this process is about to exit */ | 2427 | * since this process is about to exit */ |
@@ -3846,6 +3895,7 @@ static FILE *generate_stream_from_string(const char *s) | |||
3846 | /* Prevent it from trying to handle ctrl-z etc */ | 3895 | /* Prevent it from trying to handle ctrl-z etc */ |
3847 | USE_HUSH_JOB(G.run_list_level = 1;) | 3896 | USE_HUSH_JOB(G.run_list_level = 1;) |
3848 | #if BB_MMU | 3897 | #if BB_MMU |
3898 | reset_traps_to_defaults(); | ||
3849 | parse_and_run_string(s); | 3899 | parse_and_run_string(s); |
3850 | _exit(G.last_return_code); | 3900 | _exit(G.last_return_code); |
3851 | #else | 3901 | #else |
@@ -4097,10 +4147,10 @@ static void add_till_closing_paren(o_string *dest, struct in_str *input, bool db | |||
4097 | 4147 | ||
4098 | /* Return code: 0 for OK, 1 for syntax error */ | 4148 | /* Return code: 0 for OK, 1 for syntax error */ |
4099 | #if BB_MMU | 4149 | #if BB_MMU |
4100 | #define handle_dollar(ctx, dest, input) \ | 4150 | #define handle_dollar(as_string, dest, input) \ |
4101 | handle_dollar(dest, input) | 4151 | handle_dollar(dest, input) |
4102 | #endif | 4152 | #endif |
4103 | static int handle_dollar(struct parse_context *ctx, | 4153 | static int handle_dollar(o_string *as_string, |
4104 | o_string *dest, | 4154 | o_string *dest, |
4105 | struct in_str *input) | 4155 | struct in_str *input) |
4106 | { | 4156 | { |
@@ -4112,7 +4162,7 @@ static int handle_dollar(struct parse_context *ctx, | |||
4112 | if (isalpha(ch)) { | 4162 | if (isalpha(ch)) { |
4113 | ch = i_getch(input); | 4163 | ch = i_getch(input); |
4114 | #if !BB_MMU | 4164 | #if !BB_MMU |
4115 | if (ctx) o_addchr(&ctx->as_string, ch); | 4165 | if (as_string) o_addchr(as_string, ch); |
4116 | #endif | 4166 | #endif |
4117 | make_var: | 4167 | make_var: |
4118 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | 4168 | o_addchr(dest, SPECIAL_VAR_SYMBOL); |
@@ -4125,7 +4175,7 @@ static int handle_dollar(struct parse_context *ctx, | |||
4125 | break; | 4175 | break; |
4126 | ch = i_getch(input); | 4176 | ch = i_getch(input); |
4127 | #if !BB_MMU | 4177 | #if !BB_MMU |
4128 | if (ctx) o_addchr(&ctx->as_string, ch); | 4178 | if (as_string) o_addchr(as_string, ch); |
4129 | #endif | 4179 | #endif |
4130 | } | 4180 | } |
4131 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | 4181 | o_addchr(dest, SPECIAL_VAR_SYMBOL); |
@@ -4133,7 +4183,7 @@ static int handle_dollar(struct parse_context *ctx, | |||
4133 | make_one_char_var: | 4183 | make_one_char_var: |
4134 | ch = i_getch(input); | 4184 | ch = i_getch(input); |
4135 | #if !BB_MMU | 4185 | #if !BB_MMU |
4136 | if (ctx) o_addchr(&ctx->as_string, ch); | 4186 | if (as_string) o_addchr(as_string, ch); |
4137 | #endif | 4187 | #endif |
4138 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | 4188 | o_addchr(dest, SPECIAL_VAR_SYMBOL); |
4139 | debug_printf_parse(": '%c'\n", ch); | 4189 | debug_printf_parse(": '%c'\n", ch); |
@@ -4153,7 +4203,7 @@ static int handle_dollar(struct parse_context *ctx, | |||
4153 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | 4203 | o_addchr(dest, SPECIAL_VAR_SYMBOL); |
4154 | ch = i_getch(input); | 4204 | ch = i_getch(input); |
4155 | #if !BB_MMU | 4205 | #if !BB_MMU |
4156 | if (ctx) o_addchr(&ctx->as_string, ch); | 4206 | if (as_string) o_addchr(as_string, ch); |
4157 | #endif | 4207 | #endif |
4158 | /* XXX maybe someone will try to escape the '}' */ | 4208 | /* XXX maybe someone will try to escape the '}' */ |
4159 | expansion = 0; | 4209 | expansion = 0; |
@@ -4162,7 +4212,7 @@ static int handle_dollar(struct parse_context *ctx, | |||
4162 | while (1) { | 4212 | while (1) { |
4163 | ch = i_getch(input); | 4213 | ch = i_getch(input); |
4164 | #if !BB_MMU | 4214 | #if !BB_MMU |
4165 | if (ctx) o_addchr(&ctx->as_string, ch); | 4215 | if (as_string) o_addchr(as_string, ch); |
4166 | #endif | 4216 | #endif |
4167 | if (ch == '}') | 4217 | if (ch == '}') |
4168 | break; | 4218 | break; |
@@ -4235,13 +4285,13 @@ static int handle_dollar(struct parse_context *ctx, | |||
4235 | # endif | 4285 | # endif |
4236 | ch = i_getch(input); | 4286 | ch = i_getch(input); |
4237 | # if !BB_MMU | 4287 | # if !BB_MMU |
4238 | if (ctx) o_addchr(&ctx->as_string, ch); | 4288 | if (as_string) o_addchr(as_string, ch); |
4239 | # endif | 4289 | # endif |
4240 | # if ENABLE_SH_MATH_SUPPORT | 4290 | # if ENABLE_SH_MATH_SUPPORT |
4241 | if (i_peek(input) == '(') { | 4291 | if (i_peek(input) == '(') { |
4242 | ch = i_getch(input); | 4292 | ch = i_getch(input); |
4243 | # if !BB_MMU | 4293 | # if !BB_MMU |
4244 | if (ctx) o_addchr(&ctx->as_string, ch); | 4294 | if (as_string) o_addchr(as_string, ch); |
4245 | # endif | 4295 | # endif |
4246 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | 4296 | o_addchr(dest, SPECIAL_VAR_SYMBOL); |
4247 | o_addchr(dest, /*quote_mask |*/ '+'); | 4297 | o_addchr(dest, /*quote_mask |*/ '+'); |
@@ -4250,10 +4300,10 @@ static int handle_dollar(struct parse_context *ctx, | |||
4250 | # endif | 4300 | # endif |
4251 | add_till_closing_paren(dest, input, true); | 4301 | add_till_closing_paren(dest, input, true); |
4252 | # if !BB_MMU | 4302 | # if !BB_MMU |
4253 | if (ctx) { | 4303 | if (as_string) { |
4254 | o_addstr(&ctx->as_string, dest->data + pos); | 4304 | o_addstr(as_string, dest->data + pos); |
4255 | o_addchr(&ctx->as_string, ')'); | 4305 | o_addchr(as_string, ')'); |
4256 | o_addchr(&ctx->as_string, ')'); | 4306 | o_addchr(as_string, ')'); |
4257 | } | 4307 | } |
4258 | # endif | 4308 | # endif |
4259 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | 4309 | o_addchr(dest, SPECIAL_VAR_SYMBOL); |
@@ -4269,9 +4319,9 @@ static int handle_dollar(struct parse_context *ctx, | |||
4269 | # endif | 4319 | # endif |
4270 | add_till_closing_paren(dest, input, false); | 4320 | add_till_closing_paren(dest, input, false); |
4271 | # if !BB_MMU | 4321 | # if !BB_MMU |
4272 | if (ctx) { | 4322 | if (as_string) { |
4273 | o_addstr(&ctx->as_string, dest->data + pos); | 4323 | o_addstr(as_string, dest->data + pos); |
4274 | o_addchr(&ctx->as_string, '`'); | 4324 | o_addchr(as_string, '`'); |
4275 | } | 4325 | } |
4276 | # endif | 4326 | # endif |
4277 | //debug_printf_subst("SUBST RES2 '%s'\n", dest->data + pos); | 4327 | //debug_printf_subst("SUBST RES2 '%s'\n", dest->data + pos); |
@@ -4283,7 +4333,7 @@ static int handle_dollar(struct parse_context *ctx, | |||
4283 | case '_': | 4333 | case '_': |
4284 | ch = i_getch(input); | 4334 | ch = i_getch(input); |
4285 | #if !BB_MMU | 4335 | #if !BB_MMU |
4286 | if (ctx) o_addchr(&ctx->as_string, ch); | 4336 | if (as_string) o_addchr(as_string, ch); |
4287 | #endif | 4337 | #endif |
4288 | ch = i_peek(input); | 4338 | ch = i_peek(input); |
4289 | if (isalnum(ch)) { /* it's $_name or $_123 */ | 4339 | if (isalnum(ch)) { /* it's $_name or $_123 */ |
@@ -4302,10 +4352,10 @@ static int handle_dollar(struct parse_context *ctx, | |||
4302 | } | 4352 | } |
4303 | 4353 | ||
4304 | #if BB_MMU | 4354 | #if BB_MMU |
4305 | #define parse_stream_dquoted(ctx, dest, input, dquote_end) \ | 4355 | #define parse_stream_dquoted(as_string, dest, input, dquote_end) \ |
4306 | parse_stream_dquoted(dest, input, dquote_end) | 4356 | parse_stream_dquoted(dest, input, dquote_end) |
4307 | #endif | 4357 | #endif |
4308 | static int parse_stream_dquoted(struct parse_context *ctx, | 4358 | static int parse_stream_dquoted(o_string *as_string, |
4309 | o_string *dest, | 4359 | o_string *dest, |
4310 | struct in_str *input, | 4360 | struct in_str *input, |
4311 | int dquote_end) | 4361 | int dquote_end) |
@@ -4316,8 +4366,8 @@ static int parse_stream_dquoted(struct parse_context *ctx, | |||
4316 | again: | 4366 | again: |
4317 | ch = i_getch(input); | 4367 | ch = i_getch(input); |
4318 | #if !BB_MMU | 4368 | #if !BB_MMU |
4319 | if (ctx && ch != EOF) | 4369 | if (as_string && ch != EOF) |
4320 | o_addchr(&ctx->as_string, ch); | 4370 | o_addchr(as_string, ch); |
4321 | #endif | 4371 | #endif |
4322 | if (ch == dquote_end) { /* may be only '"' or EOF */ | 4372 | if (ch == dquote_end) { /* may be only '"' or EOF */ |
4323 | dest->nonnull = 1; | 4373 | dest->nonnull = 1; |
@@ -4360,7 +4410,7 @@ static int parse_stream_dquoted(struct parse_context *ctx, | |||
4360 | goto again; | 4410 | goto again; |
4361 | } | 4411 | } |
4362 | if (ch == '$') { | 4412 | if (ch == '$') { |
4363 | if (handle_dollar(ctx, dest, input) != 0) { | 4413 | if (handle_dollar(as_string, dest, input) != 0) { |
4364 | debug_printf_parse("parse_stream_dquoted return 1: " | 4414 | debug_printf_parse("parse_stream_dquoted return 1: " |
4365 | "handle_dollar returned non-0\n"); | 4415 | "handle_dollar returned non-0\n"); |
4366 | return 1; | 4416 | return 1; |
@@ -4432,7 +4482,7 @@ static struct pipe *parse_stream(char **pstring, | |||
4432 | redir_type redir_style; | 4482 | redir_type redir_style; |
4433 | 4483 | ||
4434 | if (is_in_dquote) { | 4484 | if (is_in_dquote) { |
4435 | if (parse_stream_dquoted(&ctx, &dest, input, '"')) { | 4485 | if (parse_stream_dquoted(&ctx.as_string, &dest, input, '"')) { |
4436 | goto parse_error; | 4486 | goto parse_error; |
4437 | } | 4487 | } |
4438 | /* We reached closing '"' */ | 4488 | /* We reached closing '"' */ |
@@ -4579,8 +4629,7 @@ static struct pipe *parse_stream(char **pstring, | |||
4579 | #endif | 4629 | #endif |
4580 | break; | 4630 | break; |
4581 | case '$': | 4631 | case '$': |
4582 | //NOMMU TODO! | 4632 | if (handle_dollar(&ctx.as_string, &dest, input) != 0) { |
4583 | if (handle_dollar(&ctx, &dest, input) != 0) { | ||
4584 | debug_printf_parse("parse_stream parse error: " | 4633 | debug_printf_parse("parse_stream parse error: " |
4585 | "handle_dollar returned non-0\n"); | 4634 | "handle_dollar returned non-0\n"); |
4586 | goto parse_error; | 4635 | goto parse_error; |
@@ -5023,6 +5072,15 @@ int hush_main(int argc, char **argv) | |||
5023 | G.PS2 = "> "; | 5072 | G.PS2 = "> "; |
5024 | #endif | 5073 | #endif |
5025 | 5074 | ||
5075 | /* Shell is non-interactive at first. We need to call | ||
5076 | * block_signals(0) if we are going to execute "sh script", | ||
5077 | * "sh -c cmds" or login shell's /etc/profile and friends. | ||
5078 | * If we later decide that we are interactive, we run block_signals(0) | ||
5079 | * (or re-run block_signals(1) if we ran block_signals(0) before) | ||
5080 | * in order to intercept (more) signals. | ||
5081 | */ | ||
5082 | |||
5083 | /* Parse options */ | ||
5026 | /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */ | 5084 | /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */ |
5027 | while (1) { | 5085 | while (1) { |
5028 | opt = getopt(argc, argv, "c:xins" | 5086 | opt = getopt(argc, argv, "c:xins" |
@@ -5136,7 +5194,9 @@ int hush_main(int argc, char **argv) | |||
5136 | goto final_return; | 5194 | goto final_return; |
5137 | } | 5195 | } |
5138 | 5196 | ||
5139 | /* Up to here, shell was non-interactive. Now it may become one. */ | 5197 | /* Up to here, shell was non-interactive. Now it may become one. |
5198 | * NB: don't forget to (re)run block_signals(0/1) as needed. | ||
5199 | */ | ||
5140 | 5200 | ||
5141 | /* A shell is interactive if the '-i' flag was given, or if all of | 5201 | /* A shell is interactive if the '-i' flag was given, or if all of |
5142 | * the following conditions are met: | 5202 | * the following conditions are met: |