From 5fa0505f8a74848ce4d2a7a4ed905e1bb8af3fe6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 3 Apr 2018 11:21:13 +0200 Subject: [PATCH] hush: fix "set -e; false || x=1; echo OK" Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-misc/assignment5.right | 5 +++++ shell/ash_test/ash-misc/assignment5.tests | 9 +++++++++ shell/hush.c | 22 ++++++++++++++------- shell/hush_test/hush-misc/assignment5.right | 5 +++++ shell/hush_test/hush-misc/assignment5.tests | 9 +++++++++ 5 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 shell/ash_test/ash-misc/assignment5.right create mode 100755 shell/ash_test/ash-misc/assignment5.tests create mode 100644 shell/hush_test/hush-misc/assignment5.right create mode 100755 shell/hush_test/hush-misc/assignment5.tests diff --git a/shell/ash_test/ash-misc/assignment5.right b/shell/ash_test/ash-misc/assignment5.right new file mode 100644 index 000000000..a91554c09 --- /dev/null +++ b/shell/ash_test/ash-misc/assignment5.right @@ -0,0 +1,5 @@ +Zero1:0 +Zero2:0 +Zero3:0 +Zero4:0 x:1 y:1 +Three:3 x:1 y:1 diff --git a/shell/ash_test/ash-misc/assignment5.tests b/shell/ash_test/ash-misc/assignment5.tests new file mode 100755 index 000000000..0b8104285 --- /dev/null +++ b/shell/ash_test/ash-misc/assignment5.tests @@ -0,0 +1,9 @@ +true; a=1; echo Zero1:$? +false; a=1; echo Zero2:$? +false || a=1; echo Zero3:$? + +false || x=$? y=`echo $?`; echo Zero4:$? x:$x y:$y +false || x=$? y=`echo $?; exit 3`; echo Three:$? x:$x y:$y + +#ash sets z=1 instead of z=3. disabled for now +#false || x=$? y=`echo $?; exit 3` z=`echo $?`; echo x:$x y:$y z:$z diff --git a/shell/hush.c b/shell/hush.c index 184d720f5..b64993faa 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -894,8 +894,9 @@ struct globals { # define G_flag_return_in_progress 0 #endif smallint exiting; /* used to prevent EXIT trap recursion */ - /* These four support $?, $#, and $1 */ + /* These support $?, $#, and $1 */ smalluint last_exitcode; + smalluint expand_exitcode; smalluint last_bg_pid_exitcode; #if ENABLE_HUSH_SET /* are global_argv and global_argv[1..n] malloced? (note: not [0]) */ @@ -6209,6 +6210,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg) * and $IFS-split */ debug_printf_subst("SUBST '%s' first_ch %x\n", arg, first_ch); G.last_exitcode = process_command_subs(&subst_result, arg); + G.expand_exitcode = G.last_exitcode; debug_printf_subst("SUBST RES:%d '%s'\n", G.last_exitcode, subst_result.data); val = subst_result.data; goto store_val; @@ -8245,9 +8247,11 @@ static NOINLINE int run_pipe(struct pipe *pi) #endif if (argv[command->assignment_cnt] == NULL) { - /* Assignments, but no command */ - /* Ensure redirects take effect (that is, create files). - * Try "a=t >file" */ + /* Assignments, but no command. + * Ensure redirects take effect (that is, create files). + * Try "a=t >file" + */ + G.expand_exitcode = 0; #if 0 /* A few cases in testsuite fail with this code. FIXME */ rcode = redirect_and_varexp_helper(&new_env, /*old_vars:*/ NULL, command, &squirrel, /*argv_expanded:*/ NULL); /* Set shell variables */ @@ -8265,7 +8269,7 @@ static NOINLINE int run_pipe(struct pipe *pi) * if evaluating assignment value set $?, retain it. * Try "false; q=`exit 2`; echo $?" - should print 2: */ if (rcode == 0) - rcode = G.last_exitcode; + rcode = G.expand_exitcode; /* Exit, _skipping_ variable restoring code: */ goto clean_up_and_ret0; @@ -8292,9 +8296,13 @@ static NOINLINE int run_pipe(struct pipe *pi) bb_putchar_stderr('\n'); /* Redirect error sets $? to 1. Otherwise, * if evaluating assignment value set $?, retain it. - * Try "false; q=`exit 2`; echo $?" - should print 2: */ + * Else, clear $?: + * false; q=`exit 2`; echo $? - should print 2 + * false; x=1; echo $? - should print 0 + * Because of the 2nd case, we can't just use G.last_exitcode. + */ if (rcode == 0) - rcode = G.last_exitcode; + rcode = G.expand_exitcode; IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;) debug_leave(); debug_printf_exec("run_pipe: return %d\n", rcode); diff --git a/shell/hush_test/hush-misc/assignment5.right b/shell/hush_test/hush-misc/assignment5.right new file mode 100644 index 000000000..a91554c09 --- /dev/null +++ b/shell/hush_test/hush-misc/assignment5.right @@ -0,0 +1,5 @@ +Zero1:0 +Zero2:0 +Zero3:0 +Zero4:0 x:1 y:1 +Three:3 x:1 y:1 diff --git a/shell/hush_test/hush-misc/assignment5.tests b/shell/hush_test/hush-misc/assignment5.tests new file mode 100755 index 000000000..0b8104285 --- /dev/null +++ b/shell/hush_test/hush-misc/assignment5.tests @@ -0,0 +1,9 @@ +true; a=1; echo Zero1:$? +false; a=1; echo Zero2:$? +false || a=1; echo Zero3:$? + +false || x=$? y=`echo $?`; echo Zero4:$? x:$x y:$y +false || x=$? y=`echo $?; exit 3`; echo Three:$? x:$x y:$y + +#ash sets z=1 instead of z=3. disabled for now +#false || x=$? y=`echo $?; exit 3` z=`echo $?`; echo x:$x y:$y z:$z