diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-04-05 11:30:17 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-04-05 11:30:17 +0200 |
commit | 34f6b12330a13194057b49a74ca14362c2a332fa (patch) | |
tree | 51bc6d44d0ecb6878a2e1dad5c50364c5a37a5ee | |
parent | d358b0b65dae83d52e511a126757e2aa7b1881b2 (diff) | |
download | busybox-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.c | 123 |
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: |