From: Francis Laniel <francis.laniel@amarulasolutions.com>
To: u-boot@lists.denx.de
Cc: Marek Behun <marek.behun@nic.cz>,
Michael Nazzareno Trimarchi <michael@amarulasolutions.com>,
Simon Glass <sjg@chromium.org>, Wolfgang Denk <wd@denx.de>,
Harald Seiler <hws@denx.de>, Tom Rini <trini@konsulko.com>,
Francis Laniel <francis.laniel@amarulasolutions.com>
Subject: [RFC PATCH v4 14/28] cli: hush_2021: Enable variables expansion for hush 2021
Date: Fri, 17 Jun 2022 00:31:44 +0200 [thread overview]
Message-ID: <20220616223158.9225-15-francis.laniel@amarulasolutions.com> (raw)
In-Reply-To: <20220616223158.9225-1-francis.laniel@amarulasolutions.com>
Enables variables expansion for hush 2021, both for local and environment
variables.
So the following commands:
foo=bar
echo $foo
setenv bar foo
echo $bar
leads to "bar" and "foo" being printed on console output.
Signed-off-by: Francis Laniel <francis.laniel@amarulasolutions.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
common/cli_hush_2021.c | 17 +++++++
common/cli_hush_upstream.c | 91 +++++++++++++++++++++++++++++++++++---
2 files changed, 103 insertions(+), 5 deletions(-)
diff --git a/common/cli_hush_2021.c b/common/cli_hush_2021.c
index d69e1ae2f3..0b1ef6dc64 100644
--- a/common/cli_hush_2021.c
+++ b/common/cli_hush_2021.c
@@ -219,6 +219,23 @@ static const char* endofname(const char *name)
return name;
}
+/**
+ * list_size() - returns the number of elements in char ** before NULL.
+ *
+ * Argument must contain NULL to signalize its end.
+ *
+ * @list The list to count the number of element.
+ * @return The number of element in list.
+ */
+static size_t list_size(char **list)
+{
+ size_t size;
+
+ for(size = 0; list[size] != NULL; size++);
+
+ return size;
+}
+
struct in_str;
static int u_boot_cli_readline(struct in_str *i);
diff --git a/common/cli_hush_upstream.c b/common/cli_hush_upstream.c
index 2c10b25993..89df34a867 100644
--- a/common/cli_hush_upstream.c
+++ b/common/cli_hush_upstream.c
@@ -3487,7 +3487,6 @@ static int o_get_last_ptr(o_string *o, int n)
return ((int)(uintptr_t)list[n-1]) + string_start;
}
-#ifndef __U_BOOT__
/*
* Globbing routines.
*
@@ -3742,8 +3741,10 @@ static int glob_needed(const char *s)
*/
static int perform_glob(o_string *o, int n)
{
+#ifndef __U_BOOT__
glob_t globdata;
int gr;
+#endif /* __U_BOOT__ */
char *pattern;
debug_printf_glob("start perform_glob: n:%d o->data:%p\n", n, o->data);
@@ -3752,13 +3753,16 @@ static int perform_glob(o_string *o, int n)
pattern = o->data + o_get_last_ptr(o, n);
debug_printf_glob("glob pattern '%s'\n", pattern);
if (!glob_needed(pattern)) {
+#ifndef __U_BOOT__
literal:
+#endif /* __U_BOOT__ */
/* unbackslash last string in o in place, fix length */
o->length = unbackslash(pattern) - o->data;
debug_printf_glob("glob pattern '%s' is literal\n", pattern);
return o_save_ptr_helper(o, n);
}
+#ifndef __U_BOOT__
memset(&globdata, 0, sizeof(globdata));
/* Can't use GLOB_NOCHECK: it does not unescape the string.
* If we glob "*.\*" and don't find anything, we need
@@ -3794,16 +3798,22 @@ static int perform_glob(o_string *o, int n)
if (DEBUG_GLOB)
debug_print_list("perform_glob returning", o, n);
return n;
+#else /* __U_BOOT__ */
+ /*
+ * NOTE We only use perform glob to call unbackslash to remove backslash
+ * from string once expanded.
+ * So, it seems OK to return this if no previous return was done.
+ */
+ return o_save_ptr_helper(o, n);
+#endif /* __U_BOOT__ */
}
-#endif /* !__U_BOOT__ */
#endif /* !HUSH_BRACE_EXPANSION */
/* If o->o_expflags & EXP_FLAG_GLOB, glob the string so far remembered.
* Otherwise, just finish current list[] and start new */
static int o_save_ptr(o_string *o, int n)
{
-#ifndef __U_BOOT__
if (o->o_expflags & EXP_FLAG_GLOB) {
/* If o->has_empty_slot, list[n] was already globbed
* (if it was requested back then when it was filled)
@@ -3811,7 +3821,6 @@ static int o_save_ptr(o_string *o, int n)
if (!o->has_empty_slot)
return perform_glob(o, n); /* o_save_ptr_helper is inside */
}
-#endif /* !__U_BOOT__ */
return o_save_ptr_helper(o, n);
}
@@ -5457,7 +5466,20 @@ static int parse_dollar(o_string *as_string,
nommu_addchr(as_string, ch);
if (ch == '}')
break;
+#ifndef __U_BOOT__
if (!isalnum(ch) && ch != '_') {
+#else /* __U_BOOT__ */
+ /*
+ * In several places in U-Boot, we use variable like
+ * foo# (e.g. serial#), particularly in env.
+ * So, we need to authorize # to appear inside
+ * variable name and then expand this variable.
+ * NOTE Having # in variable name is not permitted in
+ * upstream hush but expansion will be done (even though
+ * the result will be empty).
+ */
+ if (!isalnum(ch) && ch != '_' && ch != '#') {
+#endif /* __U_BOOT__ */
unsigned end_ch;
#ifndef __U_BOOT__
unsigned char last_ch;
@@ -7032,7 +7054,20 @@ static NOINLINE int expand_one_var(o_string *output, int n,
}
#endif /* !__U_BOOT__ */
default:
+#ifndef __U_BOOT__
val = get_local_var_value(var);
+#else /* __U_BOOT__ */
+ /*
+ * Environment variable set with setenv* have to be
+ * expanded.
+ * So, we first search if the variable exists in
+ * environment, if this is not the case, we default to
+ * local value.
+ */
+ val = env_get(var);
+ if (!val)
+ val = get_local_var_value(var);
+#endif /* __U_BOOT__ */
}
}
@@ -7377,7 +7412,11 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
case '*':
case '@': {
int i;
+#ifndef __U_BOOT__
if (!G.global_argv[1])
+#else /* __U_BOOT__ */
+ if (!G.global_argv || !G.global_argv[1])
+#endif /* __U_BOOT__ */
break;
i = 1;
cant_be_null |= first_ch; /* do it for "$@" _now_, when we know it's not empty */
@@ -9968,7 +10007,30 @@ static NOINLINE int run_pipe(struct pipe *pi)
#endif /* !__U_BOOT__ */
command = &pi->cmds[cmd_no];
cmd_no++;
- if (command->argv) {
+
+#ifdef __U_BOOT__
+ /* Replace argv and argc by expanded if it exists. */
+ if (argv_expanded) {
+ /*
+ * We need to save a pointer to argv, we will restore it
+ * later, so it will be freed when pipe is freed.
+ */
+ argv = command->argv;
+
+ /*
+ * After expansion, there can be more or less argument, so we need to
+ * update argc, for example:
+ * - More arguments:
+ * foo='bar quuz'
+ * echo $foo
+ * - Less arguments:
+ * echo $foo (if foo was never set)
+ */
+ command->argc = list_size(argv_expanded);
+ command->argv = argv_expanded;
+ }
+#endif /* __U_BOOT__ */
+ if (command->argv) {
debug_printf_exec(": pipe member '%s' '%s'...\n",
command->argv[0], command->argv[1]);
} else {
@@ -10083,6 +10145,25 @@ static NOINLINE int run_pipe(struct pipe *pi)
rcode = cmd_process(G.do_repeat ? CMD_FLAG_REPEAT : 0,
command->argc, command->argv,
&(G.flag_repeat), NULL);
+
+ if (argv_expanded) {
+ /*
+ * expand_strvec_to_strvec() allocates memory to expand
+ * argv, we need to free it.
+ */
+ free(argv_expanded);
+
+ /*
+ * We also restore command->argv to its original value
+ * so no memory leak happens.
+ */
+ command->argv = argv;
+
+ /*
+ * NOTE argc exists only in U-Boot, so argv freeing does
+ * not rely on it as this code exists in BusyBox.
+ */
+ }
#endif /* __U_BOOT__ */
}
--
2.25.1
next prev parent reply other threads:[~2022-06-16 22:37 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-06-16 22:31 [RFC PATCH v4 00/28] Modernize U-Boot shell Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 01/28] video: sandbox: Add dummy function for sandbox_sdl_remove_display() Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 02/28] test: Add framework to test hush behavior Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 03/28] test: hush: Test hush if/else Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 04/28] test/py: hush_if_test: Remove the test file Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 05/28] test: hush: Test hush variable expansion Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 06/28] test: hush: Test hush commands list Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 07/28] test: hush: Test hush loops Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 08/28] cli: Add Busybox upstream hush.c file Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 09/28] cli: Port Busybox 2021 hush to U-Boot Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 10/28] cli: Add menu for hush parser Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 11/28] global_data.h: add GD_FLG_HUSH_OLD_PARSER flag Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 12/28] cmd: Add new parser command Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 13/28] cli: Enables using hush 2021 parser as command line parser Francis Laniel
2022-06-16 22:31 ` Francis Laniel [this message]
2022-06-16 22:31 ` [RFC PATCH v4 15/28] cli: hush_2021: Add functions to be called from run_command() Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 16/28] cli: add hush 2021 as parser for run_command*() Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 17/28] test: hush: Fix instructions list tests for hush 2021 Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 18/28] test: hush: Fix variable expansion " Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 19/28] cli: hush_2021: Enable using \< and \> as string compare operators Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 20/28] cli: hush_2021: Enable if keyword Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 21/28] test: hush: Fix if tests for hush 2021 Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 22/28] cli: hush_2021: Enable loops Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 23/28] test: hush: Fix loop tests for hush 2021 Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 24/28] Modernize U-Boot shell Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 25/28] cli: hush_2021: Add upstream commits up to 6th February 2022 Francis Laniel
2022-06-20 19:11 ` Tom Rini
2022-08-12 20:56 ` Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 26/28] for test purpose only: Comment out dollar tests which prints error messages Francis Laniel
2022-06-17 14:02 ` Tom Rini
2022-08-12 21:12 ` Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 27/28] for test purpose only: Comment out failed function which fails only in CI Francis Laniel
2022-06-17 14:49 ` Tom Rini
2022-10-10 20:52 ` [PATCH] for debug purpose only: add print to debug odd behavior Francis Laniel
2022-06-16 22:31 ` [RFC PATCH v4 28/28] board: keymile: common: Use environment to store IVM_* variables Francis Laniel
2022-06-17 14:48 ` Tom Rini
2022-06-20 14:46 ` Aleksandar Gerasimovski
2022-06-20 15:27 ` Holger Brunck
2022-06-20 15:35 ` Tom Rini
2022-06-20 16:08 ` Holger Brunck
2022-06-20 17:33 ` Tom Rini
2022-08-12 21:01 ` Francis Laniel
2022-08-15 8:13 ` Holger Brunck
2022-06-17 14:50 ` [RFC PATCH v4 00/28] Modernize U-Boot shell Tom Rini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220616223158.9225-15-francis.laniel@amarulasolutions.com \
--to=francis.laniel@amarulasolutions.com \
--cc=hws@denx.de \
--cc=marek.behun@nic.cz \
--cc=michael@amarulasolutions.com \
--cc=sjg@chromium.org \
--cc=trini@konsulko.com \
--cc=u-boot@lists.denx.de \
--cc=wd@denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox