aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-04-05 20:33:27 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-04-05 20:33:27 +0000
commitc4a7af55e9c3cec111e34ac443fcc229004e2840 (patch)
tree10dc67d8669a507afa7fcfb03d9f721ce9c9c3eb /shell
parentf9375285719035dbf2f7003d582c22447ed579f0 (diff)
downloadbusybox-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.c124
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
1604static char *expand_string_to_string(const char *str); 1604static 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
1609static int parse_stream_dquoted(struct parse_context *ctx, 1609static 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
2279static 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
2279static void re_execute_shell(const char *s) NORETURN; 2310static void re_execute_shell(const char *s) NORETURN;
2280static void re_execute_shell(const char *s) 2311static 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
2350static int run_list(struct pipe *pi); 2398static 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
4103static int handle_dollar(struct parse_context *ctx, 4153static 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
4308static int parse_stream_dquoted(struct parse_context *ctx, 4358static 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: