From: Simon Glass Date: Fri, 30 Mar 2012 21:30:55 +0000 (+0000) Subject: Add run_command_list() to run a list of commands X-Git-Url: http://git.dujemihanovic.xyz/?a=commitdiff_plain;h=d51004a832a9784f4c6af5482d4dace6bfd938c4;p=u-boot.git Add run_command_list() to run a list of commands This new function runs a list of commands separated by semicolon or newline. We move this out of cmd_source so that it can be used by other code. The PXE code also uses the new function. Suggested-by: Michael Walle Signed-off-by: Simon Glass --- diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c index 77a7dd17ac..6b31deab5b 100644 --- a/common/cmd_pxe.c +++ b/common/cmd_pxe.c @@ -554,33 +554,19 @@ static void label_print(void *data) */ static int label_localboot(struct pxe_label *label) { - char *localcmd, *dupcmd; - int ret; + char *localcmd; localcmd = from_env("localcmd"); if (!localcmd) return -ENOENT; - /* - * dup the command to avoid any issues with the version of it existing - * in the environment changing during the execution of the command. - */ - dupcmd = strdup(localcmd); - - if (!dupcmd) - return -ENOMEM; - if (label->append) setenv("bootargs", label->append); - printf("running: %s\n", dupcmd); - - ret = run_command(dupcmd, 0); + debug("running: %s\n", localcmd); - free(dupcmd); - - return ret; + return run_command_list(localcmd, strlen(localcmd), 0); } /* diff --git a/common/cmd_source.c b/common/cmd_source.c index 32fff5cec8..c4cde982a5 100644 --- a/common/cmd_source.c +++ b/common/cmd_source.c @@ -39,9 +39,6 @@ #if defined(CONFIG_8xx) #include #endif -#ifdef CONFIG_SYS_HUSH_PARSER -#include -#endif int source (ulong addr, const char *fit_uname) @@ -49,8 +46,6 @@ source (ulong addr, const char *fit_uname) ulong len; image_header_t *hdr; ulong *data; - char *cmd; - int rcode = 0; int verify; #if defined(CONFIG_FIT) const void* fit_hdr; @@ -151,49 +146,7 @@ source (ulong addr, const char *fit_uname) } debug ("** Script length: %ld\n", len); - - if ((cmd = malloc (len + 1)) == NULL) { - return 1; - } - - /* make sure cmd is null terminated */ - memmove (cmd, (char *)data, len); - *(cmd + len) = 0; - -#ifdef CONFIG_SYS_HUSH_PARSER /*?? */ - rcode = parse_string_outer (cmd, FLAG_PARSE_SEMICOLON); -#else - { - char *line = cmd; - char *next = cmd; - - /* - * break into individual lines, - * and execute each line; - * terminate on error. - */ - while (*next) { - if (*next == '\n') { - *next = '\0'; - /* run only non-empty commands */ - if (*line) { - debug ("** exec: \"%s\"\n", - line); - if (run_command(line, 0) < 0) { - rcode = 1; - break; - } - } - line = next + 1; - } - ++next; - } - if (rcode == 0 && *line) - rcode = (run_command(line, 0) >= 0); - } -#endif - free (cmd); - return rcode; + return run_command_list((char *)data, len, 0); } /**************************************************/ diff --git a/common/main.c b/common/main.c index a93335798b..d96ba0a891 100644 --- a/common/main.c +++ b/common/main.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #ifdef CONFIG_MODEM_SUPPORT #include /* for free() prototype */ @@ -1373,6 +1374,90 @@ int run_command(const char *cmd, int flag) #endif } +#ifndef CONFIG_SYS_HUSH_PARSER +/** + * Execute a list of command separated by ; or \n using the built-in parser. + * + * This function cannot take a const char * for the command, since if it + * finds newlines in the string, it replaces them with \0. + * + * @param cmd String containing list of commands + * @param flag Execution flags (CMD_FLAG_...) + * @return 0 on success, or != 0 on error. + */ +static int builtin_run_command_list(char *cmd, int flag) +{ + char *line, *next; + int rcode = 0; + + /* + * Break into individual lines, and execute each line; terminate on + * error. + */ + line = next = cmd; + while (*next) { + if (*next == '\n') { + *next = '\0'; + /* run only non-empty commands */ + if (*line) { + debug("** exec: \"%s\"\n", line); + if (builtin_run_command(line, 0) < 0) { + rcode = 1; + break; + } + } + line = next + 1; + } + ++next; + } + if (rcode == 0 && *line) + rcode = (builtin_run_command(line, 0) >= 0); + + return rcode; +} +#endif + +int run_command_list(const char *cmd, int len, int flag) +{ + int need_buff = 1; + char *buff = (char *)cmd; /* cast away const */ + int rcode = 0; + + if (len == -1) { + len = strlen(cmd); +#ifdef CONFIG_SYS_HUSH_PARSER + /* hush will never change our string */ + need_buff = 0; +#else + /* the built-in parser will change our string if it sees \n */ + need_buff = strchr(cmd, '\n') != NULL; +#endif + } + if (need_buff) { + buff = malloc(len + 1); + if (!buff) + return 1; + memcpy(buff, cmd, len); + buff[len] = '\0'; + } +#ifdef CONFIG_SYS_HUSH_PARSER + rcode = parse_string_outer(buff, FLAG_PARSE_SEMICOLON); +#else + /* + * This function will overwrite any \n it sees with a \0, which + * is why it can't work with a const char *. Here we are making + * using of internal knowledge of this function, to avoid always + * doing a malloc() which is actually required only in a case that + * is pretty rare. + */ + rcode = builtin_run_command_list(buff, flag); + if (need_buff) + free(buff); +#endif + + return rcode; +} + /****************************************************************************/ #if defined(CONFIG_CMD_RUN) diff --git a/include/common.h b/include/common.h index 39859d323f..55025c0afd 100644 --- a/include/common.h +++ b/include/common.h @@ -286,6 +286,19 @@ int print_buffer (ulong addr, void* data, uint width, uint count, uint linelen); /* common/main.c */ void main_loop (void); int run_command(const char *cmd, int flag); + +/** + * Run a list of commands separated by ; or even \0 + * + * Note that if 'len' is not -1, then the command does not need to be nul + * terminated, Memory will be allocated for the command in that case. + * + * @param cmd List of commands to run, each separated bu semicolon + * @param len Length of commands excluding terminator if known (-1 if not) + * @param flag Execution flags (CMD_FLAG_...) + * @return 0 on success, or != 0 on error. + */ +int run_command_list(const char *cmd, int len, int flag); int readline (const char *const prompt); int readline_into_buffer(const char *const prompt, char *buffer, int timeout);