Am 1. März 2021 00:47:15 MEZ schrieb Sean Anderson <sean...@gmail.com>:
>The traditional way to grab the output from a shell script is to use
>command substitution. Unfortunately, we don't really have the concept
>of
>pipes in U-Boot (at least not without console recording). Even if we
>did,
>stdout is severely polluted by informational printfs.
>
>Instead of redirecting stdout, instead use a special global variable.
>This
>lets commands set a result without having to modify the function
>signature
>of every command, and everything that calls commands. This is a bit of
>a
>hack, but seemed like the least-invasive of all options.
>
>Currently, the value of cmd_result is printed if it is set. This makes
>sense for things like echo, where you can do something like
>
>       => echo a b c d e
>       a b c d e
>       => var=c
>       => echo a $(echo b $var d) e
>       a b c d e
>
>but it makes less sense for some other commands
>
>All callers of cmd_process must
>       1. Print cmd_result (unless it is being "redirected")
>       2. free() cmd_result
>       3. set cmd_result to NULL
>Calling cmd_process with a non-NULL value in cmd_result is a bug.

I don't understand what you are changing from the lines above.

Before extending the hush shell we should write a man-page in doc/usage/ 
describing what it actually does.

Building in new gimmicks without documentation does not make any sense to me.

Best regards

Heinrich


