diff options
| author | Simon Glass <sjg@chromium.org> | 2012-03-30 21:30:55 +0000 | 
|---|---|---|
| committer | Wolfgang Denk <wd@denx.de> | 2012-08-09 22:06:03 +0200 | 
| commit | d51004a832a9784f4c6af5482d4dace6bfd938c4 (patch) | |
| tree | 0817bdb51d21cd55b64e8eecdc5de7fd06e1a058 | |
| parent | 213adf6dffe44d909db0efc5ecbdc047bb029438 (diff) | |
| download | olio-uboot-2014.01-d51004a832a9784f4c6af5482d4dace6bfd938c4.tar.xz olio-uboot-2014.01-d51004a832a9784f4c6af5482d4dace6bfd938c4.zip | |
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 <michael@walle.cc>
Signed-off-by: Simon Glass <sjg@chromium.org>
| -rw-r--r-- | common/cmd_pxe.c | 20 | ||||
| -rw-r--r-- | common/cmd_source.c | 49 | ||||
| -rw-r--r-- | common/main.c | 85 | ||||
| -rw-r--r-- | include/common.h | 13 | 
4 files changed, 102 insertions, 65 deletions
| diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c index 77a7dd17a..6b31deab5 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 32fff5cec..c4cde982a 100644 --- a/common/cmd_source.c +++ b/common/cmd_source.c @@ -39,9 +39,6 @@  #if defined(CONFIG_8xx)  #include <mpc8xx.h>  #endif -#ifdef CONFIG_SYS_HUSH_PARSER -#include <hush.h> -#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 a93335798..d96ba0a89 100644 --- a/common/main.c +++ b/common/main.c @@ -30,6 +30,7 @@  #include <common.h>  #include <watchdog.h>  #include <command.h> +#include <malloc.h>  #include <version.h>  #ifdef CONFIG_MODEM_SUPPORT  #include <malloc.h>		/* 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 39859d323..55025c0af 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); |