1 /* 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 24 /* #define DEBUG */ 25 26 #include <common.h> 27 #include <watchdog.h> 28 #include <command.h> 29 #ifdef CONFIG_MODEM_SUPPORT 30 #include <malloc.h> /* for free() prototype */ 31 #endif 32 33 #ifdef CFG_HUSH_PARSER 34 #include <hush.h> 35 #endif 36 37 #include <post.h> 38 39 #ifdef CONFIG_SILENT_CONSOLE 40 DECLARE_GLOBAL_DATA_PTR; 41 #endif 42 43 #if defined(CONFIG_BOOT_RETRY_TIME) && defined(CONFIG_RESET_TO_RETRY) 44 extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); /* for do_reset() prototype */ 45 #endif 46 47 extern int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); 48 49 50 #define MAX_DELAY_STOP_STR 32 51 52 static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen); 53 static int parse_line (char *, char *[]); 54 #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) 55 static int abortboot(int); 56 #endif 57 58 #undef DEBUG_PARSER 59 60 char console_buffer[CFG_CBSIZE]; /* console I/O buffer */ 61 62 static char erase_seq[] = "\b \b"; /* erase sequence */ 63 static char tab_seq[] = " "; /* used to expand TABs */ 64 65 #ifdef CONFIG_BOOT_RETRY_TIME 66 static uint64_t endtime = 0; /* must be set, default is instant timeout */ 67 static int retry_time = -1; /* -1 so can call readline before main_loop */ 68 #endif 69 70 #define endtick(seconds) (get_ticks() + (uint64_t)(seconds) * get_tbclk()) 71 72 #ifndef CONFIG_BOOT_RETRY_MIN 73 #define CONFIG_BOOT_RETRY_MIN CONFIG_BOOT_RETRY_TIME 74 #endif 75 76 #ifdef CONFIG_MODEM_SUPPORT 77 int do_mdm_init = 0; 78 extern void mdm_init(void); /* defined in board.c */ 79 #endif 80 81 /*************************************************************************** 82 * Watch for 'delay' seconds for autoboot stop or autoboot delay string. 83 * returns: 0 - no key string, allow autoboot 84 * 1 - got key string, abort 85 */ 86 #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) 87 # if defined(CONFIG_AUTOBOOT_KEYED) 88 static __inline__ int abortboot(int bootdelay) 89 { 90 int abort = 0; 91 uint64_t etime = endtick(bootdelay); 92 struct 93 { 94 char* str; 95 u_int len; 96 int retry; 97 } 98 delaykey [] = 99 { 100 { str: getenv ("bootdelaykey"), retry: 1 }, 101 { str: getenv ("bootdelaykey2"), retry: 1 }, 102 { str: getenv ("bootstopkey"), retry: 0 }, 103 { str: getenv ("bootstopkey2"), retry: 0 }, 104 }; 105 106 char presskey [MAX_DELAY_STOP_STR]; 107 u_int presskey_len = 0; 108 u_int presskey_max = 0; 109 u_int i; 110 111 #ifdef CONFIG_SILENT_CONSOLE 112 if (gd->flags & GD_FLG_SILENT) { 113 /* Restore serial console */ 114 console_assign (stdout, "serial"); 115 console_assign (stderr, "serial"); 116 } 117 #endif 118 119 # ifdef CONFIG_AUTOBOOT_PROMPT 120 printf (CONFIG_AUTOBOOT_PROMPT, bootdelay); 121 # endif 122 123 # ifdef CONFIG_AUTOBOOT_DELAY_STR 124 if (delaykey[0].str == NULL) 125 delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR; 126 # endif 127 # ifdef CONFIG_AUTOBOOT_DELAY_STR2 128 if (delaykey[1].str == NULL) 129 delaykey[1].str = CONFIG_AUTOBOOT_DELAY_STR2; 130 # endif 131 # ifdef CONFIG_AUTOBOOT_STOP_STR 132 if (delaykey[2].str == NULL) 133 delaykey[2].str = CONFIG_AUTOBOOT_STOP_STR; 134 # endif 135 # ifdef CONFIG_AUTOBOOT_STOP_STR2 136 if (delaykey[3].str == NULL) 137 delaykey[3].str = CONFIG_AUTOBOOT_STOP_STR2; 138 # endif 139 140 for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) { 141 delaykey[i].len = delaykey[i].str == NULL ? 142 0 : strlen (delaykey[i].str); 143 delaykey[i].len = delaykey[i].len > MAX_DELAY_STOP_STR ? 144 MAX_DELAY_STOP_STR : delaykey[i].len; 145 146 presskey_max = presskey_max > delaykey[i].len ? 147 presskey_max : delaykey[i].len; 148 149 # if DEBUG_BOOTKEYS 150 printf("%s key:<%s>\n", 151 delaykey[i].retry ? "delay" : "stop", 152 delaykey[i].str ? delaykey[i].str : "NULL"); 153 # endif 154 } 155 156 /* In order to keep up with incoming data, check timeout only 157 * when catch up. 158 */ 159 while (!abort && get_ticks() <= etime) { 160 for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) { 161 if (delaykey[i].len > 0 && 162 presskey_len >= delaykey[i].len && 163 memcmp (presskey + presskey_len - delaykey[i].len, 164 delaykey[i].str, 165 delaykey[i].len) == 0) { 166 # if DEBUG_BOOTKEYS 167 printf("got %skey\n", 168 delaykey[i].retry ? "delay" : "stop"); 169 # endif 170 171 # ifdef CONFIG_BOOT_RETRY_TIME 172 /* don't retry auto boot */ 173 if (! delaykey[i].retry) 174 retry_time = -1; 175 # endif 176 abort = 1; 177 } 178 } 179 180 if (tstc()) { 181 if (presskey_len < presskey_max) { 182 presskey [presskey_len ++] = getc(); 183 } 184 else { 185 for (i = 0; i < presskey_max - 1; i ++) 186 presskey [i] = presskey [i + 1]; 187 188 presskey [i] = getc(); 189 } 190 } 191 } 192 # if DEBUG_BOOTKEYS 193 if (!abort) 194 puts ("key timeout\n"); 195 # endif 196 197 #ifdef CONFIG_SILENT_CONSOLE 198 if (abort) { 199 /* permanently enable normal console output */ 200 gd->flags &= ~(GD_FLG_SILENT); 201 } else if (gd->flags & GD_FLG_SILENT) { 202 /* Restore silent console */ 203 console_assign (stdout, "nulldev"); 204 console_assign (stderr, "nulldev"); 205 } 206 #endif 207 208 return abort; 209 } 210 211 # else /* !defined(CONFIG_AUTOBOOT_KEYED) */ 212 213 #ifdef CONFIG_MENUKEY 214 static int menukey = 0; 215 #endif 216 217 static __inline__ int abortboot(int bootdelay) 218 { 219 int abort = 0; 220 221 #ifdef CONFIG_SILENT_CONSOLE 222 if (gd->flags & GD_FLG_SILENT) { 223 /* Restore serial console */ 224 console_assign (stdout, "serial"); 225 console_assign (stderr, "serial"); 226 } 227 #endif 228 229 #ifdef CONFIG_MENUPROMPT 230 printf(CONFIG_MENUPROMPT, bootdelay); 231 #else 232 printf("Hit any key to stop autoboot: %2d ", bootdelay); 233 #endif 234 235 #if defined CONFIG_ZERO_BOOTDELAY_CHECK 236 /* 237 * Check if key already pressed 238 * Don't check if bootdelay < 0 239 */ 240 if (bootdelay >= 0) { 241 if (tstc()) { /* we got a key press */ 242 (void) getc(); /* consume input */ 243 puts ("\b\b\b 0"); 244 abort = 1; /* don't auto boot */ 245 } 246 } 247 #endif 248 249 while ((bootdelay > 0) && (!abort)) { 250 int i; 251 252 --bootdelay; 253 /* delay 100 * 10ms */ 254 for (i=0; !abort && i<100; ++i) { 255 if (tstc()) { /* we got a key press */ 256 abort = 1; /* don't auto boot */ 257 bootdelay = 0; /* no more delay */ 258 # ifdef CONFIG_MENUKEY 259 menukey = getc(); 260 # else 261 (void) getc(); /* consume input */ 262 # endif 263 break; 264 } 265 udelay (10000); 266 } 267 268 printf ("\b\b\b%2d ", bootdelay); 269 } 270 271 putc ('\n'); 272 273 #ifdef CONFIG_SILENT_CONSOLE 274 if (abort) { 275 /* permanently enable normal console output */ 276 gd->flags &= ~(GD_FLG_SILENT); 277 } else if (gd->flags & GD_FLG_SILENT) { 278 /* Restore silent console */ 279 console_assign (stdout, "nulldev"); 280 console_assign (stderr, "nulldev"); 281 } 282 #endif 283 284 return abort; 285 } 286 # endif /* CONFIG_AUTOBOOT_KEYED */ 287 #endif /* CONFIG_BOOTDELAY >= 0 */ 288 289 /****************************************************************************/ 290 291 void main_loop (void) 292 { 293 #ifndef CFG_HUSH_PARSER 294 static char lastcommand[CFG_CBSIZE] = { 0, }; 295 int len; 296 int rc = 1; 297 int flag; 298 #endif 299 300 #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) 301 char *s; 302 int bootdelay; 303 #endif 304 #ifdef CONFIG_PREBOOT 305 char *p; 306 #endif 307 #ifdef CONFIG_BOOTCOUNT_LIMIT 308 unsigned long bootcount = 0; 309 unsigned long bootlimit = 0; 310 char *bcs; 311 char bcs_set[16]; 312 #endif /* CONFIG_BOOTCOUNT_LIMIT */ 313 314 #if defined(CONFIG_VFD) && defined(VFD_TEST_LOGO) 315 ulong bmp = 0; /* default bitmap */ 316 extern int trab_vfd (ulong bitmap); 317 318 #ifdef CONFIG_MODEM_SUPPORT 319 if (do_mdm_init) 320 bmp = 1; /* alternate bitmap */ 321 #endif 322 trab_vfd (bmp); 323 #endif /* CONFIG_VFD && VFD_TEST_LOGO */ 324 325 #ifdef CONFIG_BOOTCOUNT_LIMIT 326 bootcount = bootcount_load(); 327 bootcount++; 328 bootcount_store (bootcount); 329 sprintf (bcs_set, "%lu", bootcount); 330 setenv ("bootcount", bcs_set); 331 bcs = getenv ("bootlimit"); 332 bootlimit = bcs ? simple_strtoul (bcs, NULL, 10) : 0; 333 #endif /* CONFIG_BOOTCOUNT_LIMIT */ 334 335 #ifdef CONFIG_MODEM_SUPPORT 336 debug ("DEBUG: main_loop: do_mdm_init=%d\n", do_mdm_init); 337 if (do_mdm_init) { 338 char *str = strdup(getenv("mdm_cmd")); 339 setenv ("preboot", str); /* set or delete definition */ 340 if (str != NULL) 341 free (str); 342 mdm_init(); /* wait for modem connection */ 343 } 344 #endif /* CONFIG_MODEM_SUPPORT */ 345 346 #ifdef CONFIG_VERSION_VARIABLE 347 { 348 extern char version_string[]; 349 350 setenv ("ver", version_string); /* set version variable */ 351 } 352 #endif /* CONFIG_VERSION_VARIABLE */ 353 354 #ifdef CFG_HUSH_PARSER 355 u_boot_hush_start (); 356 #endif 357 358 #ifdef CONFIG_AUTO_COMPLETE 359 install_auto_complete(); 360 #endif 361 362 #ifdef CONFIG_PREBOOT 363 if ((p = getenv ("preboot")) != NULL) { 364 # ifdef CONFIG_AUTOBOOT_KEYED 365 int prev = disable_ctrlc(1); /* disable Control C checking */ 366 # endif 367 368 # ifndef CFG_HUSH_PARSER 369 run_command (p, 0); 370 # else 371 parse_string_outer(p, FLAG_PARSE_SEMICOLON | 372 FLAG_EXIT_FROM_LOOP); 373 # endif 374 375 # ifdef CONFIG_AUTOBOOT_KEYED 376 disable_ctrlc(prev); /* restore Control C checking */ 377 # endif 378 } 379 #endif /* CONFIG_PREBOOT */ 380 381 #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) 382 s = getenv ("bootdelay"); 383 bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY; 384 385 debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay); 386 387 # ifdef CONFIG_BOOT_RETRY_TIME 388 init_cmd_timeout (); 389 # endif /* CONFIG_BOOT_RETRY_TIME */ 390 391 #ifdef CONFIG_BOOTCOUNT_LIMIT 392 if (bootlimit && (bootcount > bootlimit)) { 393 printf ("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n", 394 (unsigned)bootlimit); 395 s = getenv ("altbootcmd"); 396 } 397 else 398 #endif /* CONFIG_BOOTCOUNT_LIMIT */ 399 s = getenv ("bootcmd"); 400 401 debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>"); 402 403 if (bootdelay >= 0 && s && !abortboot (bootdelay)) { 404 # ifdef CONFIG_AUTOBOOT_KEYED 405 int prev = disable_ctrlc(1); /* disable Control C checking */ 406 # endif 407 408 # ifndef CFG_HUSH_PARSER 409 run_command (s, 0); 410 # else 411 parse_string_outer(s, FLAG_PARSE_SEMICOLON | 412 FLAG_EXIT_FROM_LOOP); 413 # endif 414 415 # ifdef CONFIG_AUTOBOOT_KEYED 416 disable_ctrlc(prev); /* restore Control C checking */ 417 # endif 418 } 419 420 # ifdef CONFIG_MENUKEY 421 if (menukey == CONFIG_MENUKEY) { 422 s = getenv("menucmd"); 423 if (s) { 424 # ifndef CFG_HUSH_PARSER 425 run_command (s, 0); 426 # else 427 parse_string_outer(s, FLAG_PARSE_SEMICOLON | 428 FLAG_EXIT_FROM_LOOP); 429 # endif 430 } 431 } 432 #endif /* CONFIG_MENUKEY */ 433 #endif /* CONFIG_BOOTDELAY */ 434 435 #ifdef CONFIG_AMIGAONEG3SE 436 { 437 extern void video_banner(void); 438 video_banner(); 439 } 440 #endif 441 442 /* 443 * Main Loop for Monitor Command Processing 444 */ 445 #ifdef CFG_HUSH_PARSER 446 parse_file_outer(); 447 /* This point is never reached */ 448 for (;;); 449 #else 450 for (;;) { 451 #ifdef CONFIG_BOOT_RETRY_TIME 452 if (rc >= 0) { 453 /* Saw enough of a valid command to 454 * restart the timeout. 455 */ 456 reset_cmd_timeout(); 457 } 458 #endif 459 len = readline (CFG_PROMPT); 460 461 flag = 0; /* assume no special flags for now */ 462 if (len > 0) 463 strcpy (lastcommand, console_buffer); 464 else if (len == 0) 465 flag |= CMD_FLAG_REPEAT; 466 #ifdef CONFIG_BOOT_RETRY_TIME 467 else if (len == -2) { 468 /* -2 means timed out, retry autoboot 469 */ 470 puts ("\nTimed out waiting for command\n"); 471 # ifdef CONFIG_RESET_TO_RETRY 472 /* Reinit board to run initialization code again */ 473 do_reset (NULL, 0, 0, NULL); 474 # else 475 return; /* retry autoboot */ 476 # endif 477 } 478 #endif 479 480 if (len == -1) 481 puts ("<INTERRUPT>\n"); 482 else 483 rc = run_command (lastcommand, flag); 484 485 if (rc <= 0) { 486 /* invalid command or not repeatable, forget it */ 487 lastcommand[0] = 0; 488 } 489 } 490 #endif /*CFG_HUSH_PARSER*/ 491 } 492 493 #ifdef CONFIG_BOOT_RETRY_TIME 494 /*************************************************************************** 495 * initialise command line timeout 496 */ 497 void init_cmd_timeout(void) 498 { 499 char *s = getenv ("bootretry"); 500 501 if (s != NULL) 502 retry_time = (int)simple_strtol(s, NULL, 10); 503 else 504 retry_time = CONFIG_BOOT_RETRY_TIME; 505 506 if (retry_time >= 0 && retry_time < CONFIG_BOOT_RETRY_MIN) 507 retry_time = CONFIG_BOOT_RETRY_MIN; 508 } 509 510 /*************************************************************************** 511 * reset command line timeout to retry_time seconds 512 */ 513 void reset_cmd_timeout(void) 514 { 515 endtime = endtick(retry_time); 516 } 517 #endif 518 519 /****************************************************************************/ 520 521 /* 522 * Prompt for input and read a line. 523 * If CONFIG_BOOT_RETRY_TIME is defined and retry_time >= 0, 524 * time out when time goes past endtime (timebase time in ticks). 525 * Return: number of read characters 526 * -1 if break 527 * -2 if timed out 528 */ 529 int readline (const char *const prompt) 530 { 531 char *p = console_buffer; 532 int n = 0; /* buffer index */ 533 int plen = 0; /* prompt length */ 534 int col; /* output column cnt */ 535 char c; 536 537 /* print prompt */ 538 if (prompt) { 539 plen = strlen (prompt); 540 puts (prompt); 541 } 542 col = plen; 543 544 for (;;) { 545 #ifdef CONFIG_BOOT_RETRY_TIME 546 while (!tstc()) { /* while no incoming data */ 547 if (retry_time >= 0 && get_ticks() > endtime) 548 return (-2); /* timed out */ 549 } 550 #endif 551 WATCHDOG_RESET(); /* Trigger watchdog, if needed */ 552 553 #ifdef CONFIG_SHOW_ACTIVITY 554 while (!tstc()) { 555 extern void show_activity(int arg); 556 show_activity(0); 557 } 558 #endif 559 c = getc(); 560 561 /* 562 * Special character handling 563 */ 564 switch (c) { 565 case '\r': /* Enter */ 566 case '\n': 567 *p = '\0'; 568 puts ("\r\n"); 569 return (p - console_buffer); 570 571 case '\0': /* nul */ 572 continue; 573 574 case 0x03: /* ^C - break */ 575 console_buffer[0] = '\0'; /* discard input */ 576 return (-1); 577 578 case 0x15: /* ^U - erase line */ 579 while (col > plen) { 580 puts (erase_seq); 581 --col; 582 } 583 p = console_buffer; 584 n = 0; 585 continue; 586 587 case 0x17: /* ^W - erase word */ 588 p=delete_char(console_buffer, p, &col, &n, plen); 589 while ((n > 0) && (*p != ' ')) { 590 p=delete_char(console_buffer, p, &col, &n, plen); 591 } 592 continue; 593 594 case 0x08: /* ^H - backspace */ 595 case 0x7F: /* DEL - backspace */ 596 p=delete_char(console_buffer, p, &col, &n, plen); 597 continue; 598 599 default: 600 /* 601 * Must be a normal character then 602 */ 603 if (n < CFG_CBSIZE-2) { 604 if (c == '\t') { /* expand TABs */ 605 #ifdef CONFIG_AUTO_COMPLETE 606 /* if auto completion triggered just continue */ 607 *p = '\0'; 608 if (cmd_auto_complete(prompt, console_buffer, &n, &col)) { 609 p = console_buffer + n; /* reset */ 610 continue; 611 } 612 #endif 613 puts (tab_seq+(col&07)); 614 col += 8 - (col&07); 615 } else { 616 ++col; /* echo input */ 617 putc (c); 618 } 619 *p++ = c; 620 ++n; 621 } else { /* Buffer full */ 622 putc ('\a'); 623 } 624 } 625 } 626 } 627 628 /****************************************************************************/ 629 630 static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen) 631 { 632 char *s; 633 634 if (*np == 0) { 635 return (p); 636 } 637 638 if (*(--p) == '\t') { /* will retype the whole line */ 639 while (*colp > plen) { 640 puts (erase_seq); 641 (*colp)--; 642 } 643 for (s=buffer; s<p; ++s) { 644 if (*s == '\t') { 645 puts (tab_seq+((*colp) & 07)); 646 *colp += 8 - ((*colp) & 07); 647 } else { 648 ++(*colp); 649 putc (*s); 650 } 651 } 652 } else { 653 puts (erase_seq); 654 (*colp)--; 655 } 656 (*np)--; 657 return (p); 658 } 659 660 /****************************************************************************/ 661 662 int parse_line (char *line, char *argv[]) 663 { 664 int nargs = 0; 665 666 #ifdef DEBUG_PARSER 667 printf ("parse_line: \"%s\"\n", line); 668 #endif 669 while (nargs < CFG_MAXARGS) { 670 671 /* skip any white space */ 672 while ((*line == ' ') || (*line == '\t')) { 673 ++line; 674 } 675 676 if (*line == '\0') { /* end of line, no more args */ 677 argv[nargs] = NULL; 678 #ifdef DEBUG_PARSER 679 printf ("parse_line: nargs=%d\n", nargs); 680 #endif 681 return (nargs); 682 } 683 684 argv[nargs++] = line; /* begin of argument string */ 685 686 /* find end of string */ 687 while (*line && (*line != ' ') && (*line != '\t')) { 688 ++line; 689 } 690 691 if (*line == '\0') { /* end of line, no more args */ 692 argv[nargs] = NULL; 693 #ifdef DEBUG_PARSER 694 printf ("parse_line: nargs=%d\n", nargs); 695 #endif 696 return (nargs); 697 } 698 699 *line++ = '\0'; /* terminate current arg */ 700 } 701 702 printf ("** Too many args (max. %d) **\n", CFG_MAXARGS); 703 704 #ifdef DEBUG_PARSER 705 printf ("parse_line: nargs=%d\n", nargs); 706 #endif 707 return (nargs); 708 } 709 710 /****************************************************************************/ 711 712 static void process_macros (const char *input, char *output) 713 { 714 char c, prev; 715 const char *varname_start = NULL; 716 int inputcnt = strlen (input); 717 int outputcnt = CFG_CBSIZE; 718 int state = 0; /* 0 = waiting for '$' */ 719 /* 1 = waiting for '(' or '{' */ 720 /* 2 = waiting for ')' or '}' */ 721 /* 3 = waiting for ''' */ 722 #ifdef DEBUG_PARSER 723 char *output_start = output; 724 725 printf ("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", strlen(input), input); 726 #endif 727 728 prev = '\0'; /* previous character */ 729 730 while (inputcnt && outputcnt) { 731 c = *input++; 732 inputcnt--; 733 734 if (state!=3) { 735 /* remove one level of escape characters */ 736 if ((c == '\\') && (prev != '\\')) { 737 if (inputcnt-- == 0) 738 break; 739 prev = c; 740 c = *input++; 741 } 742 } 743 744 switch (state) { 745 case 0: /* Waiting for (unescaped) $ */ 746 if ((c == '\'') && (prev != '\\')) { 747 state = 3; 748 break; 749 } 750 if ((c == '$') && (prev != '\\')) { 751 state++; 752 } else { 753 *(output++) = c; 754 outputcnt--; 755 } 756 break; 757 case 1: /* Waiting for ( */ 758 if (c == '(' || c == '{') { 759 state++; 760 varname_start = input; 761 } else { 762 state = 0; 763 *(output++) = '$'; 764 outputcnt--; 765 766 if (outputcnt) { 767 *(output++) = c; 768 outputcnt--; 769 } 770 } 771 break; 772 case 2: /* Waiting for ) */ 773 if (c == ')' || c == '}') { 774 int i; 775 char envname[CFG_CBSIZE], *envval; 776 int envcnt = input-varname_start-1; /* Varname # of chars */ 777 778 /* Get the varname */ 779 for (i = 0; i < envcnt; i++) { 780 envname[i] = varname_start[i]; 781 } 782 envname[i] = 0; 783 784 /* Get its value */ 785 envval = getenv (envname); 786 787 /* Copy into the line if it exists */ 788 if (envval != NULL) 789 while ((*envval) && outputcnt) { 790 *(output++) = *(envval++); 791 outputcnt--; 792 } 793 /* Look for another '$' */ 794 state = 0; 795 } 796 break; 797 case 3: /* Waiting for ' */ 798 if ((c == '\'') && (prev != '\\')) { 799 state = 0; 800 } else { 801 *(output++) = c; 802 outputcnt--; 803 } 804 break; 805 } 806 prev = c; 807 } 808 809 if (outputcnt) 810 *output = 0; 811 812 #ifdef DEBUG_PARSER 813 printf ("[PROCESS_MACROS] OUTPUT len %d: \"%s\"\n", 814 strlen(output_start), output_start); 815 #endif 816 } 817 818 /**************************************************************************** 819 * returns: 820 * 1 - command executed, repeatable 821 * 0 - command executed but not repeatable, interrupted commands are 822 * always considered not repeatable 823 * -1 - not executed (unrecognized, bootd recursion or too many args) 824 * (If cmd is NULL or "" or longer than CFG_CBSIZE-1 it is 825 * considered unrecognized) 826 * 827 * WARNING: 828 * 829 * We must create a temporary copy of the command since the command we get 830 * may be the result from getenv(), which returns a pointer directly to 831 * the environment data, which may change magicly when the command we run 832 * creates or modifies environment variables (like "bootp" does). 833 */ 834 835 int run_command (const char *cmd, int flag) 836 { 837 cmd_tbl_t *cmdtp; 838 char cmdbuf[CFG_CBSIZE]; /* working copy of cmd */ 839 char *token; /* start of token in cmdbuf */ 840 char *sep; /* end of token (separator) in cmdbuf */ 841 char finaltoken[CFG_CBSIZE]; 842 char *str = cmdbuf; 843 char *argv[CFG_MAXARGS + 1]; /* NULL terminated */ 844 int argc, inquotes; 845 int repeatable = 1; 846 int rc = 0; 847 848 #ifdef DEBUG_PARSER 849 printf ("[RUN_COMMAND] cmd[%p]=\"", cmd); 850 puts (cmd ? cmd : "NULL"); /* use puts - string may be loooong */ 851 puts ("\"\n"); 852 #endif 853 854 clear_ctrlc(); /* forget any previous Control C */ 855 856 if (!cmd || !*cmd) { 857 return -1; /* empty command */ 858 } 859 860 if (strlen(cmd) >= CFG_CBSIZE) { 861 puts ("## Command too long!\n"); 862 return -1; 863 } 864 865 strcpy (cmdbuf, cmd); 866 867 /* Process separators and check for invalid 868 * repeatable commands 869 */ 870 871 #ifdef DEBUG_PARSER 872 printf ("[PROCESS_SEPARATORS] %s\n", cmd); 873 #endif 874 while (*str) { 875 876 /* 877 * Find separator, or string end 878 * Allow simple escape of ';' by writing "\;" 879 */ 880 for (inquotes = 0, sep = str; *sep; sep++) { 881 if ((*sep=='\'') && 882 (*(sep-1) != '\\')) 883 inquotes=!inquotes; 884 885 if (!inquotes && 886 (*sep == ';') && /* separator */ 887 ( sep != str) && /* past string start */ 888 (*(sep-1) != '\\')) /* and NOT escaped */ 889 break; 890 } 891 892 /* 893 * Limit the token to data between separators 894 */ 895 token = str; 896 if (*sep) { 897 str = sep + 1; /* start of command for next pass */ 898 *sep = '\0'; 899 } 900 else 901 str = sep; /* no more commands for next pass */ 902 #ifdef DEBUG_PARSER 903 printf ("token: \"%s\"\n", token); 904 #endif 905 906 /* find macros in this token and replace them */ 907 process_macros (token, finaltoken); 908 909 /* Extract arguments */ 910 if ((argc = parse_line (finaltoken, argv)) == 0) { 911 rc = -1; /* no command at all */ 912 continue; 913 } 914 915 /* Look up command in command table */ 916 if ((cmdtp = find_cmd(argv[0])) == NULL) { 917 printf ("Unknown command '%s' - try 'help'\n", argv[0]); 918 rc = -1; /* give up after bad command */ 919 continue; 920 } 921 922 /* found - check max args */ 923 if (argc > cmdtp->maxargs) { 924 printf ("Usage:\n%s\n", cmdtp->usage); 925 rc = -1; 926 continue; 927 } 928 929 #if (CONFIG_COMMANDS & CFG_CMD_BOOTD) 930 /* avoid "bootd" recursion */ 931 if (cmdtp->cmd == do_bootd) { 932 #ifdef DEBUG_PARSER 933 printf ("[%s]\n", finaltoken); 934 #endif 935 if (flag & CMD_FLAG_BOOTD) { 936 puts ("'bootd' recursion detected\n"); 937 rc = -1; 938 continue; 939 } else { 940 flag |= CMD_FLAG_BOOTD; 941 } 942 } 943 #endif /* CFG_CMD_BOOTD */ 944 945 /* OK - call function to do the command */ 946 if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) { 947 rc = -1; 948 } 949 950 repeatable &= cmdtp->repeatable; 951 952 /* Did the user stop this? */ 953 if (had_ctrlc ()) 954 return 0; /* if stopped then not repeatable */ 955 } 956 957 return rc ? rc : repeatable; 958 } 959 960 /****************************************************************************/ 961 962 #if (CONFIG_COMMANDS & CFG_CMD_RUN) 963 int do_run (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) 964 { 965 int i; 966 967 if (argc < 2) { 968 printf ("Usage:\n%s\n", cmdtp->usage); 969 return 1; 970 } 971 972 for (i=1; i<argc; ++i) { 973 char *arg; 974 975 if ((arg = getenv (argv[i])) == NULL) { 976 printf ("## Error: \"%s\" not defined\n", argv[i]); 977 return 1; 978 } 979 #ifndef CFG_HUSH_PARSER 980 if (run_command (arg, flag) == -1) 981 return 1; 982 #else 983 if (parse_string_outer(arg, 984 FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0) 985 return 1; 986 #endif 987 } 988 return 0; 989 } 990 #endif /* CFG_CMD_RUN */ 991