>
>Signed-off-by: Sean Anderson <sean...@gmail.com>
>---
>
> common/cli_hush.c                 | 39 ++++++++++++++++++++++++++++---
> common/cli_simple.c               |  8 ++++++-
> common/command.c                  |  3 +++
> include/asm-generic/global_data.h |  4 ++++
> 4 files changed, 50 insertions(+), 4 deletions(-)
>
>diff --git a/common/cli_hush.c b/common/cli_hush.c
>index 83329763c6..8fed7eb14e 100644
>--- a/common/cli_hush.c
>+++ b/common/cli_hush.c
>@@ -475,6 +475,8 @@ static char *make_string(char **inp, int *nonnull);
>static int handle_dollar(o_string *dest, struct p_context *ctx, struct
>in_str *input);
> #ifndef __U_BOOT__
>static int parse_string(o_string *dest, struct p_context *ctx, const
>char *src);
>+#else
>+static void update_ifs_map(void);
> #endif
>static int parse_stream(o_string *dest, struct p_context *ctx, struct
>in_str *input0, int end_trigger);
> /*   setup: */
>@@ -1673,6 +1675,10 @@ static int run_pipe_real(struct pipe *pi)
>                                       "'run' command\n", child->argv[i]);
>                       return -1;
>               }
>+              if (gd->cmd_result)
>+                      puts(gd->cmd_result);
>+              free(gd->cmd_result);
>+              gd->cmd_result = NULL;
>               /* Process the command */
>               return cmd_process(flag, child->argc - i, child->argv + i,
>                                  &flag_repeat, NULL);
>@@ -2683,6 +2689,7 @@ FILE *generate_stream_from_list(struct pipe
>*head)
> #endif
>       return pf;
> }
>+#endif /* __U_BOOT__ */
> 
> /* this version hacked for testing purposes */
> /* return code is exit status of the process that is run. */
>@@ -2691,7 +2698,11 @@ static int process_command_subs(o_string *dest,
>struct p_context *ctx, struct in
>       int retcode;
>       o_string result=NULL_O_STRING;
>       struct p_context inner;
>+#ifdef __U_BOOT__
>+      int list_retcode;
>+#else
>       FILE *p;
>+#endif
>       struct in_str pipe_str;
>       initialize_context(&inner);
> 
>@@ -2702,13 +2713,21 @@ static int process_command_subs(o_string *dest,
>struct p_context *ctx, struct in
>       done_pipe(&inner, PIPE_SEQ);
>       b_free(&result);
> 
>+#ifdef __U_BOOT__
>+      list_retcode = run_list_real(inner.list_head);
>+      setup_string_in_str(&pipe_str, gd->cmd_result ?: "");
>+      /* Restore the original map as best we can */
>+      update_ifs_map();
>+#else
>       p=generate_stream_from_list(inner.list_head);
>       if (p==NULL) return 1;
>       mark_open(fileno(p));
>       setup_file_in_str(&pipe_str, p);
>+#endif
> 
>       /* now send results of command back into original context */
>       retcode = parse_stream(dest, ctx, &pipe_str, '\0');
>+#ifndef __U_BOOT__
>       /* XXX In case of a syntax error, should we try to kill the child?
>        * That would be tough to do right, so just read until EOF. */
>       if (retcode == 1) {
>@@ -2723,12 +2742,18 @@ static int process_command_subs(o_string *dest,
>struct p_context *ctx, struct in
>        * to the KISS philosophy of this program. */
>       mark_closed(fileno(p));
>       retcode=pclose(p);
>+#else
>+      free(gd->cmd_result);
>+      gd->cmd_result = NULL;
>+      retcode = list_retcode;
>+#endif
>       free_pipe_list(inner.list_head,0);
>       debug_printf("pclosed, retcode=%d\n",retcode);
>       /* XXX this process fails to trim a single trailing newline */
>       return retcode;
> }
> 
>+#ifndef __U_BOOT__
> static int parse_group(o_string *dest, struct p_context *ctx,
>       struct in_str *input, int ch)
> {
>@@ -2896,11 +2921,11 @@ static int handle_dollar(o_string *dest, struct
>p_context *ctx, struct in_str *i
>                       }
>                       b_addchr(dest, SPECIAL_VAR_SYMBOL);
>                       break;
>-#ifndef __U_BOOT__
>               case '(':
>                       b_getch(input);
>                       process_command_subs(dest, ctx, input, ')');
>                       break;
>+#ifndef __U_BOOT__
>               case '*':
>                       sep[0]=ifs[0];
>                       for (i=1; i<global_argc; i++) {
>@@ -3165,7 +3190,7 @@ static void update_ifs_map(void)
>               mapset(subst, 3);       /* never flow through */
>       }
>       mapset((uchar *)"\\$'\"", 3);       /* never flow through */
>-      mapset((uchar *)";&|#", 1);         /* flow through if quoted */
>+      mapset((uchar *)";&|()#", 1);         /* flow through if quoted */
> #endif
>       mapset(ifs, 2);            /* also flow through if quoted */
> }
>@@ -3185,7 +3210,8 @@ static int parse_stream_outer(struct in_str *inp,
>int flag)
>               ctx.type = flag;
>               initialize_context(&ctx);
>               update_ifs_map();
>-              if (!(flag & FLAG_PARSE_SEMICOLON) || (flag & FLAG_REPARSING))
>mapset((uchar *)";$&|", 0);
>+              if (!(flag & FLAG_PARSE_SEMICOLON) || (flag & FLAG_REPARSING))
>+                      mapset((uchar *)";$&|()", 0);
>               inp->promptmode=1;
>               rcode = parse_stream(&temp, &ctx, inp,
>                                    flag & FLAG_CONT_ON_NEWLINE ? -1 : '\n');
>@@ -3205,6 +3231,13 @@ static int parse_stream_outer(struct in_str
>*inp, int flag)
>                       run_list(ctx.list_head);
> #else
>                       code = run_list(ctx.list_head);
>+
>+                      if (!(flag & FLAG_REPARSING) && gd->cmd_result) {
>+                              puts(gd->cmd_result);
>+                              free(gd->cmd_result);
>+                              gd->cmd_result = NULL;
>+                      }
>+
>                       if (code == -2) {       /* exit */
>                               b_free(&temp);
>                               code = 0;
>diff --git a/common/cli_simple.c b/common/cli_simple.c
>index e80ba488a5..5df30d964f 100644
>--- a/common/cli_simple.c
>+++ b/common/cli_simple.c
>@@ -15,14 +15,16 @@
> #include <console.h>
> #include <env.h>
> #include <log.h>
>+#include <malloc.h>
> #include <linux/ctype.h>
> 
>+DECLARE_GLOBAL_DATA_PTR;
>+
> #define DEBUG_PARSER  0       /* set to 1 to debug */
> 
> #define debug_parser(fmt, args...)            \
>       debug_cond(DEBUG_PARSER, fmt, ##args)
> 
>-
> int cli_simple_parse_line(char *line, char *argv[])
> {
>       int nargs = 0;
>@@ -257,6 +259,10 @@ int cli_simple_run_command(const char *cmd, int
>flag)
> 
>               if (cmd_process(flag, argc, argv, &repeatable, NULL))
>                       rc = -1;
>+              if (gd->cmd_result)
>+                      puts(gd->cmd_result);
>+              free(gd->cmd_result);
>+              gd->cmd_result = NULL;
> 
>               /* Did the user stop this? */
>               if (had_ctrlc())
>diff --git a/common/command.c b/common/command.c
>index 3fe6791eda..952a8f00eb 100644
>--- a/common/command.c
>+++ b/common/command.c
>@@ -588,6 +588,9 @@ enum command_ret_t cmd_process(int flag, int argc,
>char *const argv[],
>       enum command_ret_t rc = CMD_RET_SUCCESS;
>       struct cmd_tbl *cmdtp;
> 
>+      /* Clear previous result */
>+      assert(!gd->cmd_result);
>+
> #if defined(CONFIG_SYS_XTRACE)
>       char *xtrace;
> 
>diff --git a/include/asm-generic/global_data.h
>b/include/asm-generic/global_data.h
>index b6a9991fc9..85262d9566 100644
>--- a/include/asm-generic/global_data.h
>+++ b/include/asm-generic/global_data.h
>@@ -453,6 +453,10 @@ struct global_data {
>        */
>       char *smbios_version;
> #endif
>+      /**
>+       * @cmd_result: Result of the current command
>+       */
>+      char *cmd_result;
> };
> 
> /**

Reply via email to