1 /* vi: set sw=8 ts=8: */
3 * hush.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
28 /** @page shell_notes Simple Shell Environment: Hush
30 * @par Notes from the source:
32 * Intended to follow the original Thompson and Ritchie "small and simple
33 * is beautiful" philosophy, which incidentally is a good match to
36 * There are two big (and related) architecture differences between
37 * this parser and the lash parser. One is that this version is
38 * actually designed from the ground up to understand nearly all
39 * of the Bourne grammar. The second, consequential change is that
40 * the parser and input reader have been turned inside out. Now,
41 * the parser is in control, and asks for input as needed. The old
42 * way had the input reader in control, and it asked for parsing to
43 * take place as needed. The new way makes it much easier to properly
44 * handle the recursion implicit in the various substitutions, especially
45 * across continuation lines.
47 * Bash grammar not implemented: (how many of these were in original sh?)
48 * - $@ (those sure look like weird quoting rules)
50 * - ! negation operator for pipes
51 * - &> and >& redirection of stdout+stderr
54 * - fancy forms of Parameter Expansion
56 * - Arithmetic Expansion
57 * - <(list) and >(list) Process Substitution
58 * - reserved words: case, esac, select, function
59 * - Here Documents ( << word )
63 * - job handling woefully incomplete and buggy
64 * - reserved word execution woefully incomplete and buggy
67 * - port selected bugfixes from post-0.49 busybox lash - done?
68 * - finish implementing reserved words: for, while, until, do, done
69 * - change { and } from special chars to reserved words
70 * - builtins: break, continue, eval, return, set, trap, ulimit
72 * - handle children going into background
73 * - clean up recognition of null pipes
74 * - check setting of global_argc and global_argv
75 * - control-C handling, probably with longjmp
76 * - follow IFS rules more precisely, including update semantics
77 * - figure out what to do with backslash-newline
78 * - explain why we use signal instead of sigaction
79 * - propagate syntax errors, die on resource errors?
80 * - continuation lines, both explicit and implicit - done?
81 * - memory leak finding and plugging - done?
82 * - more testing, especially quoting rules and redirection
83 * - document how quoting rules not precisely followed for variable assignments
84 * - maybe change map[] to use 2-bit entries
85 * - (eventually) remove all the printf's
87 * Things that do _not_ work in this environment:
89 * - redirecting (stdout to a file for example)
92 * Enable the "Hush parser" in "General Settings", "Select your shell" to
93 * get the new console feeling.
98 * This program is free software; you can redistribute it and/or modify
99 * it under the terms of the GNU General Public License as published by
100 * the Free Software Foundation; either version 2 of the License, or
101 * (at your option) any later version.
103 * This program is distributed in the hope that it will be useful,
104 * but WITHOUT ANY WARRANTY; without even the implied warranty of
105 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
106 * General Public License for more details.
108 * You should have received a copy of the GNU General Public License
109 * along with this program; if not, write to the Free Software
110 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
112 #include <malloc.h> /* malloc, free, realloc*/
114 #include <linux/ctype.h> /* isalpha, isdigit */
115 #include <common.h> /* readline */
117 #include <environment.h>
118 #include <command.h> /* find_cmd */
126 extern int do_bootd (cmd_tbl_t
*cmdtp
, int flag
, int argc
, char *argv
[]); /* do_bootd */
127 #define SPECIAL_VAR_SYMBOL 03
130 #define EXIT_SUCCESS 0
132 #define syntax() syntax_err()
133 #define xstrdup strdup
134 #define error_msg printf
143 /* might eventually control execution */
160 #define FLAG_END (1<<RES_NONE)
161 #define FLAG_IF (1<<RES_IF)
162 #define FLAG_THEN (1<<RES_THEN)
163 #define FLAG_ELIF (1<<RES_ELIF)
164 #define FLAG_ELSE (1<<RES_ELSE)
165 #define FLAG_FI (1<<RES_FI)
166 #define FLAG_FOR (1<<RES_FOR)
167 #define FLAG_WHILE (1<<RES_WHILE)
168 #define FLAG_UNTIL (1<<RES_UNTIL)
169 #define FLAG_DO (1<<RES_DO)
170 #define FLAG_DONE (1<<RES_DONE)
171 #define FLAG_IN (1<<RES_IN)
172 #define FLAG_START (1<<RES_XXXX)
174 /* This holds pointers to the various results of parsing */
176 struct child_prog
*child
;
177 struct pipe
*list_head
;
180 int old_flag
; /* for figuring out valid reserved words */
181 struct p_context
*stack
;
182 int type
; /* define type of parser : ";$" common or special symbol */
183 /* How about quoting status? */
186 unsigned int global_argc
;
191 char **argv
; /* program name and arguments */
192 int argc
; /* number of program arguments */
193 struct pipe
*group
; /* if non-NULL, first in group or subshell */
194 int sp
; /* number of SPECIAL_VAR_SYMBOL */
196 glob_t glob_result
; /* result of parameter globbing */
200 int num_progs
; /* total number of programs in job */
201 struct child_prog
*progs
; /* array of commands in pipe */
202 struct pipe
*next
; /* to track background commands */
203 pipe_style followup
; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */
204 reserved_style r_mode
; /* supports if, for, while, until */
208 static char console_buffer
[CONFIG_CBSIZE
]; /* console I/O buffer */
210 /* globals, connect us to the outside world
211 * the first three support $?, $#, and $1 */
212 static unsigned int last_return_code
;
214 /* "globals" within this file */
216 static char map
[256];
218 #define B_CHUNK (100)
228 #define NULL_O_STRING {NULL,0,0,0,0}
229 /* used for initialization:
230 o_string foo = NULL_O_STRING; */
232 /* I can almost use ordinary FILE *. Is open_memstream() universally
233 * available? Where is it documented? */
238 int (*get
) (struct in_str
*);
239 int (*peek
) (struct in_str
*);
241 #define b_getch(input) ((input)->get(input))
242 #define b_peek(input) ((input)->peek(input))
245 #define final_printf debug
247 static void syntax_err(void) {
248 printf("syntax error\n");
251 /* o_string manipulation: */
252 static int b_check_space(o_string
*o
, int len
);
253 static int b_addchr(o_string
*o
, int ch
);
254 static void b_reset(o_string
*o
);
255 static int b_addqchr(o_string
*o
, int ch
, int quote
);
256 /* in_str manipulations: */
257 static int static_get(struct in_str
*i
);
258 static int static_peek(struct in_str
*i
);
259 static int file_get(struct in_str
*i
);
260 static int file_peek(struct in_str
*i
);
261 static void setup_file_in_str(struct in_str
*i
);
262 static void setup_string_in_str(struct in_str
*i
, const char *s
);
263 /* "run" the final data structures: */
264 static int free_pipe_list(struct pipe
*head
, int indent
);
265 static int free_pipe(struct pipe
*pi
, int indent
);
266 /* really run the final data structures: */
267 static int run_list_real(struct pipe
*pi
);
268 static int run_pipe_real(struct pipe
*pi
);
269 /* extended glob support: */
270 /* variable assignment: */
271 static int is_assignment(const char *s
);
272 /* data structure manipulation: */
273 static void initialize_context(struct p_context
*ctx
);
274 static int done_word(o_string
*dest
, struct p_context
*ctx
);
275 static int done_command(struct p_context
*ctx
);
276 static int done_pipe(struct p_context
*ctx
, pipe_style type
);
277 /* primary string parsing: */
278 static const char *lookup_param(char *src
);
279 static char *make_string(char **inp
);
280 static int handle_dollar(o_string
*dest
, struct p_context
*ctx
, struct in_str
*input
);
281 static int parse_stream(o_string
*dest
, struct p_context
*ctx
, struct in_str
*input0
, int end_trigger
);
283 static int parse_stream_outer(struct p_context
*ctx
, struct in_str
*inp
, int flag
);
285 static int parse_string_outer(struct p_context
*ctx
, const char *s
, int flag
);
286 /* local variable support */
287 static char **make_list_in(char **inp
, char *name
);
288 static char *insert_var_value(char *inp
);
289 static int set_local_var(const char *s
, int flg_export
);
290 static int execute_script(const char *path
, int argc
, char *argv
[]);
291 static int source_script(const char *path
, int argc
, char *argv
[]);
293 static int b_check_space(o_string
*o
, int len
)
295 /* It would be easy to drop a more restrictive policy
296 * in here, such as setting a maximum string length */
297 if (o
->length
+ len
> o
->maxlen
) {
298 char *old_data
= o
->data
;
299 /* assert (data == NULL || o->maxlen != 0); */
300 o
->maxlen
+= max(2*len
, B_CHUNK
);
301 o
->data
= realloc(o
->data
, 1 + o
->maxlen
);
302 if (o
->data
== NULL
) {
306 return o
->data
== NULL
;
309 static int b_addchr(o_string
*o
, int ch
)
311 debug("b_addchr: %c %d %p\n", ch
, o
->length
, o
);
312 if (b_check_space(o
, 1))
314 o
->data
[o
->length
] = ch
;
316 o
->data
[o
->length
] = '\0';
320 static void b_reset(o_string
*o
)
324 if (o
->data
!= NULL
) *o
->data
= '\0';
327 static void b_free(o_string
*o
)
335 /* My analysis of quoting semantics tells me that state information
336 * is associated with a destination, not a source.
338 static int b_addqchr(o_string
*o
, int ch
, int quote
)
340 if (quote
&& strchr("*?[",ch
)) {
342 rc
= b_addchr(o
, '\\');
346 return b_addchr(o
, ch
);
349 /* belongs in utility.c */
350 char *simple_itoa(unsigned int i
)
352 /* 21 digits plus null terminator, good for 64-bit or smaller ints */
353 static char local
[22];
354 char *p
= &local
[21];
363 static int b_adduint(o_string
*o
, unsigned int i
)
366 char *p
= simple_itoa(i
);
367 /* no escape checking necessary */
370 } while (r
==0 && *p
);
375 static int static_get(struct in_str
*i
)
384 static int static_peek(struct in_str
*i
)
390 static char *getprompt(void)
395 prompt
= xmalloc(PATH_MAX
+ strlen(CONFIG_PROMPT
) + 1);
397 sprintf(prompt
, "%s%s ", CONFIG_PROMPT
, getcwd());
401 static void get_user_input(struct in_str
*i
)
404 static char the_command
[CONFIG_CBSIZE
];
407 if (i
->promptmode
== 1) {
408 n
= readline(getprompt(), console_buffer
, CONFIG_CBSIZE
);
410 n
= readline(CONFIG_PROMPT_HUSH_PS2
, console_buffer
, CONFIG_CBSIZE
);
417 console_buffer
[n
] = '\n';
418 console_buffer
[n
+1]= '\0';
419 if (i
->promptmode
== 1) {
420 strcpy(the_command
,console_buffer
);
423 if (console_buffer
[0] != '\n') {
424 if (strlen(the_command
) + strlen(console_buffer
)
426 n
= strlen(the_command
);
427 the_command
[n
-1] = ' ';
428 strcpy(&the_command
[n
],console_buffer
);
431 the_command
[0] = '\n';
432 the_command
[1] = '\0';
435 if (i
->__promptme
== 0) {
436 the_command
[0] = '\n';
437 the_command
[1] = '\0';
439 i
->p
= console_buffer
;
443 /* This is the magic location that prints prompts
444 * and gets data back from the user */
445 static int file_get(struct in_str
*i
)
450 /* If there is data waiting, eat it up */
454 /* need to double check i->file because we might be doing something
455 * more complicated by now, like sourcing or substituting. */
456 while(! i
->p
|| strlen(i
->p
)==0 ) {
463 debug("b_getch: got a %d\n", ch
);
468 /* All the callers guarantee this routine will never be
469 * used right after a newline, so prompting is not needed.
471 static int file_peek(struct in_str
*i
)
476 static void setup_file_in_str(struct in_str
*i
)
485 static void setup_string_in_str(struct in_str
*i
, const char *s
)
487 i
->peek
= static_peek
;
495 /* run_pipe_real() starts all the jobs, but doesn't wait for anything
496 * to finish. See checkjobs().
498 * return code is normally -1, when the caller has to wait for children
499 * to finish to determine the exit status of the pipe. If the pipe
500 * is a simple builtin command, however, the action is done by the
501 * time run_pipe_real returns, and the exit code is provided as the
504 * The input of the pipe is always stdin, the output is always
505 * stdout. The outpipe[] mechanism in BusyBox-0.48 lash is bogus,
506 * because it tries to avoid running the command substitution in
507 * subshell, when that is in fact necessary. The subshell process
508 * now has its stdout directed to the input of the appropriate pipe,
509 * so this routine is noticeably simpler.
511 static int run_pipe_real(struct pipe
*pi
)
515 struct child_prog
*child
;
521 /* Avoid longjmp clobbering */
529 /* Check if this is a simple builtin (not part of a pipe).
530 * Builtins within pipes have to fork anyway, and are handled in
531 * pseudo_exec. "echo foo | read bar" doesn't work on bash, either.
533 if (pi
->num_progs
== 1)
534 child
= & (pi
->progs
[0]);
535 if (pi
->num_progs
== 1 && child
->group
) {
537 debug("non-subshell grouping\n");
538 rcode
= run_list_real(child
->group
);
540 } else if (pi
->num_progs
== 1 && pi
->progs
[0].argv
!= NULL
) {
541 for (i
=0; is_assignment(child
->argv
[i
]); i
++) { /* nothing */ }
542 if (i
!=0 && child
->argv
[i
]==NULL
) {
543 /* assignments, but no command: set the local environment */
544 for (i
=0; child
->argv
[i
]!=NULL
; i
++) {
546 /* Ok, this case is tricky. We have to decide if this is a
547 * local variable, or an already exported variable. If it is
548 * already exported, we have to export the new value. If it is
549 * not exported, we need only set this as a local variable.
550 * This junk is all to decide whether or not to export this
554 name
= xstrdup(child
->argv
[i
]);
555 debug("Local environment set: %s\n", name
);
556 value
= strchr(name
, '=');
560 p
= insert_var_value(child
->argv
[i
]);
561 set_local_var(p
, export_me
);
562 if (p
!= child
->argv
[i
])
565 return EXIT_SUCCESS
; /* don't worry about errors in set_local_var() yet */
567 for (i
= 0; is_assignment(child
->argv
[i
]); i
++) {
568 p
= insert_var_value(child
->argv
[i
]);
570 if (p
!= child
->argv
[i
]) {
577 struct p_context ctx
;
578 str
= make_string((child
->argv
+ i
));
579 parse_string_outer(&ctx
, str
, FLAG_EXIT_FROM_LOOP
| FLAG_REPARSING
);
581 return last_return_code
;
584 if (strchr(child
->argv
[i
], '/')) {
585 return execute_script(child
->argv
[i
], child
->argc
-i
, &child
->argv
[i
]);
587 if ((path
= find_execable(child
->argv
[i
]))) {
588 ret
= execute_script(path
, child
->argc
-i
, &child
->argv
[i
]);
592 /* Look up command in command table */
593 if ((cmdtp
= find_cmd(child
->argv
[i
]))) {
596 /* found - check max args */
597 if ((child
->argc
- i
) > cmdtp
->maxargs
) {
598 printf ("Usage:\n%s\n", cmdtp
->usage
);
601 /* OK - call function to do the command */
602 rcode
= cmdtp
->cmd(cmdtp
, child
->argc
-i
, &child
->argv
[i
]);
606 printf ("Unknown command '%s' - try 'help'\n", child
->argv
[i
]);
607 return -1; /* give up after bad command */
613 static int run_list_real(struct pipe
*pi
)
615 char *save_name
= NULL
;
617 char **save_list
= NULL
;
620 int rcode
=0, flag_skip
=1;
621 int flag_restore
= 0;
622 int if_code
=0, next_if_code
=0; /* need double-buffer to handle elif */
623 reserved_style rmode
, skip_more_in_this_rmode
=RES_XXXX
;
624 /* check syntax for "for" */
625 for (rpipe
= pi
; rpipe
; rpipe
= rpipe
->next
) {
626 if ((rpipe
->r_mode
== RES_IN
||
627 rpipe
->r_mode
== RES_FOR
) &&
628 (rpipe
->next
== NULL
)) {
632 if ((rpipe
->r_mode
== RES_IN
&&
633 (rpipe
->next
->r_mode
== RES_IN
&&
634 rpipe
->next
->progs
->argv
!= NULL
))||
635 (rpipe
->r_mode
== RES_FOR
&&
636 rpipe
->next
->r_mode
!= RES_IN
)) {
641 for (; pi
; pi
= (flag_restore
!= 0) ? rpipe
: pi
->next
) {
642 if (pi
->r_mode
== RES_WHILE
|| pi
->r_mode
== RES_UNTIL
||
643 pi
->r_mode
== RES_FOR
) {
654 debug("rmode=%d if_code=%d next_if_code=%d skip_more=%d\n", rmode
, if_code
, next_if_code
, skip_more_in_this_rmode
);
655 if (rmode
== skip_more_in_this_rmode
&& flag_skip
) {
656 if (pi
->followup
== PIPE_SEQ
) flag_skip
=0;
660 skip_more_in_this_rmode
= RES_XXXX
;
661 if (rmode
== RES_THEN
|| rmode
== RES_ELSE
)
662 if_code
= next_if_code
;
663 if (rmode
== RES_THEN
&& if_code
)
665 if (rmode
== RES_ELSE
&& !if_code
)
667 if (rmode
== RES_ELIF
&& !if_code
)
669 if (rmode
== RES_FOR
&& pi
->num_progs
) {
671 /* if no variable values after "in" we skip "for" */
672 if (!pi
->next
->progs
->argv
)
674 /* create list of variable values */
675 list
= make_list_in(pi
->next
->progs
->argv
,
678 save_name
= pi
->progs
->argv
[0];
679 pi
->progs
->argv
[0] = NULL
;
683 free(pi
->progs
->argv
[0]);
687 pi
->progs
->argv
[0] = save_name
;
690 /* insert new value from list for variable */
691 if (pi
->progs
->argv
[0])
692 free(pi
->progs
->argv
[0]);
693 pi
->progs
->argv
[0] = *list
++;
698 if (rmode
== RES_DO
) {
702 if ((rmode
== RES_DONE
)) {
709 if (pi
->num_progs
== 0)
711 rcode
= run_pipe_real(pi
);
712 debug("run_pipe_real returned %d\n",rcode
);
714 last_return_code
= -rcode
- 2;
715 return -2; /* exit */
717 last_return_code
=rcode
;
718 if ( rmode
== RES_IF
|| rmode
== RES_ELIF
)
719 next_if_code
=rcode
; /* can be overwritten a number of times */
720 if (rmode
== RES_WHILE
)
721 flag_rep
= !last_return_code
;
722 if (rmode
== RES_UNTIL
)
723 flag_rep
= last_return_code
;
724 if ( (rcode
==EXIT_SUCCESS
&& pi
->followup
==PIPE_OR
) ||
725 (rcode
!=EXIT_SUCCESS
&& pi
->followup
==PIPE_AND
) )
726 skip_more_in_this_rmode
=rmode
;
732 /* broken, of course, but OK for testing */
733 static char *indenter(int i
)
735 static char blanks
[]=" ";
736 return &blanks
[sizeof(blanks
)-i
-1];
740 /* return code is the exit status of the pipe */
741 static int free_pipe(struct pipe
*pi
, int indent
)
744 struct child_prog
*child
;
745 int a
, i
, ret_code
=0;
747 for (i
=0; i
<pi
->num_progs
; i
++) {
748 child
= &pi
->progs
[i
];
749 final_printf("%s command %d:\n",indenter(indent
),i
);
751 for (a
=0,p
=child
->argv
; *p
; a
++,p
++) {
752 final_printf("%s argv[%d] = %s\n",indenter(indent
),a
,*p
);
754 globfree(&child
->glob_result
);
756 } else if (child
->group
) {
757 ret_code
= free_pipe_list(child
->group
,indent
+3);
758 final_printf("%s end group\n",indenter(indent
));
760 final_printf("%s (nil)\n",indenter(indent
));
763 free(pi
->progs
); /* children are an array, they get freed all at once */
768 static int free_pipe_list(struct pipe
*head
, int indent
)
770 int rcode
=0; /* if list has no members */
771 struct pipe
*pi
, *next
;
772 for (pi
=head
; pi
; pi
=next
) {
773 final_printf("%s pipe reserved mode %d\n", indenter(indent
), pi
->r_mode
);
774 rcode
= free_pipe(pi
, indent
);
775 final_printf("%s pipe followup code %d\n", indenter(indent
), pi
->followup
);
783 /* The API for glob is arguably broken. This routine pushes a non-matching
784 * string into the output structure, removing non-backslashed backslashes.
785 * If someone can prove me wrong, by performing this function within the
786 * original glob(3) api, feel free to rewrite this routine into oblivion.
787 * Return code (0 vs. GLOB_NOSPACE) matches glob(3).
788 * XXX broken if the last character is '\\', check that before calling.
790 static int globhack(const char *src
, int flags
, glob_t
*pglob
)
795 for (cnt
=1, s
=src
; s
&& *s
; s
++) {
800 if (!(flags
& GLOB_APPEND
)) {
801 pglob
->gl_pathv
= NULL
;
805 pathc
= ++pglob
->gl_pathc
;
806 pglob
->gl_pathv
= xrealloc(pglob
->gl_pathv
, (pathc
+1)*sizeof(*pglob
->gl_pathv
));
807 pglob
->gl_pathv
[pathc
-1] = dest
;
808 pglob
->gl_pathv
[pathc
] = NULL
;
809 for (s
=src
; s
&& *s
; s
++, dest
++) {
817 /* XXX broken if the last character is '\\', check that before calling */
818 static int glob_needed(const char *s
)
823 if (strchr("*[?",*s
))
830 static int xglob(o_string
*dest
, int flags
, glob_t
*pglob
)
834 /* short-circuit for null word */
835 /* we can code this better when the debug's are gone */
836 if (dest
->length
== 0) {
838 /* bash man page calls this an "explicit" null */
839 gr
= globhack(dest
->data
, flags
, pglob
);
840 debug("globhack returned %d\n",gr
);
844 } else if (glob_needed(dest
->data
)) {
845 gr
= glob(dest
->data
, flags
, NULL
, pglob
);
846 debug("glob returned %d\n",gr
);
847 if (gr
== GLOB_NOMATCH
) {
848 /* quote removal, or more accurately, backslash removal */
849 gr
= globhack(dest
->data
, flags
, pglob
);
850 debug("globhack returned %d\n",gr
);
853 gr
= globhack(dest
->data
, flags
, pglob
);
854 debug("globhack returned %d\n",gr
);
856 if (gr
!= 0) { /* GLOB_ABORTED ? */
857 error_msg("glob(3) error %d",gr
);
859 /* globprint(glob_target); */
863 /* Select which version we will use */
864 static int run_list(struct pipe
*pi
)
868 rcode
= run_list_real(pi
);
870 /* free_pipe_list has the side effect of clearing memory
871 * In the long run that function can be merged with run_list_real,
872 * but doing that now would hobble the debugging effort. */
873 free_pipe_list(pi
,0);
877 static char *get_dollar_var(char ch
);
879 /* This is used to set local shell variables
880 flg_export==0 if only local (not exporting) variable
881 flg_export==1 if "new" exporting environ
882 flg_export>1 if current startup environ (not call putenv()) */
883 static int set_local_var(const char *s
, int flg_export
)
888 /* might be possible! */
894 /* Assume when we enter this function that we are already in
895 * NAME=VALUE format. So the first order of business is to
896 * split 's' on the '=' into 'name' and 'value' */
897 value
= strchr(name
, '=');
898 if (value
==0 && ++value
==0) {
904 ret
= setenv(name
, value
);
912 static int is_assignment(const char *s
)
920 while(isalnum(*s
) || *s
=='_' || *s
=='.')
926 static struct pipe
*new_pipe(void) {
927 return (struct pipe
*)xzalloc(sizeof(struct pipe
));
930 static void initialize_context(struct p_context
*ctx
)
934 ctx
->list_head
=new_pipe();
935 ctx
->pipe
=ctx
->list_head
;
939 done_command(ctx
); /* creates the memory for working child */
942 /* normal return is 0
943 * if a reserved word is found, and processed, return 1
944 * should handle if, then, elif, else, fi, for, while, until, do, done.
945 * case, function, and select are obnoxious, save those for later.
947 struct reserved_combo
{
952 /* Mostly a list of accepted follow-up reserved words.
953 * FLAG_END means we are done with the sequence, and are ready
954 * to turn the compound list into a command.
955 * FLAG_START means the word must start a new compound list.
957 static struct reserved_combo reserved_list
[] = {
958 { "if", RES_IF
, FLAG_THEN
| FLAG_START
},
959 { "then", RES_THEN
, FLAG_ELIF
| FLAG_ELSE
| FLAG_FI
},
960 { "elif", RES_ELIF
, FLAG_THEN
},
961 { "else", RES_ELSE
, FLAG_FI
},
962 { "fi", RES_FI
, FLAG_END
},
963 { "for", RES_FOR
, FLAG_IN
| FLAG_START
},
964 { "while", RES_WHILE
, FLAG_DO
| FLAG_START
},
965 { "until", RES_UNTIL
, FLAG_DO
| FLAG_START
},
966 { "in", RES_IN
, FLAG_DO
},
967 { "do", RES_DO
, FLAG_DONE
},
968 { "done", RES_DONE
, FLAG_END
}
970 #define NRES (sizeof(reserved_list)/sizeof(struct reserved_combo))
972 static int reserved_word(o_string
*dest
, struct p_context
*ctx
)
974 struct reserved_combo
*r
;
975 for (r
=reserved_list
;
976 r
<reserved_list
+NRES
; r
++) {
977 if (strcmp(dest
->data
, r
->literal
) == 0) {
978 debug("found reserved word %s, code %d\n",r
->literal
,r
->code
);
979 if (r
->flag
& FLAG_START
) {
980 struct p_context
*new = xmalloc(sizeof(struct p_context
));
981 debug("push stack\n");
982 if (ctx
->w
== RES_IN
|| ctx
->w
== RES_FOR
) {
989 *new = *ctx
; /* physical copy */
990 initialize_context(ctx
);
992 } else if ( ctx
->w
== RES_NONE
|| ! (ctx
->old_flag
& (1<<r
->code
))) {
999 ctx
->old_flag
= r
->flag
;
1000 if (ctx
->old_flag
& FLAG_END
) {
1001 struct p_context
*old
;
1002 debug("pop stack\n");
1003 done_pipe(ctx
,PIPE_SEQ
);
1005 old
->child
->group
= ctx
->list_head
;
1006 *ctx
= *old
; /* physical copy */
1016 /* normal return is 0.
1017 * Syntax or xglob errors return 1. */
1018 static int done_word(o_string
*dest
, struct p_context
*ctx
)
1020 struct child_prog
*child
=ctx
->child
;
1021 glob_t
*glob_target
;
1024 debug("done_word: %s %p\n", dest
->data
, child
);
1025 if (dest
->length
== 0 && !dest
->nonnull
) {
1026 debug(" true null, ignored\n");
1031 return 1; /* syntax error, groups and arglists don't mix */
1033 if (!child
->argv
&& (ctx
->type
& FLAG_PARSE_SEMICOLON
)) {
1034 debug("checking %s for reserved-ness\n",dest
->data
);
1035 if (reserved_word(dest
,ctx
))
1036 return ctx
->w
==RES_SNTX
;
1039 glob_target
= &child
->glob_result
;
1041 flags
|= GLOB_APPEND
;
1043 gr
= xglob(dest
, flags
, glob_target
);
1049 child
->argv
= glob_target
->gl_pathv
;
1050 child
->argc
= glob_target
->gl_pathc
;
1052 if (ctx
->w
== RES_FOR
) {
1053 done_word(dest
,ctx
);
1054 done_pipe(ctx
,PIPE_SEQ
);
1059 /* The only possible error here is out of memory, in which case
1061 static int done_command(struct p_context
*ctx
)
1063 /* The child is really already in the pipe structure, so
1064 * advance the pipe counter and make a new, null child.
1065 * Only real trickiness here is that the uncommitted
1066 * child structure, to which ctx->child points, is not
1067 * counted in pi->num_progs. */
1068 struct pipe
*pi
=ctx
->pipe
;
1069 struct child_prog
*prog
=ctx
->child
;
1071 if (prog
&& prog
->group
== NULL
1072 && prog
->argv
== NULL
1074 debug("done_command: skipping null command\n");
1078 debug("done_command: num_progs incremented to %d\n",pi
->num_progs
);
1080 debug("done_command: initializing\n");
1082 pi
->progs
= xrealloc(pi
->progs
, sizeof(*pi
->progs
) * (pi
->num_progs
+1));
1084 prog
= pi
->progs
+ pi
->num_progs
;
1085 prog
->glob_result
.gl_pathv
= NULL
;
1091 prog
->type
= ctx
->type
;
1093 /* but ctx->pipe and ctx->list_head remain unchanged */
1097 static int done_pipe(struct p_context
*ctx
, pipe_style type
)
1100 done_command(ctx
); /* implicit closure of previous command */
1101 debug("done_pipe, type %d\n", type
);
1102 ctx
->pipe
->followup
= type
;
1103 ctx
->pipe
->r_mode
= ctx
->w
;
1105 ctx
->pipe
->next
= new_p
;
1108 done_command(ctx
); /* set up new pipe to accept commands */
1113 /* basically useful version until someone wants to get fancier,
1114 * see the bash man page under "Parameter Expansion" */
1115 static const char *lookup_param(char *src
)
1121 return get_dollar_var(src
[1]);
1126 static int parse_string(o_string
*dest
, struct p_context
*ctx
, const char *src
)
1129 setup_string_in_str(&foo
, src
);
1130 return parse_stream(dest
, ctx
, &foo
, '\0');
1133 static char *get_dollar_var(char ch
)
1135 static char buf
[40];
1140 sprintf(buf
, "%u", (unsigned int)last_return_code
);
1148 /* return code: 0 for OK, 1 for syntax error */
1149 static int handle_dollar(o_string
*dest
, struct p_context
*ctx
, struct in_str
*input
)
1152 int ch
= input
->peek(input
); /* first character after the $ */
1153 debug("handle_dollar: ch=%c\n",ch
);
1155 b_addchr(dest
, SPECIAL_VAR_SYMBOL
);
1157 while(ch
=b_peek(input
),isalnum(ch
) || ch
=='_' || ch
=='.') {
1161 b_addchr(dest
, SPECIAL_VAR_SYMBOL
);
1162 } else if (isdigit(ch
)) {
1164 i
= ch
- '0'; /* XXX is $0 special? */
1165 if (i
< ctx
->global_argc
) {
1166 parse_string(dest
, ctx
, ctx
->global_argv
[i
]); /* recursion */
1173 b_addchr(dest
, SPECIAL_VAR_SYMBOL
);
1174 b_addchr(dest
, '$');
1175 b_addchr(dest
, '?');
1176 b_addchr(dest
, SPECIAL_VAR_SYMBOL
);
1180 b_adduint(dest
,ctx
->global_argc
? ctx
->global_argc
-1 : 0);
1184 b_addchr(dest
, SPECIAL_VAR_SYMBOL
);
1187 /* XXX maybe someone will try to escape the '}' */
1188 while(ch
=b_getch(input
),ch
!=EOF
&& ch
!='}') {
1195 b_addchr(dest
, SPECIAL_VAR_SYMBOL
);
1198 b_addqchr(dest
,'$',dest
->quote
);
1201 /* Eat the character if the flag was set. If the compiler
1202 * is smart enough, we could substitute "b_getch(input);"
1203 * for all the "advance = 1;" above, and also end up with
1204 * a nice size-optimized program. Hah! That'll be the day.
1212 /* return code is 0 for normal exit, 1 for syntax error */
1213 static int parse_stream(o_string
*dest
, struct p_context
*ctx
,
1214 struct in_str
*input
, int end_trigger
)
1219 /* Only double-quote state is handled in the state variable dest->quote.
1220 * A single-quote triggers a bypass of the main loop until its mate is
1221 * found. When recursing, quote state is passed in via dest->quote. */
1223 debug("parse_stream, end_trigger=%d\n",end_trigger
);
1224 while ((ch
=b_getch(input
))!=EOF
) {
1226 if (input
->__promptme
== 0)
1228 next
= (ch
== '\n') ? 0 : b_peek(input
);
1230 debug("parse_stream: ch=%c (%d) m=%d quote=%d - %c\n",
1231 ch
>= ' ' ? ch
: '.', ch
, m
,
1232 dest
->quote
, ctx
->stack
== NULL
? '*' : '.');
1234 if (m
==0 || ((m
==1 || m
==2) && dest
->quote
)) {
1235 b_addqchr(dest
, ch
, dest
->quote
);
1237 if (m
==2) { /* unquoted IFS */
1238 if (done_word(dest
, ctx
)) {
1241 /* If we aren't performing a substitution, treat a newline as a
1242 * command separator. */
1243 if (end_trigger
!= '\0' && ch
=='\n')
1244 done_pipe(ctx
,PIPE_SEQ
);
1246 if (ch
== end_trigger
&& !dest
->quote
&& ctx
->w
==RES_NONE
) {
1247 debug("leaving parse_stream (triggered)\n");
1253 if (dest
->length
== 0 && !dest
->quote
) {
1254 while(ch
=b_peek(input
),ch
!=EOF
&& ch
!='\n') {
1258 b_addqchr(dest
, ch
, dest
->quote
);
1266 b_addqchr(dest
, '\\', dest
->quote
);
1267 b_addqchr(dest
, b_getch(input
), dest
->quote
);
1270 if (handle_dollar(dest
, ctx
, input
)!=0)
1275 while(ch
=b_getch(input
),ch
!=EOF
&& ch
!='\'') {
1276 if(input
->__promptme
== 0)
1287 dest
->quote
= !dest
->quote
;
1290 done_word(dest
, ctx
);
1291 done_pipe(ctx
,PIPE_SEQ
);
1294 done_word(dest
, ctx
);
1297 done_pipe(ctx
,PIPE_AND
);
1304 done_word(dest
, ctx
);
1307 done_pipe(ctx
,PIPE_OR
);
1309 /* we could pick up a file descriptor choice here
1310 * with redirect_opt_num(), but bash doesn't do it.
1311 * "echo foo 2| cat" yields "foo 2". */
1317 syntax(); /* this is really an internal logic error */
1323 /* complain if quote? No, maybe we just finished a command substitution
1324 * that was quoted. Example:
1325 * $ echo "`cat foo` plus more"
1326 * and we just got the EOF generated by the subshell that ran "cat foo"
1327 * The only real complaint is if we got an EOF when end_trigger != '\0',
1328 * that is, we were really supposed to get end_trigger, and never got
1329 * one before the EOF. Can't use the standard "syntax error" return code,
1330 * so that parse_stream_outer can distinguish the EOF and exit smoothly. */
1331 debug("leaving parse_stream (EOF)\n");
1332 if (end_trigger
!= '\0') return -1;
1336 static void mapset(const unsigned char *set
, int code
)
1338 const unsigned char *s
;
1339 for (s
=set
; *s
; s
++) map
[*s
] = code
;
1342 static void update_ifs_map(void)
1344 /* char *ifs and char map[256] are both globals. */
1345 ifs
= (uchar
*)getenv("IFS");
1347 if (ifs
== NULL
) ifs
=(uchar
*)" \t\n";
1348 /* Precompute a list of 'flow through' behavior so it can be treated
1349 * quickly up front. Computation is necessary because of IFS.
1350 * Special case handling of IFS == " \t\n" is not implemented.
1351 * The map[] array only really needs two bits each, and on most machines
1352 * that would be faster because of the reduced L1 cache footprint.
1354 memset(map
,0,sizeof(map
)); /* most characters flow through always */
1355 mapset((uchar
*)"\\$'\"", 3); /* never flow through */
1356 mapset((uchar
*)";&|#", 1); /* flow through if quoted */
1357 mapset(ifs
, 2); /* also flow through if quoted */
1360 /* most recursion does not come through here, the exeception is
1361 * from builtin_source() */
1362 static int parse_stream_outer(struct p_context
*ctx
, struct in_str
*inp
, int flag
)
1364 o_string temp
=NULL_O_STRING
;
1369 initialize_context(ctx
);
1371 if (!(flag
& FLAG_PARSE_SEMICOLON
) || (flag
& FLAG_REPARSING
))
1372 mapset((uchar
*)";$&|", 0);
1374 rcode
= parse_stream(&temp
, ctx
, inp
, '\n');
1375 if (rcode
!= 1 && ctx
->old_flag
!= 0) {
1378 if (rcode
!= 1 && ctx
->old_flag
== 0) {
1379 done_word(&temp
, ctx
);
1380 done_pipe(ctx
,PIPE_SEQ
);
1381 code
= run_list(ctx
->list_head
);
1382 if (code
== -2) { /* exit */
1385 /* XXX hackish way to not allow exit from main loop */
1386 if (inp
->peek
== file_peek
) {
1387 printf("exit not allowed from main input shell.\n");
1394 if (ctx
->old_flag
!= 0) {
1398 if (inp
->__promptme
== 0)
1399 printf("<INTERRUPT>\n");
1400 inp
->__promptme
= 1;
1404 free_pipe_list(ctx
->list_head
,0);
1407 } while (rcode
!= -1 && !(flag
& FLAG_EXIT_FROM_LOOP
)); /* loop on syntax errors, return on EOF */
1409 return (code
!= 0) ? 1 : 0;
1412 static int parse_string_outer(struct p_context
*ctx
, const char *s
, int flag
)
1414 struct in_str input
;
1422 cp
= strchr(s
, '\n');
1424 p
= xmalloc(strlen(s
) + 2);
1427 setup_string_in_str(&input
, p
);
1428 rcode
= parse_stream_outer(ctx
, &input
, flag
);
1432 setup_string_in_str(&input
, s
);
1433 return parse_stream_outer(ctx
, &input
, flag
);
1437 static char *insert_var_value(char *inp
)
1439 int res_str_len
= 0;
1442 char *p
, *res_str
= NULL
;
1445 while ((p
= strchr(inp
, SPECIAL_VAR_SYMBOL
))) {
1448 res_str
= xrealloc(res_str
, (res_str_len
+ len
));
1449 strncpy((res_str
+ res_str_len
), inp
, len
);
1453 p
= strchr(inp
, SPECIAL_VAR_SYMBOL
);
1455 if ((p1
= lookup_param(inp
))) {
1456 len
= res_str_len
+ strlen(p1
);
1457 res_str
= xrealloc(res_str
, (1 + len
));
1458 strcpy((res_str
+ res_str_len
), p1
);
1461 *p
= SPECIAL_VAR_SYMBOL
;
1466 res_str
= xrealloc(res_str
, (1 + res_str_len
+ strlen(inp
)));
1467 strcpy((res_str
+ res_str_len
), inp
);
1468 while ((p
= strchr(res_str
, '\n'))) {
1472 return (res_str
== NULL
) ? inp
: res_str
;
1475 static char **make_list_in(char **inp
, char *name
)
1478 int name_len
= strlen(name
);
1483 /* create list of variable values */
1484 list
= xmalloc(sizeof(*list
));
1485 for (i
= 0; inp
[i
]; i
++) {
1486 p3
= insert_var_value(inp
[i
]);
1493 if ((p2
= strchr(p1
, ' '))) {
1499 /* we use n + 2 in realloc for list,because we add
1500 * new element and then we will add NULL element */
1501 list
= xrealloc(list
, sizeof(*list
) * (n
+ 2));
1502 list
[n
] = xmalloc(2 + name_len
+ len
);
1503 strcpy(list
[n
], name
);
1504 strcat(list
[n
], "=");
1505 strncat(list
[n
], p1
, len
);
1506 list
[n
++][name_len
+ len
+ 1] = '\0';
1516 /* Make new string for parser */
1517 static char * make_string(char ** inp
)
1524 for (n
= 0; inp
[n
]; n
++) {
1525 p
= insert_var_value(inp
[n
]);
1526 str
= xrealloc(str
, (len
+ strlen(p
)));
1533 len
= strlen(str
) + 3;
1538 *(str
+ len
) = '\n';
1539 *(str
+ len
+ 1) = '\0';
1543 int run_command (const char *cmd
, int flag
)
1545 struct p_context ctx
;
1546 return parse_string_outer(&ctx
, cmd
, FLAG_PARSE_SEMICOLON
);
1549 static int execute_script(const char *path
, int argc
, char *argv
[])
1554 ret
= source_script(path
, argc
, argv
);
1560 static int source_script(const char *path
, int argc
, char *argv
[])
1562 struct p_context ctx
;
1566 ctx
.global_argc
= argc
;
1567 ctx
.global_argv
= argv
;
1569 script
= read_file(path
, NULL
);
1575 ret
= parse_string_outer(&ctx
, script
, FLAG_PARSE_SEMICOLON
);
1585 struct in_str input
;
1586 struct p_context ctx
;
1588 setup_file_in_str(&input
);
1589 rcode
= parse_stream_outer(&ctx
, &input
, FLAG_PARSE_SEMICOLON
);
1593 static int do_sh(cmd_tbl_t
*cmdtp
, int argc
, char *argv
[])
1596 printf ("Usage:\n%s\n", cmdtp
->usage
);
1600 return execute_script(argv
[1], argc
- 1, argv
+ 1);
1603 static const __maybe_unused
char cmd_sh_help
[] =
1604 "Usage: sh filename [arguments]\n"
1606 "Execute a shell script\n";
1608 U_BOOT_CMD_START(sh
)
1609 .maxargs
= CONFIG_MAXARGS
,
1611 .usage
= "run shell script",
1612 U_BOOT_CMD_HELP(cmd_sh_help
)
1615 static int do_source(cmd_tbl_t
*cmdtp
, int argc
, char *argv
[])
1618 printf ("Usage:\n%s\n", cmdtp
->usage
);
1622 return source_script(argv
[1], argc
- 1, argv
+ 1);
1625 static const char *source_aliases
[] = { ".", NULL
};
1627 static const __maybe_unused
char cmd_source_help
[] =
1628 "Usage: . filename [arguments]\n"
1629 "or source filename [arguments]\n"
1631 "Read and execute commands from filename in the current shell\n"
1632 "environment and return the exit status of the last command exe-\n"
1633 "cuted from filename\n";
1635 static const __maybe_unused
char cmd_source_usage
[] =
1636 "execute shell script in current shell environment";
1638 U_BOOT_CMD_START(source
)
1639 .maxargs
= CONFIG_MAXARGS
,
1640 .aliases
= source_aliases
,
1642 .usage
= cmd_source_usage
,
1643 U_BOOT_CMD_HELP(cmd_source_help
)
1648 * @brief A prototype Bourne shell grammar parser
1651 /** @page sh_command Starting shell
1653 * Usage: sh \<filename\> [\<arguments\>]
1655 * Execute a shell script named \<filename\> and forward (if given)
1656 * \<arguments\> to it.
1658 * Usage: . \<filename\> [\<arguments\>]
1659 * or source \<filename\> [\<arguments\>]
1661 * Read and execute commands from \<filename\> in the current shell environment,
1662 * forward (if given) \<arguments\> to it and return the exit status of the last
1663 * command executed from filename.