[U-Boot] [PATCH] cli: hush: Adjust 'run' command to run each line of the env var

Simon Glass sjg at chromium.org
Tue Oct 7 21:59:43 CEST 2014


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 at denx.de>
Signed-off-by: Simon Glass <sjg at chromium.org>
---

 common/cli.c       |  9 ++++++---
 common/cli_hush.c  |  3 ++-
 include/cli_hush.h |  1 +
 include/command.h  |  1 +
 test/command_ut.c  | 14 ++++++++++++++
 5 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/common/cli.c b/common/cli.c
index 272b028..075ae9d 100644
--- a/common/cli.c
+++ b/common/cli.c
@@ -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;
diff --git a/common/cli_hush.c b/common/cli_hush.c
index 38da5a0..2b654b7 100644
--- a/common/cli_hush.c
+++ b/common/cli_hush.c
@@ -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
diff --git a/include/cli_hush.h b/include/cli_hush.h
index 4951eef..57c870d 100644
--- a/include/cli_hush.h
+++ b/include/cli_hush.h
@@ -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);
diff --git a/include/command.h b/include/command.h
index 6f06db1..bd3fc04 100644
--- a/include/command.h
+++ b/include/command.h
@@ -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,
diff --git a/test/command_ut.c b/test/command_ut.c
index ae6466d..e136075 100644
--- a/test/command_ut.c
+++ b/test/command_ut.c
@@ -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) \
-- 
2.1.0.rc2.206.gedb03e5



More information about the U-Boot mailing list