cmd: exit: Fix return value propagation out of environment scripts
authorMarek Vasut <marex@denx.de>
Tue, 20 Dec 2022 06:25:59 +0000 (07:25 +0100)
committerTom Rini <trini@konsulko.com>
Wed, 11 Jan 2023 20:02:24 +0000 (15:02 -0500)
Make sure the 'exit' command as well as 'exit $val' command exits
from environment scripts immediately and propagates return value
out of those scripts fully. That means the following behavior is
expected:

"
=> setenv foo 'echo bar ; exit 1' ; run foo ; echo $?
bar
1
=> setenv foo 'echo bar ; exit 0' ; run foo ; echo $?
bar
0
=> setenv foo 'echo bar ; exit -2' ; run foo ; echo $?
bar
0
"

As well as the followin behavior:

"
=> setenv foo 'echo bar ; exit 3 ; echo fail'; run foo; echo $?
bar
3
=> setenv foo 'echo bar ; exit 1 ; echo fail'; run foo; echo $?
bar
1
=> setenv foo 'echo bar ; exit 0 ; echo fail'; run foo; echo $?
bar
0
=> setenv foo 'echo bar ; exit -1 ; echo fail'; run foo; echo $?
bar
0
=> setenv foo 'echo bar ; exit -2 ; echo fail'; run foo; echo $?
bar
0
=> setenv foo 'echo bar ; exit ; echo fail'; run foo; echo $?
bar
0
"

Fixes: 8c4e3b79bd0 ("cmd: exit: Fix return value")
Reviewed-by: Hector Palacios <hector.palacios@digi.com>
Signed-off-by: Marek Vasut <marex@denx.de>
cmd/exit.c
common/cli.c
common/cli_hush.c
doc/usage/cmd/exit.rst

index 2c71326..7bf241e 100644 (file)
 static int do_exit(struct cmd_tbl *cmdtp, int flag, int argc,
                   char *const argv[])
 {
+       int r;
+
+       r = 0;
        if (argc > 1)
-               return dectoul(argv[1], NULL);
+               r = simple_strtoul(argv[1], NULL, 10);
 
-       return 0;
+       return -r - 2;
 }
 
 U_BOOT_CMD(
index a47d6a3..ba45dad 100644 (file)
@@ -146,7 +146,7 @@ int run_commandf(const char *fmt, ...)
 #if defined(CONFIG_CMD_RUN)
 int do_run(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
-       int i;
+       int i, ret;
 
        if (argc < 2)
                return CMD_RET_USAGE;
@@ -160,8 +160,9 @@ int do_run(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
                        return 1;
                }
 
-               if (run_command(arg, flag | CMD_FLAG_ENV) != 0)
-                       return 1;
+               ret = run_command(arg, flag | CMD_FLAG_ENV);
+               if (ret)
+                       return ret;
        }
        return 0;
 }
index a80b847..1ad7a50 100644 (file)
@@ -1901,7 +1901,7 @@ static int run_list_real(struct pipe *pi)
                        last_return_code = -rcode - 2;
                        return -2;      /* exit */
                }
-               last_return_code=(rcode == 0) ? 0 : 1;
+               last_return_code = rcode;
 #endif
 #ifndef __U_BOOT__
                pi->num_progs = save_num_progs; /* restore number of programs */
@@ -3211,7 +3211,15 @@ static int parse_stream_outer(struct in_str *inp, int flag)
                                        printf("exit not allowed from main input shell.\n");
                                        continue;
                                }
-                               break;
+                               /*
+                                * DANGER
+                                * Return code -2 is special in this context,
+                                * it indicates exit from inner pipe instead
+                                * of return code itself, the return code is
+                                * stored in 'last_return_code' variable!
+                                * DANGER
+                                */
+                               return -2;
                        }
                        if (code == -1)
                            flag_repeat = 0;
@@ -3248,9 +3256,9 @@ int parse_string_outer(const char *s, int flag)
 #endif /* __U_BOOT__ */
 {
        struct in_str input;
+       int rcode;
 #ifdef __U_BOOT__
        char *p = NULL;
-       int rcode;
        if (!s)
                return 1;
        if (!*s)
@@ -3262,11 +3270,12 @@ int parse_string_outer(const char *s, int flag)
                setup_string_in_str(&input, p);
                rcode = parse_stream_outer(&input, flag);
                free(p);
-               return rcode;
+               return rcode == -2 ? last_return_code : rcode;
        } else {
 #endif
        setup_string_in_str(&input, s);
-       return parse_stream_outer(&input, flag);
+       rcode = parse_stream_outer(&input, flag);
+       return rcode == -2 ? last_return_code : rcode;
 #ifdef __U_BOOT__
        }
 #endif
@@ -3286,7 +3295,7 @@ int parse_file_outer(void)
        setup_file_in_str(&input);
 #endif
        rcode = parse_stream_outer(&input, FLAG_PARSE_SEMICOLON);
-       return rcode;
+       return rcode == -2 ? last_return_code : rcode;
 }
 
 #ifdef __U_BOOT__
index 769223c..3edb128 100644 (file)
@@ -37,4 +37,6 @@ executed.
 Return value
 ------------
 
-$? is always set to 0 (true).
+$? is default set to 0 (true). In case zero or positive integer parameter
+is passed to the command, the return value is the parameter value. In case
+negative integer parameter is passed to the command, the return value is 0.