aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-04-05 11:30:17 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2018-04-05 11:30:17 +0200
commit34f6b12330a13194057b49a74ca14362c2a332fa (patch)
tree51bc6d44d0ecb6878a2e1dad5c50364c5a37a5ee
parentd358b0b65dae83d52e511a126757e2aa7b1881b2 (diff)
downloadbusybox-w32-34f6b12330a13194057b49a74ca14362c2a332fa.tar.gz
busybox-w32-34f6b12330a13194057b49a74ca14362c2a332fa.tar.bz2
busybox-w32-34f6b12330a13194057b49a74ca14362c2a332fa.zip
hush: make run_pipe code simpler to understand, no logic changes
function old new delta run_pipe 1641 1651 +10 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/hush.c123
1 files changed, 57 insertions, 66 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 00d86b4e4..3ad6a9724 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -7599,9 +7599,8 @@ static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save,
7599{ 7599{
7600 const struct built_in_command *x; 7600 const struct built_in_command *x;
7601 char **new_env; 7601 char **new_env;
7602#if ENABLE_HUSH_COMMAND 7602 IF_HUSH_COMMAND(char opt_vV = 0;)
7603 char opt_vV = 0; 7603 IF_HUSH_FUNCTIONS(const struct function *funcp;)
7604#endif
7605 7604
7606 new_env = expand_assignments(argv, assignment_cnt); 7605 new_env = expand_assignments(argv, assignment_cnt);
7607 dump_cmd_in_x_mode(new_env); 7606 dump_cmd_in_x_mode(new_env);
@@ -7640,12 +7639,9 @@ static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save,
7640 7639
7641#if ENABLE_HUSH_FUNCTIONS 7640#if ENABLE_HUSH_FUNCTIONS
7642 /* Check if the command matches any functions (this goes before bltins) */ 7641 /* Check if the command matches any functions (this goes before bltins) */
7643 { 7642 funcp = find_function(argv[0]);
7644 const struct function *funcp = find_function(argv[0]); 7643 if (funcp)
7645 if (funcp) { 7644 exec_function(&nommu_save->argv_from_re_execing, funcp, argv);
7646 exec_function(&nommu_save->argv_from_re_execing, funcp, argv);
7647 }
7648 }
7649#endif 7645#endif
7650 7646
7651#if ENABLE_HUSH_COMMAND 7647#if ENABLE_HUSH_COMMAND
@@ -8366,22 +8362,18 @@ static NOINLINE int run_pipe(struct pipe *pi)
8366 if (!funcp) 8362 if (!funcp)
8367 x = find_builtin(argv_expanded[0]); 8363 x = find_builtin(argv_expanded[0]);
8368 if (x || funcp) { 8364 if (x || funcp) {
8369 if (!funcp) { 8365 if (x && x->b_function == builtin_exec && argv_expanded[1] == NULL) {
8370 if (x->b_function == builtin_exec && argv_expanded[1] == NULL) { 8366 debug_printf("exec with redirects only\n");
8371 debug_printf("exec with redirects only\n"); 8367 rcode = setup_redirects(command, NULL);
8372 rcode = setup_redirects(command, NULL); 8368 /* rcode=1 can be if redir file can't be opened */
8373 /* rcode=1 can be if redir file can't be opened */ 8369 goto clean_up_and_ret1;
8374 goto clean_up_and_ret1;
8375 }
8376 } 8370 }
8377 8371
8378 /* Without bumping var nesting level, this leaks 8372 /* Bump var nesting, or this will leak exported $a:
8379 * exported $a:
8380 * a=b true; env | grep ^a= 8373 * a=b true; env | grep ^a=
8381 */ 8374 */
8382 enter_var_nest_level(); 8375 enter_var_nest_level();
8383 rcode = redirect_and_varexp_helper(&old_vars, command, &squirrel, argv_expanded); 8376 rcode = redirect_and_varexp_helper(&old_vars, command, &squirrel, argv_expanded);
8384
8385 if (rcode == 0) { 8377 if (rcode == 0) {
8386 if (!funcp) { 8378 if (!funcp) {
8387 debug_printf_exec(": builtin '%s' '%s'...\n", 8379 debug_printf_exec(": builtin '%s' '%s'...\n",
@@ -8406,58 +8398,57 @@ static NOINLINE int run_pipe(struct pipe *pi)
8406 } 8398 }
8407#endif 8399#endif
8408 } 8400 }
8409 clean_up_and_ret: 8401 } else
8410 leave_var_nest_level(); 8402 if (ENABLE_FEATURE_SH_NOFORK && NUM_APPLETS > 1) {
8411 add_vars(old_vars); 8403 int n = find_applet_by_name(argv_expanded[0]);
8412 restore_redirects(squirrel); 8404 if (n < 0 || !APPLET_IS_NOFORK(n))
8413 /* 8405 goto must_fork;
8414 * Try "usleep 99999999" + ^C + "echo $?" 8406
8415 * with FEATURE_SH_NOFORK=y. 8407 enter_var_nest_level();
8416 */ 8408 rcode = redirect_and_varexp_helper(&old_vars, command, &squirrel, argv_expanded);
8417 if (!funcp) { 8409 if (rcode == 0) {
8418 /* It was builtin or nofork. 8410 debug_printf_exec(": run_nofork_applet '%s' '%s'...\n",
8419 * if this would be a real fork/execed program, 8411 argv_expanded[0], argv_expanded[1]);
8420 * it should have died if a fatal sig was received. 8412 /*
8421 * But OTOH, there was no separate process, 8413 * Note: signals (^C) can't interrupt here.
8422 * the sig was sent to _shell_, not to non-existing 8414 * We remember them and they will be acted upon
8423 * child. 8415 * after applet returns.
8424 * Let's just handle ^C only, this one is obvious: 8416 * This makes applets which can run for a long time
8425 * we aren't ok with exitcode 0 when ^C was pressed 8417 * and/or wait for user input ineligible for NOFORK:
8426 * during builtin/nofork. 8418 * for example, "yes" or "rm" (rm -i waits for input).
8427 */ 8419 */
8428 if (sigismember(&G.pending_set, SIGINT)) 8420 rcode = run_nofork_applet(n, argv_expanded);
8429 rcode = 128 + SIGINT;
8430 } 8421 }
8431 clean_up_and_ret1:
8432 free(argv_expanded);
8433 IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
8434 debug_leave();
8435 debug_printf_exec("run_pipe return %d\n", rcode);
8436 return rcode;
8437 } 8422 }
8438 8423
8439 if (ENABLE_FEATURE_SH_NOFORK && NUM_APPLETS > 1) { 8424 leave_var_nest_level();
8440 int n = find_applet_by_name(argv_expanded[0]); 8425 add_vars(old_vars);
8441 if (n >= 0 && APPLET_IS_NOFORK(n)) { 8426 restore_redirects(squirrel);
8442 enter_var_nest_level(); 8427
8443 rcode = redirect_and_varexp_helper(&old_vars, command, &squirrel, argv_expanded); 8428 /*
8444 if (rcode == 0) { 8429 * Try "usleep 99999999" + ^C + "echo $?"
8445 debug_printf_exec(": run_nofork_applet '%s' '%s'...\n", 8430 * with FEATURE_SH_NOFORK=y.
8446 argv_expanded[0], argv_expanded[1]); 8431 */
8447 /* 8432 if (!funcp) {
8448 * Note: signals (^C) can't interrupt here. 8433 /* It was builtin or nofork.
8449 * We remember them and they will be acted upon 8434 * if this would be a real fork/execed program,
8450 * after applet returns. 8435 * it should have died if a fatal sig was received.
8451 * This makes applets which can run for a long time 8436 * But OTOH, there was no separate process,
8452 * and/or wait for user input ineligible for NOFORK: 8437 * the sig was sent to _shell_, not to non-existing
8453 * for example, "yes" or "rm" (rm -i waits for input). 8438 * child.
8454 */ 8439 * Let's just handle ^C only, this one is obvious:
8455 rcode = run_nofork_applet(n, argv_expanded); 8440 * we aren't ok with exitcode 0 when ^C was pressed
8456 } 8441 * during builtin/nofork.
8457 goto clean_up_and_ret; 8442 */
8458 } 8443 if (sigismember(&G.pending_set, SIGINT))
8444 rcode = 128 + SIGINT;
8459 } 8445 }
8460 /* It is neither builtin nor applet. We must fork. */ 8446 clean_up_and_ret1:
8447 free(argv_expanded);
8448 IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
8449 debug_leave();
8450 debug_printf_exec("run_pipe return %d\n", rcode);
8451 return rcode;
8461 } 8452 }
8462 8453
8463 must_fork: 8454 must_fork: