📄 main.c
字号:
#endif /*CFG_HUSH_PARSER*/}#ifdef CONFIG_BOOT_RETRY_TIME/*************************************************************************** * initialise command line timeout */void init_cmd_timeout(void){ char *s = getenv ("bootretry"); if (s != NULL) retry_time = (int)simple_strtol(s, NULL, 10); else retry_time = CONFIG_BOOT_RETRY_TIME; if (retry_time >= 0 && retry_time < CONFIG_BOOT_RETRY_MIN) retry_time = CONFIG_BOOT_RETRY_MIN;}/*************************************************************************** * reset command line timeout to retry_time seconds */void reset_cmd_timeout(void){ endtime = endtick(retry_time);}#endif/****************************************************************************//* * Prompt for input and read a line. * If CONFIG_BOOT_RETRY_TIME is defined and retry_time >= 0, * time out when time goes past endtime (timebase time in ticks). * Return: number of read characters * -1 if break * -2 if timed out */int readline (const char *const prompt){ char *p = console_buffer; int n = 0; /* buffer index */ int plen = 0; /* prompt length */ int col; /* output column cnt */ char c; /* print prompt */ if (prompt) { plen = strlen (prompt); puts (prompt); } col = plen; for (;;) {#ifdef CONFIG_BOOT_RETRY_TIME while (!tstc()) { /* while no incoming data */ if (retry_time >= 0 && get_ticks() > endtime) return (-2); /* timed out */ }#endif WATCHDOG_RESET(); /* Trigger watchdog, if needed */#ifdef CONFIG_SHOW_ACTIVITY while (!tstc()) { extern void show_activity(int arg); show_activity(0); }#endif c = getc(); /* * Special character handling */ switch (c) { case '\r': /* Enter */ case '\n': *p = '\0'; puts ("\r\n"); return (p - console_buffer); case '\0': /* nul */ continue; case 0x03: /* ^C - break */ console_buffer[0] = '\0'; /* discard input */ return (-1); case 0x15: /* ^U - erase line */ while (col > plen) { puts (erase_seq); --col; } p = console_buffer; n = 0; continue; case 0x17: /* ^W - erase word */ p=delete_char(console_buffer, p, &col, &n, plen); while ((n > 0) && (*p != ' ')) { p=delete_char(console_buffer, p, &col, &n, plen); } continue; case 0x08: /* ^H - backspace */ case 0x7F: /* DEL - backspace */ p=delete_char(console_buffer, p, &col, &n, plen); continue; default: /* * Must be a normal character then */ if (n < CFG_CBSIZE-2) { if (c == '\t') { /* expand TABs */#ifdef CONFIG_AUTO_COMPLETE /* if auto completion triggered just continue */ *p = '\0'; if (cmd_auto_complete(prompt, console_buffer, &n, &col)) { p = console_buffer + n; /* reset */ continue; }#endif puts (tab_seq+(col&07)); col += 8 - (col&07); } else { ++col; /* echo input */ putc (c); } *p++ = c; ++n; } else { /* Buffer full */ putc ('\a'); } } }}/****************************************************************************/static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen){ char *s; if (*np == 0) { return (p); } if (*(--p) == '\t') { /* will retype the whole line */ while (*colp > plen) { puts (erase_seq); (*colp)--; } for (s=buffer; s<p; ++s) { if (*s == '\t') { puts (tab_seq+((*colp) & 07)); *colp += 8 - ((*colp) & 07); } else { ++(*colp); putc (*s); } } } else { puts (erase_seq); (*colp)--; } (*np)--; return (p);}/****************************************************************************/int parse_line (char *line, char *argv[]){ int nargs = 0;#ifdef DEBUG_PARSER printf ("parse_line: \"%s\"\n", line);#endif while (nargs < CFG_MAXARGS) { /* skip any white space */ while ((*line == ' ') || (*line == '\t')) { ++line; } if (*line == '\0') { /* end of line, no more args */ argv[nargs] = NULL;#ifdef DEBUG_PARSER printf ("parse_line: nargs=%d\n", nargs);#endif return (nargs); } argv[nargs++] = line; /* begin of argument string */ /* find end of string */ while (*line && (*line != ' ') && (*line != '\t')) { ++line; } if (*line == '\0') { /* end of line, no more args */ argv[nargs] = NULL;#ifdef DEBUG_PARSER printf ("parse_line: nargs=%d\n", nargs);#endif return (nargs); } *line++ = '\0'; /* terminate current arg */ } printf ("** Too many args (max. %d) **\n", CFG_MAXARGS);#ifdef DEBUG_PARSER printf ("parse_line: nargs=%d\n", nargs);#endif return (nargs);}/****************************************************************************/static void process_macros (const char *input, char *output){ char c, prev; const char *varname_start = NULL; int inputcnt = strlen (input); int outputcnt = CFG_CBSIZE; int state = 0; /* 0 = waiting for '$' */ /* 1 = waiting for '(' or '{' */ /* 2 = waiting for ')' or '}' */ /* 3 = waiting for ''' */#ifdef DEBUG_PARSER char *output_start = output; printf ("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", strlen(input), input);#endif prev = '\0'; /* previous character */ while (inputcnt && outputcnt) { c = *input++; inputcnt--; if (state!=3) { /* remove one level of escape characters */ if ((c == '\\') && (prev != '\\')) { if (inputcnt-- == 0) break; prev = c; c = *input++; } } switch (state) { case 0: /* Waiting for (unescaped) $ */ if ((c == '\'') && (prev != '\\')) { state = 3; break; } if ((c == '$') && (prev != '\\')) { state++; } else { *(output++) = c; outputcnt--; } break; case 1: /* Waiting for ( */ if (c == '(' || c == '{') { state++; varname_start = input; } else { state = 0; *(output++) = '$'; outputcnt--; if (outputcnt) { *(output++) = c; outputcnt--; } } break; case 2: /* Waiting for ) */ if (c == ')' || c == '}') { int i; char envname[CFG_CBSIZE], *envval; int envcnt = input-varname_start-1; /* Varname # of chars */ /* Get the varname */ for (i = 0; i < envcnt; i++) { envname[i] = varname_start[i]; } envname[i] = 0; /* Get its value */ envval = getenv (envname); /* Copy into the line if it exists */ if (envval != NULL) while ((*envval) && outputcnt) { *(output++) = *(envval++); outputcnt--; } /* Look for another '$' */ state = 0; } break; case 3: /* Waiting for ' */ if ((c == '\'') && (prev != '\\')) { state = 0; } else { *(output++) = c; outputcnt--; } break; } prev = c; } if (outputcnt) *output = 0;#ifdef DEBUG_PARSER printf ("[PROCESS_MACROS] OUTPUT len %d: \"%s\"\n", strlen(output_start), output_start);#endif}/**************************************************************************** * returns: * 1 - command executed, repeatable * 0 - command executed but not repeatable, interrupted commands are * always considered not repeatable * -1 - not executed (unrecognized, bootd recursion or too many args) * (If cmd is NULL or "" or longer than CFG_CBSIZE-1 it is * considered unrecognized) * * WARNING: * * We must create a temporary copy of the command since the command we get * may be the result from getenv(), which returns a pointer directly to * the environment data, which may change magicly when the command we run * creates or modifies environment variables (like "bootp" does). */int run_command (const char *cmd, int flag){ cmd_tbl_t *cmdtp; char cmdbuf[CFG_CBSIZE]; /* working copy of cmd */ char *token; /* start of token in cmdbuf */ char *sep; /* end of token (separator) in cmdbuf */ char finaltoken[CFG_CBSIZE]; char *str = cmdbuf; char *argv[CFG_MAXARGS + 1]; /* NULL terminated */ int argc, inquotes; int repeatable = 1; int rc = 0;#ifdef DEBUG_PARSER printf ("[RUN_COMMAND] cmd[%p]=\"", cmd); puts (cmd ? cmd : "NULL"); /* use puts - string may be loooong */ puts ("\"\n");#endif clear_ctrlc(); /* forget any previous Control C */ if (!cmd || !*cmd) { return -1; /* empty command */ } if (strlen(cmd) >= CFG_CBSIZE) { puts ("## Command too long!\n"); return -1; } strcpy (cmdbuf, cmd); /* Process separators and check for invalid * repeatable commands */#ifdef DEBUG_PARSER printf ("[PROCESS_SEPARATORS] %s\n", cmd);#endif while (*str) { /* * Find separator, or string end * Allow simple escape of ';' by writing "\;" */ for (inquotes = 0, sep = str; *sep; sep++) { if ((*sep=='\'') && (*(sep-1) != '\\')) inquotes=!inquotes; if (!inquotes && (*sep == ';') && /* separator */ ( sep != str) && /* past string start */ (*(sep-1) != '\\')) /* and NOT escaped */ break; } /* * Limit the token to data between separators */ token = str; if (*sep) { str = sep + 1; /* start of command for next pass */ *sep = '\0'; } else str = sep; /* no more commands for next pass */#ifdef DEBUG_PARSER printf ("token: \"%s\"\n", token);#endif /* find macros in this token and replace them */ process_macros (token, finaltoken); /* Extract arguments */ argc = parse_line (finaltoken, argv); /* Look up command in command table */ if ((cmdtp = find_cmd(argv[0])) == NULL) { printf ("Unknown command '%s' - try 'help'\n", argv[0]); rc = -1; /* give up after bad command */ continue; } /* found - check max args */ if (argc > cmdtp->maxargs) { printf ("Usage:\n%s\n", cmdtp->usage); rc = -1; continue; }#if (CONFIG_COMMANDS & CFG_CMD_BOOTD) /* avoid "bootd" recursion */ if (cmdtp->cmd == do_bootd) {#ifdef DEBUG_PARSER printf ("[%s]\n", finaltoken);#endif if (flag & CMD_FLAG_BOOTD) { puts ("'bootd' recursion detected\n"); rc = -1; continue; } else flag |= CMD_FLAG_BOOTD; }#endif /* CFG_CMD_BOOTD */ /* OK - call function to do the command */ if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) { rc = -1; } repeatable &= cmdtp->repeatable; /* Did the user stop this? */ if (had_ctrlc ()) return 0; /* if stopped then not repeatable */ } return rc ? rc : repeatable;}/****************************************************************************/#if (CONFIG_COMMANDS & CFG_CMD_RUN)int do_run (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]){ int i; if (argc < 2) { printf ("Usage:\n%s\n", cmdtp->usage); return 1; } for (i=1; i<argc; ++i) { char *arg; if ((arg = getenv (argv[i])) == NULL) { printf ("## Error: \"%s\" not defined\n", argv[i]); return 1; }#ifndef CFG_HUSH_PARSER if (run_command (arg, flag) == -1) return 1;#else if (parse_string_outer(arg, FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0) return 1;#endif } return 0;}#endif /* CFG_CMD_RUN */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -