1 /* vi: set sw=4 ts=4: */
3 * sh.c -- a prototype Bourne shell grammar parser
4 * Intended to follow the original Thompson and Ritchie
5 * "small and simple is beautiful" philosophy, which
6 * incidentally is a good match to today's BusyBox.
8 * Copyright (C) 2000,2001 Larry Doolittle <larry@doolittle.boa.org>
11 * The parser routines proper are all original material, first
12 * written Dec 2000 and Jan 2001 by Larry Doolittle.
13 * The execution engine, the builtins, and much of the underlying
14 * support has been adapted from busybox-0.49pre's lash,
15 * which is Copyright (C) 2000 by Lineo, Inc., and
16 * written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>.
17 * That, in turn, is based in part on ladsh.c, by Michael K. Johnson and
18 * Erik W. Troan, which they placed in the public domain. I don't know
19 * how much of the Johnson/Troan code has survived the repeated rewrites.
21 * simple_itoa() was lifted from boa-0.93.15
22 * b_addchr() derived from similar w_addchar function in glibc-2.2
23 * setup_redirect(), redirect_opt_num(), and big chunks of main()
24 * and many builtins derived from contributions by Erik Andersen
25 * miscellaneous bugfixes from Matt Kraai
27 * There are two big (and related) architecture differences between
28 * this parser and the lash parser. One is that this version is
29 * actually designed from the ground up to understand nearly all
30 * of the Bourne grammar. The second, consequential change is that
31 * the parser and input reader have been turned inside out. Now,
32 * the parser is in control, and asks for input as needed. The old
33 * way had the input reader in control, and it asked for parsing to
34 * take place as needed. The new way makes it much easier to properly
35 * handle the recursion implicit in the various substitutions, especially
36 * across continuation lines.
38 * Bash grammar not implemented: (how many of these were in original sh?)
39 * $@ (those sure look like weird quoting rules)
41 * ! negation operator for pipes
42 * &> and >& redirection of stdout+stderr
45 * fancy forms of Parameter Expansion
47 * Arithmetic Expansion
48 * <(list) and >(list) Process Substitution
49 * reserved words: case, esac, select, function
50 * Here Documents ( << word )
53 * job handling woefully incomplete and buggy
54 * reserved word execution woefully incomplete and buggy
56 * port selected bugfixes from post-0.49 busybox lash - done?
57 * finish implementing reserved words: for, while, until, do, done
58 * change { and } from special chars to reserved words
59 * builtins: break, continue, eval, return, set, trap, ulimit
61 * handle children going into background
62 * clean up recognition of null pipes
63 * check setting of global_argc and global_argv
64 * control-C handling, probably with longjmp
65 * follow IFS rules more precisely, including update semantics
66 * figure out what to do with backslash-newline
67 * explain why we use signal instead of sigaction
68 * propagate syntax errors, die on resource errors?
69 * continuation lines, both explicit and implicit - done?
70 * memory leak finding and plugging - done?
71 * more testing, especially quoting rules and redirection
72 * document how quoting rules not precisely followed for variable assignments
73 * maybe change map[] to use 2-bit entries
74 * (eventually) remove all the printf's
76 * This program is free software; you can redistribute it and/or modify
77 * it under the terms of the GNU General Public License as published by
78 * the Free Software Foundation; either version 2 of the License, or
79 * (at your option) any later version.
81 * This program is distributed in the hope that it will be useful,
82 * but WITHOUT ANY WARRANTY; without even the implied warranty of
83 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
84 * General Public License for more details.
86 * You should have received a copy of the GNU General Public License
87 * along with this program; if not, write to the Free Software
88 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
91 #include <malloc.h> /* malloc, free, realloc*/
92 #include <linux/ctype.h> /* isalpha, isdigit */
93 #include <common.h> /* readline */
95 #include <command.h> /* find_cmd */
97 extern int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); /* do_bootd */
99 #ifdef CFG_HUSH_PARSER
100 #define SPECIAL_VAR_SYMBOL 03
102 DECLARE_GLOBAL_DATA_PTR;
104 #define EXIT_SUCCESS 0
106 #define syntax() syntax_err()
107 #define xstrdup strdup
108 #define error_msg printf
111 PIPE_SEQ = 1, PIPE_AND = 2, PIPE_OR = 3, PIPE_BG = 4,
114 /* might eventually control execution */
131 #define FLAG_END (1<<RES_NONE)
132 #define FLAG_IF (1<<RES_IF)
133 #define FLAG_THEN (1<<RES_THEN)
134 #define FLAG_ELIF (1<<RES_ELIF)
135 #define FLAG_ELSE (1<<RES_ELSE)
136 #define FLAG_FI (1<<RES_FI)
137 #define FLAG_FOR (1<<RES_FOR)
138 #define FLAG_WHILE (1<<RES_WHILE)
139 #define FLAG_UNTIL (1<<RES_UNTIL)
140 #define FLAG_DO (1<<RES_DO)
141 #define FLAG_DONE (1<<RES_DONE)
142 #define FLAG_IN (1<<RES_IN)
143 #define FLAG_START (1<<RES_XXXX)
145 /* This holds pointers to the various results of parsing */
147 struct child_prog *child;
148 struct pipe *list_head;
151 int old_flag; /* for figuring out valid reserved words */
152 struct p_context *stack;
153 int type; /* define type of parser : ";$" common or special symbol */
154 /* How about quoting status? */
158 char **argv; /* program name and arguments */
159 int argc; /* number of program arguments */
160 struct pipe *group; /* if non-NULL, first in group or subshell */
161 int sp; /* number of SPECIAL_VAR_SYMBOL */
166 int num_progs; /* total number of programs in job */
167 struct child_prog *progs; /* array of commands in pipe */
168 struct pipe *next; /* to track background commands */
169 pipe_style followup; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */
170 reserved_style r_mode; /* supports if, for, while, until */
178 struct variables *next;
181 /* globals, connect us to the outside world
182 * the first three support $?, $#, and $1 */
183 unsigned int last_return_code;
186 /* "globals" within this file */
188 static char map[256];
189 static int flag_repeat = 0;
190 static int do_repeat = 0;
191 static struct variables *top_vars = NULL;
193 #define B_CHUNK (100)
203 #define NULL_O_STRING {NULL,0,0,0,0}
204 /* used for initialization:
205 o_string foo = NULL_O_STRING; */
207 /* I can almost use ordinary FILE *. Is open_memstream() universally
208 * available? Where is it documented? */
213 int (*get)(struct in_str *);
214 int (*peek)(struct in_str *);
216 #define b_getch(input) ((input)->get(input))
217 #define b_peek(input) ((input)->peek(input))
219 /* This should be in utility.c */
221 #define debug_printf printf /* U-Boot debug flag */
223 static inline void debug_printf(const char *format, ...) {
226 #define final_printf debug_printf
228 static void syntax_err(void) {
229 printf_err("syntax error!\n");
232 static void *xmalloc(size_t size);
233 static void *xrealloc(void *ptr, size_t size);
235 /* o_string manipulation: */
236 static int b_check_space(o_string *o, int len);
237 static int b_addchr(o_string *o, int ch);
238 static void b_reset(o_string *o);
239 static int b_addqchr(o_string *o, int ch, int quote);
241 /* in_str manipulations: */
242 static int static_get(struct in_str *i);
243 static int static_peek(struct in_str *i);
244 static int file_get(struct in_str *i);
245 static int file_peek(struct in_str *i);
246 static void setup_file_in_str(struct in_str *i);
247 static void setup_string_in_str(struct in_str *i, const char *s);
249 /* "run" the final data structures: */
250 static char *indenter(int i);
251 static int free_pipe_list(struct pipe *head, int indent);
252 static int free_pipe(struct pipe *pi, int indent);
254 /* really run the final data structures: */
255 static int run_list_real(struct pipe *pi);
256 static int run_pipe_real(struct pipe *pi);
258 /* variable assignment: */
259 static int is_assignment(const char *s);
261 /* data structure manipulation: */
262 static void initialize_context(struct p_context *ctx);
263 static int done_word(o_string *dest, struct p_context *ctx);
264 static int done_command(struct p_context *ctx);
265 static int done_pipe(struct p_context *ctx, pipe_style type);
267 /* primary string parsing: */
268 static char *lookup_param(char *src);
269 static char *make_string(char **inp);
270 static int handle_dollar(o_string *dest, struct p_context *ctx,
271 struct in_str *input);
272 static int parse_stream(o_string *dest, struct p_context *ctx,
273 struct in_str *input0, int end_trigger);
276 static int parse_stream_outer(struct in_str *inp, int flag);
278 /* local variable support */
279 static char **make_list_in(char **inp, char *name);
280 static char *insert_var_value(char *inp);
281 static char *get_local_var(const char *var);
282 static int set_local_var(const char *s, int flg_export);
284 static int b_check_space(o_string *o, int len) {
285 /* It would be easy to drop a more restrictive policy
286 * in here, such as setting a maximum string length */
287 if (o->length + len > o->maxlen) {
288 char *old_data = o->data;
289 /* assert (data == NULL || o->maxlen != 0); */
290 o->maxlen += max(2 * len, B_CHUNK);
291 o->data = realloc(o->data, 1 + o->maxlen);
292 if (o->data == NULL) {
296 return o->data == NULL;
299 static int b_addchr(o_string *o, int ch) {
300 debug_printf("b_addchr: %c %d %p\n", ch, o->length, o);
301 if (b_check_space(o, 1))
303 o->data[o->length] = ch;
305 o->data[o->length] = '\0';
309 static void b_reset(o_string *o) {
316 static void b_free(o_string *o) {
323 /* My analysis of quoting semantics tells me that state information
324 * is associated with a destination, not a source.
326 static int b_addqchr(o_string *o, int ch, int quote) {
327 if (quote && strchr("*?[\\", ch)) {
329 rc = b_addchr(o, '\\');
333 return b_addchr(o, ch);
336 /* belongs in utility.c */
337 char *simple_itoa(unsigned int i) {
338 /* 21 digits plus null terminator, good for 64-bit or smaller ints */
339 static char local[22];
340 char *p = &local[21];
349 static int static_get(struct in_str *i) {
356 static int static_peek(struct in_str *i) {
360 static void get_user_input(struct in_str *i) {
361 extern char console_buffer[CFG_CBSIZE];
363 static char the_command[CFG_CBSIZE];
365 #ifdef CONFIG_BOOT_RETRY_TIME
366 # ifdef CONFIG_RESET_TO_RETRY
367 extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
369 # error "This currently only works with CONFIG_RESET_TO_RETRY enabled"
374 if (i->promptmode == 1) {
375 n = readline(CFG_PROMPT);
377 n = readline(CFG_PROMPT_HUSH_PS2);
379 #ifdef CONFIG_BOOT_RETRY_TIME
381 puts("\nTimeout waiting for command\n");
382 # ifdef CONFIG_RESET_TO_RETRY
383 do_reset(NULL, 0, 0, NULL);
385 # error "This currently only works with CONFIG_RESET_TO_RETRY enabled"
393 n = strlen(console_buffer);
394 console_buffer[n] = '\n';
395 console_buffer[n + 1] = '\0';
400 if (i->promptmode == 1) {
401 if (console_buffer[0] == '\n' && flag_repeat == 0) {
402 strcpy(the_command, console_buffer);
404 if (console_buffer[0] != '\n') {
405 strcpy(the_command, console_buffer);
413 if (console_buffer[0] != '\n') {
414 if (strlen(the_command) + strlen(console_buffer) < CFG_CBSIZE) {
415 n = strlen(the_command);
416 the_command[n - 1] = ' ';
417 strcpy(&the_command[n], console_buffer);
419 the_command[0] = '\n';
420 the_command[1] = '\0';
424 if (i->__promptme == 0) {
425 the_command[0] = '\n';
426 the_command[1] = '\0';
428 i->p = console_buffer;
432 /* This is the magic location that prints prompts
433 * and gets data back from the user */
434 static int file_get(struct in_str *i) {
438 /* If there is data waiting, eat it up */
442 /* need to double check i->file because we might be doing something
443 * more complicated by now, like sourcing or substituting. */
444 while (!i->p || strlen(i->p) == 0) {
453 debug_printf("b_getch: got a %d\n", ch);
459 /* All the callers guarantee this routine will never be
460 * used right after a newline, so prompting is not needed.
462 static int file_peek(struct in_str *i) {
466 static void setup_file_in_str(struct in_str *i) {
474 static void setup_string_in_str(struct in_str *i, const char *s) {
475 i->peek = static_peek;
482 /* run_pipe_real() starts all the jobs, but doesn't wait for anything
483 * to finish. See checkjobs().
485 * return code is normally -1, when the caller has to wait for children
486 * to finish to determine the exit status of the pipe. If the pipe
487 * is a simple builtin command, however, the action is done by the
488 * time run_pipe_real returns, and the exit code is provided as the
491 * The input of the pipe is always stdin, the output is always
492 * stdout. The outpipe[] mechanism in BusyBox-0.48 lash is bogus,
493 * because it tries to avoid running the command substitution in
494 * subshell, when that is in fact necessary. The subshell process
495 * now has its stdout directed to the input of the appropriate pipe,
496 * so this routine is noticeably simpler.
498 static int run_pipe_real(struct pipe *pi) {
501 int flag = do_repeat ? CMD_FLAG_REPEAT : 0;
502 struct child_prog *child;
506 /* Avoid longjmp clobbering */
514 /* Check if this is a simple builtin (not part of a pipe).
515 * Builtins within pipes have to fork anyway, and are handled in
516 * pseudo_exec. "echo foo | read bar" doesn't work on bash, either.
518 if (pi->num_progs == 1)
519 child = &(pi->progs[0]);
520 if (pi->num_progs == 1 && child->group) {
522 debug_printf("non-subshell grouping\n");
523 rcode = run_list_real(child->group);
525 } else if (pi->num_progs == 1 && pi->progs[0].argv != NULL) {
526 for (i = 0; is_assignment(child->argv[i]); i++) { /* nothing */
528 if (i != 0 && child->argv[i] == NULL) {
529 /* assignments, but no command: set the local environment */
530 for (i = 0; child->argv[i] != NULL; i++) {
532 /* Ok, this case is tricky. We have to decide if this is a
533 * local variable, or an already exported variable. If it is
534 * already exported, we have to export the new value. If it is
535 * not exported, we need only set this as a local variable.
536 * This junk is all to decide whether or not to export this
540 name = xstrdup(child->argv[i]);
541 debug_printf("Local environment set: %s\n", name);
542 value = strchr(name, '=');
546 p = insert_var_value(child->argv[i]);
547 set_local_var(p, export_me);
548 if (p != child->argv[i])
551 return EXIT_SUCCESS; /* don't worry about errors in set_local_var() yet */
553 for (i = 0; is_assignment(child->argv[i]); i++) {
554 p = insert_var_value(child->argv[i]);
556 if (p != child->argv[i]) {
564 str = make_string((child->argv + i));
565 parse_string_outer(str, FLAG_EXIT_FROM_LOOP | FLAG_REPARSING);
567 return last_return_code;
570 /* check ";", because ,example , argv consist from
571 * "help;flinfo" must not execute
573 if (strchr(child->argv[i], ';')) {
574 printf_err("unknown command '%s' - try 'help' or use 'run' command\n", child->argv[i]);
578 /* Look up command in command table */
579 if ((cmdtp = find_cmd(child->argv[i])) == NULL) {
580 printf_err("unknown command '%s' - try 'help'\n", child->argv[i]);
581 return -1; /* give up after bad command */
584 #if defined(CONFIG_CMD_BOOTD)
585 extern int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
587 /* avoid "bootd" recursion */
588 if (cmdtp->cmd == do_bootd) {
589 if (flag & CMD_FLAG_BOOTD) {
590 printf_err("'bootd' recursion detected!\n");
593 flag |= CMD_FLAG_BOOTD;
596 #endif /* CONFIG_CMD_BOOTD */
597 /* found - check max args */
598 if ((child->argc - i) > cmdtp->maxargs) {
599 print_cmd_help(cmdtp);
602 child->argv += i; /* XXX horrible hack */
603 /* OK - call function to do the command */
604 rcode = (cmdtp->cmd)(cmdtp, flag, child->argc - i, &child->argv[i]);
606 if (!cmdtp->repeatable)
609 child->argv -= i; /* XXX restore hack so free() can work right */
617 static int run_list_real(struct pipe *pi) {
618 char *save_name = NULL;
620 char **save_list = NULL;
623 int rcode = 0, flag_skip = 1;
624 int flag_restore = 0;
625 int if_code = 0, next_if_code = 0; /* need double-buffer to handle elif */
626 reserved_style rmode, skip_more_in_this_rmode = RES_XXXX;
627 /* check syntax for "for" */
628 for (rpipe = pi; rpipe; rpipe = rpipe->next) {
629 if ((rpipe->r_mode == RES_IN || rpipe->r_mode == RES_FOR)
630 && (rpipe->next == NULL)) {
635 if ((rpipe->r_mode == RES_IN
636 && (rpipe->next->r_mode == RES_IN
637 && rpipe->next->progs->argv != NULL))
638 || (rpipe->r_mode == RES_FOR && rpipe->next->r_mode != RES_IN)) {
644 for (; pi; pi = (flag_restore != 0) ? rpipe : pi->next) {
645 if (pi->r_mode == RES_WHILE || pi->r_mode == RES_UNTIL
646 || pi->r_mode == RES_FOR) {
659 debug_printf("rmode=%d if_code=%d next_if_code=%d skip_more=%d\n",
660 rmode, if_code, next_if_code, skip_more_in_this_rmode);
661 if (rmode == skip_more_in_this_rmode && flag_skip) {
662 if (pi->followup == PIPE_SEQ)
667 skip_more_in_this_rmode = RES_XXXX;
668 if (rmode == RES_THEN || rmode == RES_ELSE)
669 if_code = next_if_code;
670 if (rmode == RES_THEN && if_code)
672 if (rmode == RES_ELSE && !if_code)
674 if (rmode == RES_ELIF && !if_code)
676 if (rmode == RES_FOR && pi->num_progs) {
678 /* if no variable values after "in" we skip "for" */
679 if (!pi->next->progs->argv)
681 /* create list of variable values */
682 list = make_list_in(pi->next->progs->argv, pi->progs->argv[0]);
684 save_name = pi->progs->argv[0];
685 pi->progs->argv[0] = NULL;
689 free(pi->progs->argv[0]);
693 pi->progs->argv[0] = save_name;
696 /* insert new value from list for variable */
697 if (pi->progs->argv[0])
698 free(pi->progs->argv[0]);
699 pi->progs->argv[0] = *list++;
704 if (rmode == RES_DO) {
708 if ((rmode == RES_DONE)) {
715 if (pi->num_progs == 0)
717 rcode = run_pipe_real(pi);
718 debug_printf("run_pipe_real returned %d\n", rcode);
720 last_return_code = -rcode - 2;
721 return -2; /* exit */
723 last_return_code = (rcode == 0) ? 0 : 1;
725 if (rmode == RES_IF || rmode == RES_ELIF)
726 next_if_code = rcode; /* can be overwritten a number of times */
727 if (rmode == RES_WHILE)
728 flag_rep = !last_return_code;
729 if (rmode == RES_UNTIL)
730 flag_rep = last_return_code;
731 if ((rcode == EXIT_SUCCESS && pi->followup == PIPE_OR)
732 || (rcode != EXIT_SUCCESS && pi->followup == PIPE_AND))
733 skip_more_in_this_rmode = rmode;
738 /* broken, of course, but OK for testing */
739 static char *indenter(int i) {
740 static char blanks[] = " ";
741 return &blanks[sizeof(blanks) - i - 1];
744 /* return code is the exit status of the pipe */
745 static int free_pipe(struct pipe *pi, int indent) {
747 struct child_prog *child;
748 int a, i, ret_code = 0;
749 char *ind = indenter(indent);
751 for (i = 0; i < pi->num_progs; i++) {
752 child = &pi->progs[i];
753 final_printf("%s command %d:\n", ind, i);
755 for (a = 0, p = child->argv; *p; a++, p++) {
756 final_printf("%s argv[%d] = %s\n", ind, a, *p);
758 for (a = child->argc; a >= 0; a--) {
759 free(child->argv[a]);
764 } else if (child->group) {
765 ret_code = free_pipe_list(child->group, indent + 3);
766 final_printf("%s end group\n", ind);
768 final_printf("%s (nil)\n", ind);
771 free(pi->progs); /* children are an array, they get freed all at once */
776 static int free_pipe_list(struct pipe *head, int indent) {
777 int rcode = 0; /* if list has no members */
778 struct pipe *pi, *next;
779 char *ind = indenter(indent);
780 for (pi = head; pi; pi = next) {
781 final_printf("%s pipe reserved mode %d\n", ind, pi->r_mode);
782 rcode = free_pipe(pi, indent);
783 final_printf("%s pipe followup code %d\n", ind, pi->followup);
791 /* Select which version we will use */
792 static int run_list(struct pipe *pi) {
793 int rcode = run_list_real(pi);
795 /* free_pipe_list has the side effect of clearing memory
796 * In the long run that function can be merged with run_list_real,
797 * but doing that now would hobble the debugging effort. */
798 free_pipe_list(pi, 0);
802 static char *get_dollar_var(char ch);
804 /* This is used to get/check local shell variables */
805 static char *get_local_var(const char *s) {
806 struct variables *cur;
812 return get_dollar_var(s[1]);
814 for (cur = top_vars; cur; cur = cur->next)
815 if (strcmp(cur->name, s) == 0)
820 /* This is used to set local shell variables
821 flg_export==0 if only local (not exporting) variable
822 flg_export==1 if "new" exporting environ
823 flg_export>1 if current startup environ (not call putenv()) */
824 static int set_local_var(const char *s, int flg_export) {
827 struct variables *cur;
829 /* might be possible! */
835 if (getenv(name) != NULL) {
836 printf_err("there is a global environment variable with the same name!\n");
841 /* Assume when we enter this function that we are already in
842 * NAME=VALUE format. So the first order of business is to
843 * split 's' on the '=' into 'name' and 'value' */
844 value = strchr(name, '=');
845 if (value == 0 && ++value == 0) {
851 for (cur = top_vars; cur; cur = cur->next) {
852 if (strcmp(cur->name, name) == 0)
857 if (strcmp(cur->value, value) == 0) {
858 if (flg_export > 0 && cur->flg_export == 0)
859 cur->flg_export = flg_export;
863 if (cur->flg_read_only) {
864 printf_err("%s: readonly variable", name);
867 if (flg_export > 0 || cur->flg_export > 1)
871 cur->value = strdup(value);
875 cur = malloc(sizeof(struct variables));
879 cur->name = strdup(name);
880 if (cur->name == 0) {
884 struct variables *bottom = top_vars;
885 cur->value = strdup(value);
887 cur->flg_export = flg_export;
888 cur->flg_read_only = 0;
890 bottom = bottom->next;
901 static int is_assignment(const char *s) {
908 while (isalnum(*s) || *s == '_')
913 struct pipe *new_pipe(void) {
915 pi = xmalloc(sizeof(struct pipe));
919 pi->followup = 0; /* invalid */
920 pi->r_mode = RES_NONE;
924 static void initialize_context(struct p_context *ctx) {
927 ctx->list_head = new_pipe();
928 ctx->pipe = ctx->list_head;
932 done_command(ctx); /* creates the memory for working child */
935 /* normal return is 0
936 * if a reserved word is found, and processed, return 1
937 * should handle if, then, elif, else, fi, for, while, until, do, done.
938 * case, function, and select are obnoxious, save those for later.
940 struct reserved_combo {
945 /* Mostly a list of accepted follow-up reserved words.
946 * FLAG_END means we are done with the sequence, and are ready
947 * to turn the compound list into a command.
948 * FLAG_START means the word must start a new compound list.
950 static struct reserved_combo reserved_list[] = { { "if", RES_IF, FLAG_THEN
951 | FLAG_START }, { "then", RES_THEN, FLAG_ELIF | FLAG_ELSE | FLAG_FI }, {
952 "elif", RES_ELIF, FLAG_THEN }, { "else", RES_ELSE, FLAG_FI }, { "fi",
953 RES_FI, FLAG_END }, { "for", RES_FOR, FLAG_IN | FLAG_START }, { "while",
954 RES_WHILE, FLAG_DO | FLAG_START }, { "until", RES_UNTIL, FLAG_DO
955 | FLAG_START }, { "in", RES_IN, FLAG_DO }, { "do", RES_DO, FLAG_DONE },
956 { "done", RES_DONE, FLAG_END } };
957 #define NRES (sizeof(reserved_list)/sizeof(struct reserved_combo))
959 int reserved_word(o_string *dest, struct p_context *ctx) {
960 struct reserved_combo *r;
961 for (r = reserved_list; r < reserved_list + NRES; r++) {
962 if (strcmp(dest->data, r->literal) == 0) {
963 debug_printf("found reserved word %s, code %d\n", r->literal,
965 if (r->flag & FLAG_START) {
966 struct p_context *new = xmalloc(sizeof(struct p_context));
967 debug_printf("push stack\n");
968 if (ctx->w == RES_IN || ctx->w == RES_FOR) {
975 *new = *ctx; /* physical copy */
976 initialize_context(ctx);
978 } else if (ctx->w == RES_NONE
979 || !(ctx->old_flag & (1 << r->code))) {
986 ctx->old_flag = r->flag;
987 if (ctx->old_flag & FLAG_END) {
988 struct p_context *old;
989 debug_printf("pop stack\n");
990 done_pipe(ctx, PIPE_SEQ);
992 old->child->group = ctx->list_head;
993 *ctx = *old; /* physical copy */
1003 /* normal return is 0.
1004 * Syntax or xglob errors return 1. */
1005 static int done_word(o_string *dest, struct p_context *ctx) {
1006 struct child_prog *child = ctx->child;
1010 debug_printf("done_word: %s %p\n", dest->data, child);
1011 if (dest->length == 0 && !dest->nonnull) {
1012 debug_printf(" true null, ignored\n");
1017 return 1; /* syntax error, groups and arglists don't mix */
1019 if (!child->argv && (ctx->type & FLAG_PARSE_SEMICOLON)) {
1020 debug_printf("checking %s for reserved-ness\n", dest->data);
1021 if (reserved_word(dest, ctx))
1022 return ctx->w == RES_SNTX;
1024 for (cnt = 1, s = dest->data; s && *s; s++) {
1032 if (child->argv == NULL) {
1035 argc = ++child->argc;
1036 child->argv = realloc(child->argv, (argc + 1) * sizeof(*child->argv));
1037 if (child->argv == NULL)
1039 child->argv[argc - 1] = str;
1040 child->argv[argc] = NULL;
1041 for (s = dest->data; s && *s; s++, str++) {
1051 if (ctx->w == RES_FOR) {
1052 done_word(dest, ctx);
1053 done_pipe(ctx, PIPE_SEQ);
1058 /* The only possible error here is out of memory, in which case
1060 static int done_command(struct p_context *ctx) {
1061 /* The child is really already in the pipe structure, so
1062 * advance the pipe counter and make a new, null child.
1063 * Only real trickiness here is that the uncommitted
1064 * child structure, to which ctx->child points, is not
1065 * counted in pi->num_progs. */
1066 struct pipe *pi = ctx->pipe;
1067 struct child_prog *prog = ctx->child;
1069 if (prog && prog->group == NULL && prog->argv == NULL) {
1070 debug_printf("done_command: skipping null command\n");
1074 debug_printf("done_command: num_progs incremented to %d\n",
1077 debug_printf("done_command: initializing\n");
1079 pi->progs = xrealloc(pi->progs, sizeof(*pi->progs) * (pi->num_progs + 1));
1081 prog = pi->progs + pi->num_progs;
1086 prog->type = ctx->type;
1088 /* but ctx->pipe and ctx->list_head remain unchanged */
1092 static int done_pipe(struct p_context *ctx, pipe_style type) {
1094 done_command(ctx); /* implicit closure of previous command */
1095 debug_printf("done_pipe, type %d\n", type);
1096 ctx->pipe->followup = type;
1097 ctx->pipe->r_mode = ctx->w;
1099 ctx->pipe->next = new_p;
1102 done_command(ctx); /* set up new pipe to accept commands */
1106 /* basically useful version until someone wants to get fancier,
1107 * see the bash man page under "Parameter Expansion" */
1108 static char *lookup_param(char *src) {
1116 p = get_local_var(src);
1121 static char *get_dollar_var(char ch) {
1122 static char buf[40];
1127 sprintf(buf, "%u", (unsigned int) last_return_code);
1135 /* return code: 0 for OK, 1 for syntax error */
1136 static int handle_dollar(o_string *dest, struct p_context *ctx,
1137 struct in_str *input) {
1139 int ch = input->peek(input); /* first character after the $ */
1140 debug_printf("handle_dollar: ch=%c\n", ch);
1142 b_addchr(dest, SPECIAL_VAR_SYMBOL);
1144 while (ch = b_peek(input), isalnum(ch) || ch == '_') {
1148 b_addchr(dest, SPECIAL_VAR_SYMBOL);
1153 b_addchr(dest, SPECIAL_VAR_SYMBOL);
1154 b_addchr(dest, '$');
1155 b_addchr(dest, '?');
1156 b_addchr(dest, SPECIAL_VAR_SYMBOL);
1160 b_addchr(dest, SPECIAL_VAR_SYMBOL);
1163 /* XXX maybe someone will try to escape the '}' */
1164 while (ch = b_getch(input), ch != EOF && ch != '}') {
1171 b_addchr(dest, SPECIAL_VAR_SYMBOL);
1174 b_addqchr(dest, '$', dest->quote);
1176 /* Eat the character if the flag was set. If the compiler
1177 * is smart enough, we could substitute "b_getch(input);"
1178 * for all the "advance = 1;" above, and also end up with
1179 * a nice size-optimized program. Hah! That'll be the day.
1186 /* return code is 0 for normal exit, 1 for syntax error */
1187 int parse_stream(o_string *dest, struct p_context *ctx, struct in_str *input,
1192 /* Only double-quote state is handled in the state variable dest->quote.
1193 * A single-quote triggers a bypass of the main loop until its mate is
1194 * found. When recursing, quote state is passed in via dest->quote. */
1196 debug_printf("parse_stream, end_trigger=%d\n", end_trigger);
1197 while ((ch = b_getch(input)) != EOF) {
1199 if (input->__promptme == 0)
1202 next = (ch == '\n') ? 0 : b_peek(input);
1204 debug_printf("parse_stream: ch=%c (%d) m=%d quote=%d - %c\n",
1205 ch >= ' ' ? ch : '.', ch, m, dest->quote,
1206 ctx->stack == NULL ? '*' : '.');
1208 if (m == 0 || ((m == 1 || m == 2) && dest->quote)) {
1209 b_addqchr(dest, ch, dest->quote);
1211 if (m == 2) { /* unquoted IFS */
1212 if (done_word(dest, ctx)) {
1215 /* If we aren't performing a substitution, treat a newline as a
1216 * command separator. */
1217 if (end_trigger != '\0' && ch == '\n')
1218 done_pipe(ctx, PIPE_SEQ);
1220 if (ch == end_trigger && !dest->quote && ctx->w == RES_NONE) {
1221 debug_printf("leaving parse_stream (triggered)\n");
1227 if (dest->length == 0 && !dest->quote) {
1228 while (ch = b_peek(input), ch != EOF && ch != '\n') {
1232 b_addqchr(dest, ch, dest->quote);
1240 b_addqchr(dest, '\\', dest->quote);
1241 b_addqchr(dest, b_getch(input), dest->quote);
1244 if (handle_dollar(dest, ctx, input) != 0)
1249 while (ch = b_getch(input), ch != EOF && ch != '\'') {
1250 if (input->__promptme == 0)
1261 dest->quote = !dest->quote;
1264 done_word(dest, ctx);
1265 done_pipe(ctx, PIPE_SEQ);
1268 done_word(dest, ctx);
1271 done_pipe(ctx, PIPE_AND);
1278 done_word(dest, ctx);
1281 done_pipe(ctx, PIPE_OR);
1283 /* we could pick up a file descriptor choice here
1284 * with redirect_opt_num(), but bash doesn't do it.
1285 * "echo foo 2| cat" yields "foo 2". */
1291 syntax(); /* this is really an internal logic error */
1296 /* complain if quote? No, maybe we just finished a command substitution
1297 * that was quoted. Example:
1298 * $ echo "`cat foo` plus more"
1299 * and we just got the EOF generated by the subshell that ran "cat foo"
1300 * The only real complaint is if we got an EOF when end_trigger != '\0',
1301 * that is, we were really supposed to get end_trigger, and never got
1302 * one before the EOF. Can't use the standard "syntax error" return code,
1303 * so that parse_stream_outer can distinguish the EOF and exit smoothly. */
1304 debug_printf("leaving parse_stream (EOF)\n");
1305 if (end_trigger != '\0')
1310 void mapset(const unsigned char *set, int code) {
1311 const unsigned char *s;
1312 for (s = set; *s; s++)
1316 void update_ifs_map(void) {
1317 /* char *ifs and char map[256] are both globals. */
1318 ifs = (uchar *) getenv("IFS");
1320 ifs = (uchar *) " \t\n";
1321 /* Precompute a list of 'flow through' behavior so it can be treated
1322 * quickly up front. Computation is necessary because of IFS.
1323 * Special case handling of IFS == " \t\n" is not implemented.
1324 * The map[] array only really needs two bits each, and on most machines
1325 * that would be faster because of the reduced L1 cache footprint.
1327 memset(map, 0, sizeof(map)); /* most characters flow through always */
1328 mapset((uchar *) "\\$'\"", 3); /* never flow through */
1329 mapset((uchar *) ";&|#", 1); /* flow through if quoted */
1330 mapset(ifs, 2); /* also flow through if quoted */
1333 /* most recursion does not come through here, the exeception is
1334 * from builtin_source() */
1335 int parse_stream_outer(struct in_str *inp, int flag) {
1337 struct p_context ctx;
1338 o_string temp = NULL_O_STRING;
1343 initialize_context(&ctx);
1345 if (!(flag & FLAG_PARSE_SEMICOLON) || (flag & FLAG_REPARSING))
1346 mapset((uchar *) ";$&|", 0);
1347 inp->promptmode = 1;
1348 rcode = parse_stream(&temp, &ctx, inp, '\n');
1351 if (rcode != 1 && ctx.old_flag != 0) {
1355 if (rcode != 1 && ctx.old_flag == 0) {
1356 done_word(&temp, &ctx);
1357 done_pipe(&ctx, PIPE_SEQ);
1358 code = run_list(ctx.list_head);
1359 if (code == -2) { /* exit */
1362 /* XXX hackish way to not allow exit from main loop */
1363 if (inp->peek == file_peek) {
1364 printf_err("exit not allowed from main input shell!\n");
1372 if (ctx.old_flag != 0) {
1376 if (inp->__promptme == 0)
1377 printf("<INTERRUPT>\n");
1378 inp->__promptme = 1;
1382 free_pipe_list(ctx.list_head, 0);
1385 } while (rcode != -1 && !(flag & FLAG_EXIT_FROM_LOOP)); /* loop on syntax errors, return on EOF */
1387 return (code != 0) ? 1 : 0;
1390 int parse_string_outer(char *s, int flag) {
1391 struct in_str input;
1398 if (!(p = strchr(s, '\n')) || *++p) {
1399 p = xmalloc(strlen(s) + 2);
1402 setup_string_in_str(&input, p);
1403 rcode = parse_stream_outer(&input, flag);
1407 setup_string_in_str(&input, s);
1408 return parse_stream_outer(&input, flag);
1412 int parse_file_outer(void) {
1414 struct in_str input;
1415 setup_file_in_str(&input);
1416 rcode = parse_stream_outer(&input, FLAG_PARSE_SEMICOLON);
1420 static void u_boot_hush_reloc(void) {
1422 struct reserved_combo *r;
1424 for (r = reserved_list; r < reserved_list + NRES; r++) {
1425 addr = (ulong) (r->literal) + gd->reloc_off;
1426 r->literal = (char *) addr;
1430 int u_boot_hush_start(void) {
1431 if (top_vars == NULL) {
1432 top_vars = malloc(sizeof(struct variables));
1433 top_vars->name = "HUSH_VERSION";
1434 top_vars->value = "0.01";
1436 top_vars->flg_export = 0;
1437 top_vars->flg_read_only = 1;
1438 u_boot_hush_reloc();
1443 static void *xmalloc(size_t size) {
1446 if (!(p = malloc(size))) {
1447 printf_err("memory not allocated!\n");
1454 static void *xrealloc(void *ptr, size_t size) {
1457 if (!(p = realloc(ptr, size))) {
1458 printf_err("memory not allocated!\n");
1465 static char *insert_var_value(char *inp) {
1466 int res_str_len = 0;
1469 char *p, *p1, *res_str = NULL;
1471 while ((p = strchr(inp, SPECIAL_VAR_SYMBOL))) {
1474 res_str = xrealloc(res_str, (res_str_len + len));
1475 strncpy((res_str + res_str_len), inp, len);
1479 p = strchr(inp, SPECIAL_VAR_SYMBOL);
1481 if ((p1 = lookup_param(inp))) {
1482 len = res_str_len + strlen(p1);
1483 res_str = xrealloc(res_str, (1 + len));
1484 strcpy((res_str + res_str_len), p1);
1487 *p = SPECIAL_VAR_SYMBOL;
1492 res_str = xrealloc(res_str, (1 + res_str_len + strlen(inp)));
1493 strcpy((res_str + res_str_len), inp);
1494 while ((p = strchr(res_str, '\n'))) {
1498 return (res_str == NULL) ? inp : res_str;
1501 static char **make_list_in(char **inp, char *name) {
1503 int name_len = strlen(name);
1508 /* create list of variable values */
1509 list = xmalloc(sizeof(*list));
1510 for (i = 0; inp[i]; i++) {
1511 p3 = insert_var_value(inp[i]);
1518 if ((p2 = strchr(p1, ' '))) {
1524 /* we use n + 2 in realloc for list,because we add
1525 * new element and then we will add NULL element */
1526 list = xrealloc(list, sizeof(*list) * (n + 2));
1527 list[n] = xmalloc(2 + name_len + len);
1528 strcpy(list[n], name);
1529 strcat(list[n], "=");
1530 strncat(list[n], p1, len);
1531 list[n++][name_len + len + 1] = '\0';
1541 /* Make new string for parser */
1542 static char * make_string(char ** inp) {
1548 for (n = 0; inp[n]; n++) {
1549 p = insert_var_value(inp[n]);
1550 str = xrealloc(str, (len + strlen(p)));
1557 len = strlen(str) + 3;
1562 *(str + len) = '\n';
1563 *(str + len + 1) = '\0';
1567 int do_true(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
1572 U_BOOT_CMD(true, 1, 1, do_true, "return true\n", NULL);
1574 #endif /* CFG_HUSH_PARSER */
1575 /****************************************************************************/