Commit d51004a832a9784f4c6af5482d4dace6bfd938c4
Committed by
Wolfgang Denk
1 parent
213adf6dff
Exists in
master
and in
55 other branches
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>
Showing 4 changed files with 102 additions and 65 deletions Side-by-side Diff
common/cmd_pxe.c
... | ... | @@ -554,33 +554,19 @@ |
554 | 554 | */ |
555 | 555 | static int label_localboot(struct pxe_label *label) |
556 | 556 | { |
557 | - char *localcmd, *dupcmd; | |
558 | - int ret; | |
557 | + char *localcmd; | |
559 | 558 | |
560 | 559 | localcmd = from_env("localcmd"); |
561 | 560 | |
562 | 561 | if (!localcmd) |
563 | 562 | return -ENOENT; |
564 | 563 | |
565 | - /* | |
566 | - * dup the command to avoid any issues with the version of it existing | |
567 | - * in the environment changing during the execution of the command. | |
568 | - */ | |
569 | - dupcmd = strdup(localcmd); | |
570 | - | |
571 | - if (!dupcmd) | |
572 | - return -ENOMEM; | |
573 | - | |
574 | 564 | if (label->append) |
575 | 565 | setenv("bootargs", label->append); |
576 | 566 | |
577 | - printf("running: %s\n", dupcmd); | |
567 | + debug("running: %s\n", localcmd); | |
578 | 568 | |
579 | - ret = run_command(dupcmd, 0); | |
580 | - | |
581 | - free(dupcmd); | |
582 | - | |
583 | - return ret; | |
569 | + return run_command_list(localcmd, strlen(localcmd), 0); | |
584 | 570 | } |
585 | 571 | |
586 | 572 | /* |
common/cmd_source.c
... | ... | @@ -39,9 +39,6 @@ |
39 | 39 | #if defined(CONFIG_8xx) |
40 | 40 | #include <mpc8xx.h> |
41 | 41 | #endif |
42 | -#ifdef CONFIG_SYS_HUSH_PARSER | |
43 | -#include <hush.h> | |
44 | -#endif | |
45 | 42 | |
46 | 43 | int |
47 | 44 | source (ulong addr, const char *fit_uname) |
... | ... | @@ -49,8 +46,6 @@ |
49 | 46 | ulong len; |
50 | 47 | image_header_t *hdr; |
51 | 48 | ulong *data; |
52 | - char *cmd; | |
53 | - int rcode = 0; | |
54 | 49 | int verify; |
55 | 50 | #if defined(CONFIG_FIT) |
56 | 51 | const void* fit_hdr; |
... | ... | @@ -151,49 +146,7 @@ |
151 | 146 | } |
152 | 147 | |
153 | 148 | debug ("** Script length: %ld\n", len); |
154 | - | |
155 | - if ((cmd = malloc (len + 1)) == NULL) { | |
156 | - return 1; | |
157 | - } | |
158 | - | |
159 | - /* make sure cmd is null terminated */ | |
160 | - memmove (cmd, (char *)data, len); | |
161 | - *(cmd + len) = 0; | |
162 | - | |
163 | -#ifdef CONFIG_SYS_HUSH_PARSER /*?? */ | |
164 | - rcode = parse_string_outer (cmd, FLAG_PARSE_SEMICOLON); | |
165 | -#else | |
166 | - { | |
167 | - char *line = cmd; | |
168 | - char *next = cmd; | |
169 | - | |
170 | - /* | |
171 | - * break into individual lines, | |
172 | - * and execute each line; | |
173 | - * terminate on error. | |
174 | - */ | |
175 | - while (*next) { | |
176 | - if (*next == '\n') { | |
177 | - *next = '\0'; | |
178 | - /* run only non-empty commands */ | |
179 | - if (*line) { | |
180 | - debug ("** exec: \"%s\"\n", | |
181 | - line); | |
182 | - if (run_command(line, 0) < 0) { | |
183 | - rcode = 1; | |
184 | - break; | |
185 | - } | |
186 | - } | |
187 | - line = next + 1; | |
188 | - } | |
189 | - ++next; | |
190 | - } | |
191 | - if (rcode == 0 && *line) | |
192 | - rcode = (run_command(line, 0) >= 0); | |
193 | - } | |
194 | -#endif | |
195 | - free (cmd); | |
196 | - return rcode; | |
149 | + return run_command_list((char *)data, len, 0); | |
197 | 150 | } |
198 | 151 | |
199 | 152 | /**************************************************/ |
common/main.c
... | ... | @@ -30,6 +30,7 @@ |
30 | 30 | #include <common.h> |
31 | 31 | #include <watchdog.h> |
32 | 32 | #include <command.h> |
33 | +#include <malloc.h> | |
33 | 34 | #include <version.h> |
34 | 35 | #ifdef CONFIG_MODEM_SUPPORT |
35 | 36 | #include <malloc.h> /* for free() prototype */ |
... | ... | @@ -1371,6 +1372,90 @@ |
1371 | 1372 | return parse_string_outer(cmd, |
1372 | 1373 | FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP); |
1373 | 1374 | #endif |
1375 | +} | |
1376 | + | |
1377 | +#ifndef CONFIG_SYS_HUSH_PARSER | |
1378 | +/** | |
1379 | + * Execute a list of command separated by ; or \n using the built-in parser. | |
1380 | + * | |
1381 | + * This function cannot take a const char * for the command, since if it | |
1382 | + * finds newlines in the string, it replaces them with \0. | |
1383 | + * | |
1384 | + * @param cmd String containing list of commands | |
1385 | + * @param flag Execution flags (CMD_FLAG_...) | |
1386 | + * @return 0 on success, or != 0 on error. | |
1387 | + */ | |
1388 | +static int builtin_run_command_list(char *cmd, int flag) | |
1389 | +{ | |
1390 | + char *line, *next; | |
1391 | + int rcode = 0; | |
1392 | + | |
1393 | + /* | |
1394 | + * Break into individual lines, and execute each line; terminate on | |
1395 | + * error. | |
1396 | + */ | |
1397 | + line = next = cmd; | |
1398 | + while (*next) { | |
1399 | + if (*next == '\n') { | |
1400 | + *next = '\0'; | |
1401 | + /* run only non-empty commands */ | |
1402 | + if (*line) { | |
1403 | + debug("** exec: \"%s\"\n", line); | |
1404 | + if (builtin_run_command(line, 0) < 0) { | |
1405 | + rcode = 1; | |
1406 | + break; | |
1407 | + } | |
1408 | + } | |
1409 | + line = next + 1; | |
1410 | + } | |
1411 | + ++next; | |
1412 | + } | |
1413 | + if (rcode == 0 && *line) | |
1414 | + rcode = (builtin_run_command(line, 0) >= 0); | |
1415 | + | |
1416 | + return rcode; | |
1417 | +} | |
1418 | +#endif | |
1419 | + | |
1420 | +int run_command_list(const char *cmd, int len, int flag) | |
1421 | +{ | |
1422 | + int need_buff = 1; | |
1423 | + char *buff = (char *)cmd; /* cast away const */ | |
1424 | + int rcode = 0; | |
1425 | + | |
1426 | + if (len == -1) { | |
1427 | + len = strlen(cmd); | |
1428 | +#ifdef CONFIG_SYS_HUSH_PARSER | |
1429 | + /* hush will never change our string */ | |
1430 | + need_buff = 0; | |
1431 | +#else | |
1432 | + /* the built-in parser will change our string if it sees \n */ | |
1433 | + need_buff = strchr(cmd, '\n') != NULL; | |
1434 | +#endif | |
1435 | + } | |
1436 | + if (need_buff) { | |
1437 | + buff = malloc(len + 1); | |
1438 | + if (!buff) | |
1439 | + return 1; | |
1440 | + memcpy(buff, cmd, len); | |
1441 | + buff[len] = '\0'; | |
1442 | + } | |
1443 | +#ifdef CONFIG_SYS_HUSH_PARSER | |
1444 | + rcode = parse_string_outer(buff, FLAG_PARSE_SEMICOLON); | |
1445 | +#else | |
1446 | + /* | |
1447 | + * This function will overwrite any \n it sees with a \0, which | |
1448 | + * is why it can't work with a const char *. Here we are making | |
1449 | + * using of internal knowledge of this function, to avoid always | |
1450 | + * doing a malloc() which is actually required only in a case that | |
1451 | + * is pretty rare. | |
1452 | + */ | |
1453 | + rcode = builtin_run_command_list(buff, flag); | |
1454 | + if (need_buff) | |
1455 | + free(buff); | |
1456 | +#endif | |
1457 | + | |
1458 | + return rcode; | |
1374 | 1459 | } |
1375 | 1460 | |
1376 | 1461 | /****************************************************************************/ |
include/common.h
... | ... | @@ -286,6 +286,19 @@ |
286 | 286 | /* common/main.c */ |
287 | 287 | void main_loop (void); |
288 | 288 | int run_command(const char *cmd, int flag); |
289 | + | |
290 | +/** | |
291 | + * Run a list of commands separated by ; or even \0 | |
292 | + * | |
293 | + * Note that if 'len' is not -1, then the command does not need to be nul | |
294 | + * terminated, Memory will be allocated for the command in that case. | |
295 | + * | |
296 | + * @param cmd List of commands to run, each separated bu semicolon | |
297 | + * @param len Length of commands excluding terminator if known (-1 if not) | |
298 | + * @param flag Execution flags (CMD_FLAG_...) | |
299 | + * @return 0 on success, or != 0 on error. | |
300 | + */ | |
301 | +int run_command_list(const char *cmd, int len, int flag); | |
289 | 302 | int readline (const char *const prompt); |
290 | 303 | int readline_into_buffer(const char *const prompt, char *buffer, |
291 | 304 | int timeout); |