blob: 3e92649ced3a981f932166b22899b7cab45971c0 [file] [log] [blame]
wdenkc6097192002-11-03 00:24:07 +00001/*
2 * (C) Copyright 2000
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
wdenka6c7ad22002-12-03 21:28:10 +000024/* #define DEBUG */
25
wdenkc6097192002-11-03 00:24:07 +000026#include <common.h>
27#include <watchdog.h>
28#include <command.h>
29#include <cmd_nvedit.h>
30#include <cmd_bootm.h>
31#include <malloc.h>
32#if defined(CONFIG_BOOT_RETRY_TIME) && defined(CONFIG_RESET_TO_RETRY)
33#include <cmd_boot.h> /* for do_reset() prototype */
34#endif
35
36#ifdef CFG_HUSH_PARSER
37#include <hush.h>
38#endif
39
40#define MAX_DELAY_STOP_STR 32
41
42static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen);
43static int parse_line (char *, char *[]);
44#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
45static int abortboot(int);
46#endif
47
48#undef DEBUG_PARSER
49
50char console_buffer[CFG_CBSIZE]; /* console I/O buffer */
51
52static char erase_seq[] = "\b \b"; /* erase sequence */
53static char tab_seq[] = " "; /* used to expand TABs */
54
55#ifdef CONFIG_BOOT_RETRY_TIME
56static uint64_t endtime = 0; /* must be set, default is instant timeout */
57static int retry_time = -1; /* -1 so can call readline before main_loop */
58#endif
59
60#define endtick(seconds) (get_ticks() + (uint64_t)(seconds) * get_tbclk())
61
62#ifndef CONFIG_BOOT_RETRY_MIN
63#define CONFIG_BOOT_RETRY_MIN CONFIG_BOOT_RETRY_TIME
64#endif
65
66#ifdef CONFIG_MODEM_SUPPORT
67int do_mdm_init = 0;
68extern void mdm_init(void); /* defined in board.c */
69#endif
70
71/***************************************************************************
72 * Watch for 'delay' seconds for autoboot stop or autoboot delay string.
73 * returns: 0 - no key string, allow autoboot
74 * 1 - got key string, abort
75 */
76#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
77# if defined(CONFIG_AUTOBOOT_KEYED)
78static __inline__ int abortboot(int bootdelay)
79{
80 int abort = 0;
81 uint64_t etime = endtick(bootdelay);
82 struct
83 {
84 char* str;
85 u_int len;
86 int retry;
87 }
88 delaykey [] =
89 {
90 { str: getenv ("bootdelaykey"), retry: 1 },
91 { str: getenv ("bootdelaykey2"), retry: 1 },
92 { str: getenv ("bootstopkey"), retry: 0 },
93 { str: getenv ("bootstopkey2"), retry: 0 },
94 };
95
96 char presskey [MAX_DELAY_STOP_STR];
97 u_int presskey_len = 0;
98 u_int presskey_max = 0;
99 u_int i;
100
101# ifdef CONFIG_AUTOBOOT_PROMPT
102 printf (CONFIG_AUTOBOOT_PROMPT, bootdelay);
103# endif
104
105# ifdef CONFIG_AUTOBOOT_DELAY_STR
106 if (delaykey[0].str == NULL)
107 delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR;
108# endif
109# ifdef CONFIG_AUTOBOOT_DELAY_STR2
110 if (delaykey[1].str == NULL)
111 delaykey[1].str = CONFIG_AUTOBOOT_DELAY_STR2;
112# endif
113# ifdef CONFIG_AUTOBOOT_STOP_STR
114 if (delaykey[2].str == NULL)
115 delaykey[2].str = CONFIG_AUTOBOOT_STOP_STR;
116# endif
117# ifdef CONFIG_AUTOBOOT_STOP_STR2
118 if (delaykey[3].str == NULL)
119 delaykey[3].str = CONFIG_AUTOBOOT_STOP_STR2;
120# endif
121
122 for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) {
123 delaykey[i].len = delaykey[i].str == NULL ?
124 0 : strlen (delaykey[i].str);
125 delaykey[i].len = delaykey[i].len > MAX_DELAY_STOP_STR ?
126 MAX_DELAY_STOP_STR : delaykey[i].len;
127
128 presskey_max = presskey_max > delaykey[i].len ?
129 presskey_max : delaykey[i].len;
130
131# if DEBUG_BOOTKEYS
132 printf("%s key:<%s>\n",
133 delaykey[i].retry ? "delay" : "stop",
134 delaykey[i].str ? delaykey[i].str : "NULL");
135# endif
136 }
137
138 /* In order to keep up with incoming data, check timeout only
139 * when catch up.
140 */
141 while (!abort && get_ticks() <= etime) {
142 for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) {
143 if (delaykey[i].len > 0 &&
144 presskey_len >= delaykey[i].len &&
145 memcmp (presskey + presskey_len - delaykey[i].len,
146 delaykey[i].str,
147 delaykey[i].len) == 0) {
148# if DEBUG_BOOTKEYS
149 printf("got %skey\n",
150 delaykey[i].retry ? "delay" : "stop");
151# endif
152
153# ifdef CONFIG_BOOT_RETRY_TIME
154 /* don't retry auto boot */
155 if (! delaykey[i].retry)
156 retry_time = -1;
157# endif
158 abort = 1;
159 }
160 }
161
162 if (tstc()) {
163 if (presskey_len < presskey_max) {
164 presskey [presskey_len ++] = getc();
165 }
166 else {
167 for (i = 0; i < presskey_max - 1; i ++)
168 presskey [i] = presskey [i + 1];
169
170 presskey [i] = getc();
171 }
172 }
173 }
174# if DEBUG_BOOTKEYS
175 if (!abort)
176 printf("key timeout\n");
177# endif
178
179 return abort;
180}
181
182# else /* !defined(CONFIG_AUTOBOOT_KEYED) */
183
wdenkc7de8292002-11-19 11:04:11 +0000184#ifdef CONFIG_MENUKEY
185static int menukey = 0;
186#endif
187
wdenkc6097192002-11-03 00:24:07 +0000188static __inline__ int abortboot(int bootdelay)
189{
190 int abort = 0;
191
wdenkc7de8292002-11-19 11:04:11 +0000192#ifdef CONFIG_MENUPROMPT
193 printf(CONFIG_MENUPROMPT, bootdelay);
194#else
wdenkc6097192002-11-03 00:24:07 +0000195 printf("Hit any key to stop autoboot: %2d ", bootdelay);
wdenkc7de8292002-11-19 11:04:11 +0000196#endif
wdenkc6097192002-11-03 00:24:07 +0000197
198#if defined CONFIG_ZERO_BOOTDELAY_CHECK
199 /*
200 * Check if key already pressed
201 * Don't check if bootdelay < 0
202 */
203 if (bootdelay >= 0) {
204 if (tstc()) { /* we got a key press */
205 (void) getc(); /* consume input */
206 printf ("\b\b\b 0\n");
207 return 1; /* don't auto boot */
208 }
209 }
210#endif
211
212 while (bootdelay > 0) {
213 int i;
214
215 --bootdelay;
216 /* delay 100 * 10ms */
217 for (i=0; !abort && i<100; ++i) {
218 if (tstc()) { /* we got a key press */
219 abort = 1; /* don't auto boot */
220 bootdelay = 0; /* no more delay */
wdenkc7de8292002-11-19 11:04:11 +0000221# ifdef CONFIG_MENUKEY
222 menukey = getc();
223# else
wdenkc6097192002-11-03 00:24:07 +0000224 (void) getc(); /* consume input */
wdenkc7de8292002-11-19 11:04:11 +0000225# endif
wdenkc6097192002-11-03 00:24:07 +0000226 break;
227 }
228 udelay (10000);
229 }
230
231 printf ("\b\b\b%2d ", bootdelay);
232 }
233
234 putc ('\n');
235
236 return abort;
237}
238# endif /* CONFIG_AUTOBOOT_KEYED */
239#endif /* CONFIG_BOOTDELAY >= 0 */
240
241/****************************************************************************/
242
243void main_loop (void)
244{
245#ifndef CFG_HUSH_PARSER
246 static char lastcommand[CFG_CBSIZE] = { 0, };
247 int len;
248 int rc = 1;
249 int flag;
250#endif
251
252#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
253 char *s;
254 int bootdelay;
255#endif
256#ifdef CONFIG_PREBOOT
257 char *p;
258#endif
259
260#if defined(CONFIG_VFD) && defined(VFD_TEST_LOGO)
261 ulong bmp = 0; /* default bitmap */
262 extern int trab_vfd (ulong bitmap);
263
264#ifdef CONFIG_MODEM_SUPPORT
265 if (do_mdm_init)
266 bmp = 1; /* alternate bitmap */
267#endif
268 trab_vfd (bmp);
269#endif /* CONFIG_VFD && VFD_TEST_LOGO */
270
271#ifdef CONFIG_MODEM_SUPPORT
272 debug ("DEBUG: main_loop: do_mdm_init=%d\n", do_mdm_init);
273 if (do_mdm_init) {
274 uchar *str = strdup(getenv("mdm_cmd"));
275 setenv ("preboot", str); /* set or delete definition */
276 if (str != NULL)
277 free (str);
278 mdm_init(); /* wait for modem connection */
279 }
280#endif /* CONFIG_MODEM_SUPPORT */
281
282#ifdef CFG_HUSH_PARSER
283 u_boot_hush_start ();
284#endif
285
286#ifdef CONFIG_PREBOOT
287 if ((p = getenv ("preboot")) != NULL) {
288# ifdef CONFIG_AUTOBOOT_KEYED
289 int prev = disable_ctrlc(1); /* disable Control C checking */
290# endif
291
292# ifndef CFG_HUSH_PARSER
293 run_command (p, 0);
294# else
295 parse_string_outer(p, FLAG_PARSE_SEMICOLON |
296 FLAG_EXIT_FROM_LOOP);
297# endif
298
299# ifdef CONFIG_AUTOBOOT_KEYED
300 disable_ctrlc(prev); /* restore Control C checking */
301# endif
302 }
303#endif /* CONFIG_PREBOOT */
304
305#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
306 s = getenv ("bootdelay");
307 bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
308
wdenka6c7ad22002-12-03 21:28:10 +0000309 debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay);
wdenkc6097192002-11-03 00:24:07 +0000310
311# ifdef CONFIG_BOOT_RETRY_TIME
312 s = getenv ("bootretry");
313 if (s != NULL)
314 retry_time = (int)simple_strtoul(s, NULL, 10);
315 else
316 retry_time = CONFIG_BOOT_RETRY_TIME;
317 if (retry_time >= 0 && retry_time < CONFIG_BOOT_RETRY_MIN)
318 retry_time = CONFIG_BOOT_RETRY_MIN;
319# endif /* CONFIG_BOOT_RETRY_TIME */
320
321 s = getenv ("bootcmd");
wdenka6c7ad22002-12-03 21:28:10 +0000322
323 debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
324
wdenkc6097192002-11-03 00:24:07 +0000325 if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
326# ifdef CONFIG_AUTOBOOT_KEYED
327 int prev = disable_ctrlc(1); /* disable Control C checking */
328# endif
329
330# ifndef CFG_HUSH_PARSER
331 run_command (s, 0);
332# else
333 parse_string_outer(s, FLAG_PARSE_SEMICOLON |
334 FLAG_EXIT_FROM_LOOP);
335# endif
336
337# ifdef CONFIG_AUTOBOOT_KEYED
338 disable_ctrlc(prev); /* restore Control C checking */
339# endif
340 }
wdenkc7de8292002-11-19 11:04:11 +0000341
342# ifdef CONFIG_MENUKEY
wdenka6c7ad22002-12-03 21:28:10 +0000343 if (menukey == CONFIG_MENUKEY) {
wdenkc7de8292002-11-19 11:04:11 +0000344 s = getenv("menucmd");
wdenka6c7ad22002-12-03 21:28:10 +0000345 if (s) {
wdenkc7de8292002-11-19 11:04:11 +0000346# ifndef CFG_HUSH_PARSER
347 run_command (s, bd, 0);
348# else
349 parse_string_outer(s, FLAG_PARSE_SEMICOLON |
350 FLAG_EXIT_FROM_LOOP);
351# endif
352 }
353 }
354#endif /* CONFIG_MENUKEY */
wdenkc6097192002-11-03 00:24:07 +0000355#endif /* CONFIG_BOOTDELAY */
356
wdenkc7de8292002-11-19 11:04:11 +0000357#ifdef CONFIG_AMIGAONEG3SE
358 {
359 extern void video_banner(void);
360 video_banner();
361 }
362#endif
363
wdenkc6097192002-11-03 00:24:07 +0000364 /*
365 * Main Loop for Monitor Command Processing
366 */
367#ifdef CFG_HUSH_PARSER
368 parse_file_outer();
369 /* This point is never reached */
370 for (;;);
371#else
372 for (;;) {
373#ifdef CONFIG_BOOT_RETRY_TIME
374 if (rc >= 0) {
375 /* Saw enough of a valid command to
376 * restart the timeout.
377 */
378 reset_cmd_timeout();
379 }
380#endif
381 len = readline (CFG_PROMPT);
382
383 flag = 0; /* assume no special flags for now */
384 if (len > 0)
385 strcpy (lastcommand, console_buffer);
386 else if (len == 0)
387 flag |= CMD_FLAG_REPEAT;
388#ifdef CONFIG_BOOT_RETRY_TIME
389 else if (len == -2) {
390 /* -2 means timed out, retry autoboot
391 */
392 printf("\nTimed out waiting for command\n");
393# ifdef CONFIG_RESET_TO_RETRY
394 /* Reinit board to run initialization code again */
395 do_reset (NULL, 0, 0, NULL);
396# else
397 return; /* retry autoboot */
398# endif
399 }
400#endif
401
402 if (len == -1)
403 printf ("<INTERRUPT>\n");
404 else
405 rc = run_command (lastcommand, flag);
406
407 if (rc <= 0) {
408 /* invalid command or not repeatable, forget it */
409 lastcommand[0] = 0;
410 }
411 }
412#endif /*CFG_HUSH_PARSER*/
413}
414
415/***************************************************************************
416 * reset command line timeout to retry_time seconds
417 */
418#ifdef CONFIG_BOOT_RETRY_TIME
419void reset_cmd_timeout(void)
420{
421 endtime = endtick(retry_time);
422}
423#endif
424
425/****************************************************************************/
426
427/*
428 * Prompt for input and read a line.
429 * If CONFIG_BOOT_RETRY_TIME is defined and retry_time >= 0,
430 * time out when time goes past endtime (timebase time in ticks).
431 * Return: number of read characters
432 * -1 if break
433 * -2 if timed out
434 */
435int readline (const char *const prompt)
436{
437 char *p = console_buffer;
438 int n = 0; /* buffer index */
439 int plen = 0; /* prompt length */
440 int col; /* output column cnt */
441 char c;
442
443 /* print prompt */
444 if (prompt) {
445 plen = strlen (prompt);
446 puts (prompt);
447 }
448 col = plen;
449
450 for (;;) {
451#ifdef CONFIG_BOOT_RETRY_TIME
452 while (!tstc()) { /* while no incoming data */
453 if (retry_time >= 0 && get_ticks() > endtime)
454 return (-2); /* timed out */
455 }
456#endif
457 WATCHDOG_RESET(); /* Trigger watchdog, if needed */
458
459#ifdef CONFIG_SHOW_ACTIVITY
460 while (!tstc()) {
461 extern void show_activity(int arg);
462 show_activity(0);
463 }
464#endif
465 c = getc();
466
467 /*
468 * Special character handling
469 */
470 switch (c) {
471 case '\r': /* Enter */
472 case '\n':
473 *p = '\0';
474 puts ("\r\n");
475 return (p - console_buffer);
476
477 case 0x03: /* ^C - break */
478 console_buffer[0] = '\0'; /* discard input */
479 return (-1);
480
481 case 0x15: /* ^U - erase line */
482 while (col > plen) {
483 puts (erase_seq);
484 --col;
485 }
486 p = console_buffer;
487 n = 0;
488 continue;
489
490 case 0x17: /* ^W - erase word */
491 p=delete_char(console_buffer, p, &col, &n, plen);
492 while ((n > 0) && (*p != ' ')) {
493 p=delete_char(console_buffer, p, &col, &n, plen);
494 }
495 continue;
496
497 case 0x08: /* ^H - backspace */
498 case 0x7F: /* DEL - backspace */
499 p=delete_char(console_buffer, p, &col, &n, plen);
500 continue;
501
502 default:
503 /*
504 * Must be a normal character then
505 */
506 if (n < CFG_CBSIZE-2) {
507 if (c == '\t') { /* expand TABs */
508 puts (tab_seq+(col&07));
509 col += 8 - (col&07);
510 } else {
511 ++col; /* echo input */
512 putc (c);
513 }
514 *p++ = c;
515 ++n;
516 } else { /* Buffer full */
517 putc ('\a');
518 }
519 }
520 }
521}
522
523/****************************************************************************/
524
525static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen)
526{
527 char *s;
528
529 if (*np == 0) {
530 return (p);
531 }
532
533 if (*(--p) == '\t') { /* will retype the whole line */
534 while (*colp > plen) {
535 puts (erase_seq);
536 (*colp)--;
537 }
538 for (s=buffer; s<p; ++s) {
539 if (*s == '\t') {
540 puts (tab_seq+((*colp) & 07));
541 *colp += 8 - ((*colp) & 07);
542 } else {
543 ++(*colp);
544 putc (*s);
545 }
546 }
547 } else {
548 puts (erase_seq);
549 (*colp)--;
550 }
551 (*np)--;
552 return (p);
553}
554
555/****************************************************************************/
556
557int parse_line (char *line, char *argv[])
558{
559 int nargs = 0;
560
561#ifdef DEBUG_PARSER
562 printf ("parse_line: \"%s\"\n", line);
563#endif
564 while (nargs < CFG_MAXARGS) {
565
566 /* skip any white space */
567 while ((*line == ' ') || (*line == '\t')) {
568 ++line;
569 }
570
571 if (*line == '\0') { /* end of line, no more args */
572 argv[nargs] = NULL;
573#ifdef DEBUG_PARSER
574 printf ("parse_line: nargs=%d\n", nargs);
575#endif
576 return (nargs);
577 }
578
579 argv[nargs++] = line; /* begin of argument string */
580
581 /* find end of string */
582 while (*line && (*line != ' ') && (*line != '\t')) {
583 ++line;
584 }
585
586 if (*line == '\0') { /* end of line, no more args */
587 argv[nargs] = NULL;
588#ifdef DEBUG_PARSER
589 printf ("parse_line: nargs=%d\n", nargs);
590#endif
591 return (nargs);
592 }
593
594 *line++ = '\0'; /* terminate current arg */
595 }
596
597 printf ("** Too many args (max. %d) **\n", CFG_MAXARGS);
598
599#ifdef DEBUG_PARSER
600 printf ("parse_line: nargs=%d\n", nargs);
601#endif
602 return (nargs);
603}
604
605/****************************************************************************/
606
607static void process_macros (const char *input, char *output)
608{
609 char c, prev;
610 const char *varname_start = NULL;
611 int inputcnt = strlen (input);
612 int outputcnt = CFG_CBSIZE;
613 int state = 0; /* 0 = waiting for '$' */
614 /* 1 = waiting for '(' */
615 /* 2 = waiting for ')' */
616
617#ifdef DEBUG_PARSER
618 char *output_start = output;
619
620 printf ("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", strlen(input), input);
621#endif
622
623 prev = '\0'; /* previous character */
624
625 while (inputcnt && outputcnt) {
626 c = *input++;
627 inputcnt--;
628
629 /* remove one level of escape characters */
630 if ((c == '\\') && (prev != '\\')) {
631 if (inputcnt-- == 0)
632 break;
633 prev = c;
634 c = *input++;
635 }
636
637 switch (state) {
638 case 0: /* Waiting for (unescaped) $ */
639 if ((c == '$') && (prev != '\\')) {
640 state++;
641 } else {
642 *(output++) = c;
643 outputcnt--;
644 }
645 break;
646 case 1: /* Waiting for ( */
647 if (c == '(') {
648 state++;
649 varname_start = input;
650 } else {
651 state = 0;
652 *(output++) = '$';
653 outputcnt--;
654
655 if (outputcnt) {
656 *(output++) = c;
657 outputcnt--;
658 }
659 }
660 break;
661 case 2: /* Waiting for ) */
662 if (c == ')') {
663 int i;
664 char envname[CFG_CBSIZE], *envval;
665 int envcnt = input-varname_start-1; /* Varname # of chars */
666
667 /* Get the varname */
668 for (i = 0; i < envcnt; i++) {
669 envname[i] = varname_start[i];
670 }
671 envname[i] = 0;
672
673 /* Get its value */
674 envval = getenv (envname);
675
676 /* Copy into the line if it exists */
677 if (envval != NULL)
678 while ((*envval) && outputcnt) {
679 *(output++) = *(envval++);
680 outputcnt--;
681 }
682 /* Look for another '$' */
683 state = 0;
684 }
685 break;
686 }
687
688 prev = c;
689 }
690
691 if (outputcnt)
692 *output = 0;
693
694#ifdef DEBUG_PARSER
695 printf ("[PROCESS_MACROS] OUTPUT len %d: \"%s\"\n",
696 strlen(output_start), output_start);
697#endif
698}
699
700/****************************************************************************
701 * returns:
702 * 1 - command executed, repeatable
703 * 0 - command executed but not repeatable, interrupted commands are
704 * always considered not repeatable
705 * -1 - not executed (unrecognized, bootd recursion or too many args)
706 * (If cmd is NULL or "" or longer than CFG_CBSIZE-1 it is
707 * considered unrecognized)
708 *
709 * WARNING:
710 *
711 * We must create a temporary copy of the command since the command we get
712 * may be the result from getenv(), which returns a pointer directly to
713 * the environment data, which may change magicly when the command we run
714 * creates or modifies environment variables (like "bootp" does).
715 */
716
717int run_command (const char *cmd, int flag)
718{
719 cmd_tbl_t *cmdtp;
720 char cmdbuf[CFG_CBSIZE]; /* working copy of cmd */
721 char *token; /* start of token in cmdbuf */
722 char *sep; /* end of token (separator) in cmdbuf */
723 char finaltoken[CFG_CBSIZE];
724 char *str = cmdbuf;
725 char *argv[CFG_MAXARGS + 1]; /* NULL terminated */
726 int argc;
727 int repeatable = 1;
728
729#ifdef DEBUG_PARSER
730 printf ("[RUN_COMMAND] cmd[%p]=\"", cmd);
731 puts (cmd ? cmd : "NULL"); /* use puts - string may be loooong */
732 puts ("\"\n");
733#endif
734
735 clear_ctrlc(); /* forget any previous Control C */
736
737 if (!cmd || !*cmd) {
738 return -1; /* empty command */
739 }
740
741 if (strlen(cmd) >= CFG_CBSIZE) {
742 puts ("## Command too long!\n");
743 return -1;
744 }
745
746 strcpy (cmdbuf, cmd);
747
748 /* Process separators and check for invalid
749 * repeatable commands
750 */
751
752#ifdef DEBUG_PARSER
753 printf ("[PROCESS_SEPARATORS] %s\n", cmd);
754#endif
755 while (*str) {
756
757 /*
758 * Find separator, or string end
759 * Allow simple escape of ';' by writing "\;"
760 */
761 for (sep = str; *sep; sep++) {
762 if ((*sep == ';') && /* separator */
763 ( sep != str) && /* past string start */
764 (*(sep-1) != '\\')) /* and NOT escaped */
765 break;
766 }
767
768 /*
769 * Limit the token to data between separators
770 */
771 token = str;
772 if (*sep) {
773 str = sep + 1; /* start of command for next pass */
774 *sep = '\0';
775 }
776 else
777 str = sep; /* no more commands for next pass */
778#ifdef DEBUG_PARSER
779 printf ("token: \"%s\"\n", token);
780#endif
781
782 /* find macros in this token and replace them */
783 process_macros (token, finaltoken);
784
785 /* Extract arguments */
786 argc = parse_line (finaltoken, argv);
787
788 /* Look up command in command table */
789 if ((cmdtp = find_cmd(argv[0])) == NULL) {
790 printf ("Unknown command '%s' - try 'help'\n", argv[0]);
791 return -1; /* give up after bad command */
792 }
793
794 /* found - check max args */
795 if (argc > cmdtp->maxargs) {
796 printf ("Usage:\n%s\n", cmdtp->usage);
797 return -1;
798 }
799
800#if (CONFIG_COMMANDS & CFG_CMD_BOOTD)
801 /* avoid "bootd" recursion */
802 if (cmdtp->cmd == do_bootd) {
803#ifdef DEBUG_PARSER
804 printf ("[%s]\n", finaltoken);
805#endif
806 if (flag & CMD_FLAG_BOOTD) {
807 printf ("'bootd' recursion detected\n");
808 return -1;
809 }
810 else
811 flag |= CMD_FLAG_BOOTD;
812 }
813#endif /* CFG_CMD_BOOTD */
814
815 /* OK - call function to do the command */
816 if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) {
817 return (-1);
818 }
819
820 repeatable &= cmdtp->repeatable;
821
822 /* Did the user stop this? */
823 if (had_ctrlc ())
824 return 0; /* if stopped then not repeatable */
825 }
826
827 return repeatable;
828}
829
830/****************************************************************************/
831
832#if (CONFIG_COMMANDS & CFG_CMD_RUN)
833int do_run (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
834{
835 int i;
836 int rcode = 1;
837
838 if (argc < 2) {
839 printf ("Usage:\n%s\n", cmdtp->usage);
840 return 1;
841 }
842
843 for (i=1; i<argc; ++i) {
844#ifndef CFG_HUSH_PARSER
845 if (run_command (getenv (argv[i]), flag) != -1) ++rcode;
846#else
847 if (parse_string_outer(getenv (argv[i]),
848 FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) == 0) ++rcode;
849#endif
850 }
851 return ((rcode == i) ? 0 : 1);
852}
853#endif