cli: hush: Adjust 'run' command to run each line of the env var
authorSimon Glass <sjg@chromium.org>
Tue, 7 Oct 2014 19:59:43 +0000 (13:59 -0600)
committerTom Rini <trini@ti.com>
Mon, 27 Oct 2014 15:03:33 +0000 (11:03 -0400)
The run command treats each argument an an environment variable. It gets the
value of each variable and executes it as a command. If an environment
variable contains a newline and the hush cli is used, it is supposed to
execute each line one after the other.

Normally a newline signals to hush to exit - this is used in normal command
line entry - after a command is entered we want to return to allow the user
to enter the next one. But environment variables obviously need to execute
to completion.

Add a special case for the execution of environment variables which
continues when a newline is seen, and add a few tests to check this
behaviour.

Note: it's not impossible that this may cause regressions in other areas.
I can't think of a case but with any change of behaviour with limited test
coverage there is always a risk. From what I can tell this behaviour has
been around since at least U-Boot 2011.03, although this pre-dates sandbox
and I have not tested it on real hardware.

Reported-by: Wolfgang Denk <wd@denx.de>
Signed-off-by: Simon Glass <sjg@chromium.org>
common/cli.c
common/cli_hush.c
include/cli_hush.h
include/command.h
test/command_ut.c

index 272b0288d76d56bbcaf5bb16310898d023b9127c..075ae9dc4aec5971b327651c7b8117211adb04e1 100644 (file)
@@ -36,8 +36,11 @@ int run_command(const char *cmd, int flag)
 
        return 0;
 #else
-       return parse_string_outer(cmd,
-                       FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
+       int hush_flags = FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP;
+
+       if (flag & CMD_FLAG_ENV)
+               hush_flags |= FLAG_CONT_ON_NEWLINE;
+       return parse_string_outer(cmd, hush_flags);
 #endif
 }
 
@@ -125,7 +128,7 @@ int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                        return 1;
                }
 
-               if (run_command(arg, flag) != 0)
+               if (run_command(arg, flag | CMD_FLAG_ENV) != 0)
                        return 1;
        }
        return 0;
index 38da5a09fa30d76c245088f44811c53bcb0c99f6..2b654b754f5d5423f639014cc8f260fef1ee1871 100644 (file)
@@ -3170,7 +3170,8 @@ static int parse_stream_outer(struct in_str *inp, int flag)
                update_ifs_map();
                if (!(flag & FLAG_PARSE_SEMICOLON) || (flag & FLAG_REPARSING)) mapset((uchar *)";$&|", 0);
                inp->promptmode=1;
-               rcode = parse_stream(&temp, &ctx, inp, '\n');
+               rcode = parse_stream(&temp, &ctx, inp,
+                                    flag & FLAG_CONT_ON_NEWLINE ? -1 : '\n');
 #ifdef __U_BOOT__
                if (rcode == 1) flag_repeat = 0;
 #endif
index 4951eef5724305519038ca739a77c60e087a5fa5..57c870dfe99a157119b3ab43c393bea6271eafb0 100644 (file)
@@ -11,6 +11,7 @@
 #define FLAG_EXIT_FROM_LOOP 1
 #define FLAG_PARSE_SEMICOLON (1 << 1)    /* symbol ';' is special for parser */
 #define FLAG_REPARSING       (1 << 2)    /* >=2nd pass */
+#define FLAG_CONT_ON_NEWLINE (1 << 3)    /* continue when we see \n */
 
 extern int u_boot_hush_start(void);
 extern int parse_string_outer(const char *, int);
index 6f06db1cc302ee219bd5c3ad75dd04723ec8895e..bd3fc049ecaa7b3e3c30c0fafc4fb35dd1790f02 100644 (file)
@@ -147,6 +147,7 @@ int cmd_process(int flag, int argc, char * const argv[],
  */
 #define CMD_FLAG_REPEAT                0x0001  /* repeat last command          */
 #define CMD_FLAG_BOOTD         0x0002  /* command is from bootd        */
+#define CMD_FLAG_ENV           0x0004  /* command is from the environment */
 
 #ifdef CONFIG_AUTO_COMPLETE
 # define _CMD_COMPLETE(x) x,
index ae6466d0ed8340fc64d833bdf29a618896e80d04..e136075541b76c4a21096f4619a6ea0f7a180f69 100644 (file)
@@ -66,7 +66,21 @@ static int do_ut_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
        assert(run_command_list("false", -1, 0) == 1);
        assert(run_command_list("echo", -1, 0) == 0);
 
+       run_command("setenv foo 'setenv monty 1; setenv python 2'", 0);
+       run_command("run foo", 0);
+       assert(getenv("monty") != NULL);
+       assert(!strcmp("1", getenv("monty")));
+       assert(getenv("python") != NULL);
+       assert(!strcmp("2", getenv("python")));
+
 #ifdef CONFIG_SYS_HUSH_PARSER
+       run_command("setenv foo 'setenv black 1\nsetenv adder 2'", 0);
+       run_command("run foo", 0);
+       assert(getenv("black") != NULL);
+       assert(!strcmp("1", getenv("black")));
+       assert(getenv("adder") != NULL);
+       assert(!strcmp("2", getenv("adder")));
+
        /* Test the 'test' command */
 
 #define HUSH_TEST(name, expr, expected_result) \