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 */
116 #include <environment.h>
117 #include <command.h> /* find_cmd */
125 extern int do_bootd (cmd_tbl_t
*cmdtp
, int flag
, int argc
, char *argv
[]); /* do_bootd */
126 #define SPECIAL_VAR_SYMBOL 03
129 #define EXIT_SUCCESS 0
131 #define syntax() syntax_err()
132 #define xstrdup strdup
133 #define error_msg printf
142 /* might eventually control execution */
159 #define FLAG_END (1<<RES_NONE)
160 #define FLAG_IF (1<<RES_IF)
161 #define FLAG_THEN (1<<RES_THEN)
162 #define FLAG_ELIF (1<<RES_ELIF)
163 #define FLAG_ELSE (1<<RES_ELSE)
164 #define FLAG_FI (1<<RES_FI)
165 #define FLAG_FOR (1<<RES_FOR)
166 #define FLAG_WHILE (1<<RES_WHILE)
167 #define FLAG_UNTIL (1<<RES_UNTIL)
168 #define FLAG_DO (1<<RES_DO)
169 #define FLAG_DONE (1<<RES_DONE)
170 #define FLAG_IN (1<<RES_IN)
171 #define FLAG_START (1<<RES_XXXX)
173 #define FLAG_EXIT_FROM_LOOP 1
174 #define FLAG_PARSE_SEMICOLON (1 << 1) /* symbol ';' is special for parser */
175 #define FLAG_REPARSING (1 << 2) /* >=2nd pass */
177 /* This holds pointers to the various results of parsing */
179 struct child_prog
*child
;
180 struct pipe
*list_head
;
183 int old_flag
; /* for figuring out valid reserved words */
184 struct p_context
*stack
;
185 int type
; /* define type of parser : ";$" common or special symbol */
186 /* How about quoting status? */
189 unsigned int global_argc
;
194 char **argv
; /* program name and arguments */
195 int argc
; /* number of program arguments */
196 struct pipe
*group
; /* if non-NULL, first in group or subshell */
197 int sp
; /* number of SPECIAL_VAR_SYMBOL */
199 glob_t glob_result
; /* result of parameter globbing */
203 int num_progs
; /* total number of programs in job */
204 struct child_prog
*progs
; /* array of commands in pipe */
205 struct pipe
*next
; /* to track background commands */
206 pipe_style followup
; /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */
207 reserved_style r_mode
; /* supports if, for, while, until */
211 static char console_buffer
[CONFIG_CBSIZE
]; /* console I/O buffer */
213 /* globals, connect us to the outside world
214 * the first three support $?, $#, and $1 */
215 static unsigned int last_return_code
;
217 /* "globals" within this file */
219 static char map
[256];
221 #define B_CHUNK (100)
231 #define NULL_O_STRING {NULL,0,0,0,0}
232 /* used for initialization:
233 o_string foo = NULL_O_STRING; */
235 /* I can almost use ordinary FILE *. Is open_memstream() universally
236 * available? Where is it documented? */
241 int (*get
) (struct in_str
*);
242 int (*peek
) (struct in_str
*);
244 #define b_getch(input) ((input)->get(input))
245 #define b_peek(input) ((input)->peek(input))
248 #define final_printf debug
250 static void syntax_err(void) {
251 printf("syntax error\n");
254 /* o_string manipulation: */
255 static int b_check_space(o_string
*o
, int len
);
256 static int b_addchr(o_string
*o
, int ch
);
257 static void b_reset(o_string
*o
);
258 static int b_addqchr(o_string
*o
, int ch
, int quote
);
259 /* in_str manipulations: */
260 static int static_get(struct in_str
*i
);
261 static int static_peek(struct in_str
*i
);
262 static int file_get(struct in_str
*i
);
263 static int file_peek(struct in_str
*i
);
264 static void setup_file_in_str(struct in_str
*i
);
265 static void setup_string_in_str(struct in_str
*i
, const char *s
);
266 /* "run" the final data structures: */
267 static int free_pipe_list(struct pipe
*head
, int indent
);
268 static int free_pipe(struct pipe
*pi
, int indent
);
269 /* really run the final data structures: */
270 static int run_list_real(struct pipe
*pi
);
271 static int run_pipe_real(struct pipe
*pi
);
272 /* extended glob support: */
273 /* variable assignment: */
274 static int is_assignment(const char *s
);
275 /* data structure manipulation: */
276 static void initialize_context(struct p_context
*ctx
);
277 static int done_word(o_string
*dest
, struct p_context
*ctx
);
278 static int done_command(struct p_context
*ctx
);
279 static int done_pipe(struct p_context
*ctx
, pipe_style type
);
280 /* primary string parsing: */
281 static const char *lookup_param(char *src
);
282 static char *make_string(char **inp
);
283 static int handle_dollar(o_string
*dest
, struct p_context
*ctx
, struct in_str
*input
);
284 static int parse_stream(o_string
*dest
, struct p_context
*ctx
, struct in_str
*input0
, int end_trigger
);
286 static int parse_stream_outer(struct p_context
*ctx
, struct in_str
*inp
, int flag
);
288 static int parse_string_outer(struct p_context
*ctx
, const char *s
, int flag
);
289 /* local variable support */
290 static char **make_list_in(char **inp
, char *name
);
291 static char *insert_var_value(char *inp
);
292 static int set_local_var(const char *s
, int flg_export
);
293 static int execute_script(const char *path
, int argc
, char *argv
[]);
294 static int source_script(const char *path
, int argc
, char *argv
[]);
296 static int b_check_space(o_string
*o
, int len
)
298 /* It would be easy to drop a more restrictive policy
299 * in here, such as setting a maximum string length */
300 if (o
->length
+ len
> o
->maxlen
) {
301 char *old_data
= o
->data
;
302 /* assert (data == NULL || o->maxlen != 0); */
303 o
->maxlen
+= max(2*len
, B_CHUNK
);
304 o
->data
= realloc(o
->data
, 1 + o
->maxlen
);
305 if (o
->data
== NULL
) {
309 return o
->data
== NULL
;
312 static int b_addchr(o_string
*o
, int ch
)
314 debug("b_addchr: %c %d %p\n", ch
, o
->length
, o
);
315 if (b_check_space(o
, 1))
317 o
->data
[o
->length
] = ch
;
319 o
->data
[o
->length
] = '\0';
323 static void b_reset(o_string
*o
)
327 if (o
->data
!= NULL
) *o
->data
= '\0';
330 static void b_free(o_string
*o
)
338 /* My analysis of quoting semantics tells me that state information
339 * is associated with a destination, not a source.
341 static int b_addqchr(o_string
*o
, int ch
, int quote
)
343 if (quote
&& strchr("*?[",ch
)) {
345 rc
= b_addchr(o
, '\\');
349 return b_addchr(o
, ch
);
352 /* belongs in utility.c */
353 char *simple_itoa(unsigned int i
)
355 /* 21 digits plus null terminator, good for 64-bit or smaller ints */
356 static char local
[22];
357 char *p
= &local
[21];
366 static int b_adduint(o_string
*o
, unsigned int i
)
369 char *p
= simple_itoa(i
);
370 /* no escape checking necessary */
373 } while (r
==0 && *p
);
378 static int static_get(struct in_str
*i
)
387 static int static_peek(struct in_str
*i
)
393 static char *getprompt(void)
398 prompt
= xmalloc(PATH_MAX
+ strlen(CONFIG_PROMPT
) + 1);
400 sprintf(prompt
, "%s%s ", CONFIG_PROMPT
, getcwd());
404 static void get_user_input(struct in_str
*i
)
407 static char the_command
[CONFIG_CBSIZE
];
410 if (i
->promptmode
== 1) {
411 n
= readline(getprompt(), console_buffer
, CONFIG_CBSIZE
);
413 n
= readline(CONFIG_PROMPT_HUSH_PS2
, console_buffer
, CONFIG_CBSIZE
);
420 console_buffer
[n
] = '\n';
421 console_buffer
[n
+1]= '\0';
422 if (i
->promptmode
== 1) {
423 strcpy(the_command
,console_buffer
);
426 if (console_buffer
[0] != '\n') {
427 if (strlen(the_command
) + strlen(console_buffer
)
429 n
= strlen(the_command
);
430 the_command
[n
-1] = ' ';
431 strcpy(&the_command
[n
],console_buffer
);
434 the_command
[0] = '\n';
435 the_command
[1] = '\0';
438 if (i
->__promptme
== 0) {
439 the_command
[0] = '\n';
440 the_command
[1] = '\0';
442 i
->p
= console_buffer
;
446 /* This is the magic location that prints prompts
447 * and gets data back from the user */
448 static int file_get(struct in_str
*i
)
453 /* If there is data waiting, eat it up */
457 /* need to double check i->file because we might be doing something
458 * more complicated by now, like sourcing or substituting. */
459 while(! i
->p
|| strlen(i
->p
)==0 ) {
466 debug("b_getch: got a %d\n", ch
);
471 /* All the callers guarantee this routine will never be
472 * used right after a newline, so prompting is not needed.
474 static int file_peek(struct in_str
*i
)
479 static void setup_file_in_str(struct in_str
*i
)
488 static void setup_string_in_str(struct in_str
*i
, const char *s
)
490 i
->peek
= static_peek
;
498 /* run_pipe_real() starts all the jobs, but doesn't wait for anything
499 * to finish. See checkjobs().
501 * return code is normally -1, when the caller has to wait for children
502 * to finish to determine the exit status of the pipe. If the pipe
503 * is a simple builtin command, however, the action is done by the
504 * time run_pipe_real returns, and the exit code is provided as the
507 * The input of the pipe is always stdin, the output is always
508 * stdout. The outpipe[] mechanism in BusyBox-0.48 lash is bogus,
509 * because it tries to avoid running the command substitution in
510 * subshell, when that is in fact necessary. The subshell process
511 * now has its stdout directed to the input of the appropriate pipe,
512 * so this routine is noticeably simpler.
514 static int run_pipe_real(struct pipe
*pi
)
518 struct child_prog
*child
;
523 /* Avoid longjmp clobbering */
531 /* Check if this is a simple builtin (not part of a pipe).
532 * Builtins within pipes have to fork anyway, and are handled in
533 * pseudo_exec. "echo foo | read bar" doesn't work on bash, either.
535 if (pi
->num_progs
== 1)
536 child
= & (pi
->progs
[0]);
537 if (pi
->num_progs
== 1 && child
->group
) {
539 debug("non-subshell grouping\n");
540 rcode
= run_list_real(child
->group
);
542 } else if (pi
->num_progs
== 1 && pi
->progs
[0].argv
!= NULL
) {
543 for (i
=0; is_assignment(child
->argv
[i
]); i
++) { /* nothing */ }
544 if (i
!=0 && child
->argv
[i
]==NULL
) {
545 /* assignments, but no command: set the local environment */
546 for (i
=0; child
->argv
[i
]!=NULL
; i
++) {
548 /* Ok, this case is tricky. We have to decide if this is a
549 * local variable, or an already exported variable. If it is
550 * already exported, we have to export the new value. If it is
551 * not exported, we need only set this as a local variable.
552 * This junk is all to decide whether or not to export this
556 name
= xstrdup(child
->argv
[i
]);
557 debug("Local environment set: %s\n", name
);
558 value
= strchr(name
, '=');
562 p
= insert_var_value(child
->argv
[i
]);
563 set_local_var(p
, export_me
);
564 if (p
!= child
->argv
[i
])
567 return EXIT_SUCCESS
; /* don't worry about errors in set_local_var() yet */
569 for (i
= 0; is_assignment(child
->argv
[i
]); i
++) {
570 p
= insert_var_value(child
->argv
[i
]);
572 if (p
!= child
->argv
[i
]) {
579 struct p_context ctx
;
580 str
= make_string((child
->argv
+ i
));
581 parse_string_outer(&ctx
, str
, FLAG_EXIT_FROM_LOOP
| FLAG_REPARSING
);
583 return last_return_code
;
586 if (strchr(child
->argv
[i
], '/')) {
587 return execute_script(child
->argv
[i
], child
->argc
-i
, &child
->argv
[i
]);
589 if ((path
= find_execable(child
->argv
[i
]))) {
590 ret
= execute_script(path
, child
->argc
-i
, &child
->argv
[i
]);
595 return execute_command(child
->argc
- i
, &child
->argv
[i
]);
600 static int run_list_real(struct pipe
*pi
)
602 char *save_name
= NULL
;
604 char **save_list
= NULL
;
607 int rcode
=0, flag_skip
=1;
608 int flag_restore
= 0;
609 int if_code
=0, next_if_code
=0; /* need double-buffer to handle elif */
610 reserved_style rmode
, skip_more_in_this_rmode
=RES_XXXX
;
611 /* check syntax for "for" */
612 for (rpipe
= pi
; rpipe
; rpipe
= rpipe
->next
) {
613 if ((rpipe
->r_mode
== RES_IN
||
614 rpipe
->r_mode
== RES_FOR
) &&
615 (rpipe
->next
== NULL
)) {
619 if ((rpipe
->r_mode
== RES_IN
&&
620 (rpipe
->next
->r_mode
== RES_IN
&&
621 rpipe
->next
->progs
->argv
!= NULL
))||
622 (rpipe
->r_mode
== RES_FOR
&&
623 rpipe
->next
->r_mode
!= RES_IN
)) {
628 for (; pi
; pi
= (flag_restore
!= 0) ? rpipe
: pi
->next
) {
629 if (pi
->r_mode
== RES_WHILE
|| pi
->r_mode
== RES_UNTIL
||
630 pi
->r_mode
== RES_FOR
) {
641 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
);
642 if (rmode
== skip_more_in_this_rmode
&& flag_skip
) {
643 if (pi
->followup
== PIPE_SEQ
) flag_skip
=0;
647 skip_more_in_this_rmode
= RES_XXXX
;
648 if (rmode
== RES_THEN
|| rmode
== RES_ELSE
)
649 if_code
= next_if_code
;
650 if (rmode
== RES_THEN
&& if_code
)
652 if (rmode
== RES_ELSE
&& !if_code
)
654 if (rmode
== RES_ELIF
&& !if_code
)
656 if (rmode
== RES_FOR
&& pi
->num_progs
) {
658 /* if no variable values after "in" we skip "for" */
659 if (!pi
->next
->progs
->argv
)
661 /* create list of variable values */
662 list
= make_list_in(pi
->next
->progs
->argv
,
665 save_name
= pi
->progs
->argv
[0];
666 pi
->progs
->argv
[0] = NULL
;
670 free(pi
->progs
->argv
[0]);
674 pi
->progs
->argv
[0] = save_name
;
677 /* insert new value from list for variable */
678 if (pi
->progs
->argv
[0])
679 free(pi
->progs
->argv
[0]);
680 pi
->progs
->argv
[0] = *list
++;
685 if (rmode
== RES_DO
) {
689 if ((rmode
== RES_DONE
)) {
696 if (pi
->num_progs
== 0)
698 rcode
= run_pipe_real(pi
);
699 debug("run_pipe_real returned %d\n",rcode
);
701 last_return_code
= -rcode
- 2;
702 return -2; /* exit */
704 last_return_code
=rcode
;
705 if ( rmode
== RES_IF
|| rmode
== RES_ELIF
)
706 next_if_code
=rcode
; /* can be overwritten a number of times */
707 if (rmode
== RES_WHILE
)
708 flag_rep
= !last_return_code
;
709 if (rmode
== RES_UNTIL
)
710 flag_rep
= last_return_code
;
711 if ( (rcode
==EXIT_SUCCESS
&& pi
->followup
==PIPE_OR
) ||
712 (rcode
!=EXIT_SUCCESS
&& pi
->followup
==PIPE_AND
) )
713 skip_more_in_this_rmode
=rmode
;
719 /* broken, of course, but OK for testing */
720 static char *indenter(int i
)
722 static char blanks
[]=" ";
723 return &blanks
[sizeof(blanks
)-i
-1];
727 /* return code is the exit status of the pipe */
728 static int free_pipe(struct pipe
*pi
, int indent
)
731 struct child_prog
*child
;
732 int a
, i
, ret_code
=0;
734 for (i
=0; i
<pi
->num_progs
; i
++) {
735 child
= &pi
->progs
[i
];
736 final_printf("%s command %d:\n",indenter(indent
),i
);
738 for (a
=0,p
=child
->argv
; *p
; a
++,p
++) {
739 final_printf("%s argv[%d] = %s\n",indenter(indent
),a
,*p
);
741 globfree(&child
->glob_result
);
743 } else if (child
->group
) {
744 ret_code
= free_pipe_list(child
->group
,indent
+3);
745 final_printf("%s end group\n",indenter(indent
));
747 final_printf("%s (nil)\n",indenter(indent
));
750 free(pi
->progs
); /* children are an array, they get freed all at once */
755 static int free_pipe_list(struct pipe
*head
, int indent
)
757 int rcode
=0; /* if list has no members */
758 struct pipe
*pi
, *next
;
759 for (pi
=head
; pi
; pi
=next
) {
760 final_printf("%s pipe reserved mode %d\n", indenter(indent
), pi
->r_mode
);
761 rcode
= free_pipe(pi
, indent
);
762 final_printf("%s pipe followup code %d\n", indenter(indent
), pi
->followup
);
770 /* The API for glob is arguably broken. This routine pushes a non-matching
771 * string into the output structure, removing non-backslashed backslashes.
772 * If someone can prove me wrong, by performing this function within the
773 * original glob(3) api, feel free to rewrite this routine into oblivion.
774 * Return code (0 vs. GLOB_NOSPACE) matches glob(3).
775 * XXX broken if the last character is '\\', check that before calling.
777 static int globhack(const char *src
, int flags
, glob_t
*pglob
)
782 for (cnt
=1, s
=src
; s
&& *s
; s
++) {
787 if (!(flags
& GLOB_APPEND
)) {
788 pglob
->gl_pathv
= NULL
;
792 pathc
= ++pglob
->gl_pathc
;
793 pglob
->gl_pathv
= xrealloc(pglob
->gl_pathv
, (pathc
+1)*sizeof(*pglob
->gl_pathv
));
794 pglob
->gl_pathv
[pathc
-1] = dest
;
795 pglob
->gl_pathv
[pathc
] = NULL
;
796 for (s
=src
; s
&& *s
; s
++, dest
++) {
804 /* XXX broken if the last character is '\\', check that before calling */
805 static int glob_needed(const char *s
)
810 if (strchr("*[?",*s
))
817 static int xglob(o_string
*dest
, int flags
, glob_t
*pglob
)
821 /* short-circuit for null word */
822 /* we can code this better when the debug's are gone */
823 if (dest
->length
== 0) {
825 /* bash man page calls this an "explicit" null */
826 gr
= globhack(dest
->data
, flags
, pglob
);
827 debug("globhack returned %d\n",gr
);
831 } else if (glob_needed(dest
->data
)) {
832 gr
= glob(dest
->data
, flags
, NULL
, pglob
);
833 debug("glob returned %d\n",gr
);
834 if (gr
== GLOB_NOMATCH
) {
835 /* quote removal, or more accurately, backslash removal */
836 gr
= globhack(dest
->data
, flags
, pglob
);
837 debug("globhack returned %d\n",gr
);
840 gr
= globhack(dest
->data
, flags
, pglob
);
841 debug("globhack returned %d\n",gr
);
843 if (gr
!= 0) { /* GLOB_ABORTED ? */
844 error_msg("glob(3) error %d",gr
);
846 /* globprint(glob_target); */
850 /* Select which version we will use */
851 static int run_list(struct pipe
*pi
)
855 rcode
= run_list_real(pi
);
857 /* free_pipe_list has the side effect of clearing memory
858 * In the long run that function can be merged with run_list_real,
859 * but doing that now would hobble the debugging effort. */
860 free_pipe_list(pi
,0);
864 static char *get_dollar_var(char ch
);
866 /* This is used to set local shell variables
867 flg_export==0 if only local (not exporting) variable
868 flg_export==1 if "new" exporting environ
869 flg_export>1 if current startup environ (not call putenv()) */
870 static int set_local_var(const char *s
, int flg_export
)
875 /* might be possible! */
881 /* Assume when we enter this function that we are already in
882 * NAME=VALUE format. So the first order of business is to
883 * split 's' on the '=' into 'name' and 'value' */
884 value
= strchr(name
, '=');
885 if (value
==0 && ++value
==0) {
891 ret
= setenv(name
, value
);
899 static int is_assignment(const char *s
)
907 while(isalnum(*s
) || *s
=='_' || *s
=='.')
913 static struct pipe
*new_pipe(void) {
914 return (struct pipe
*)xzalloc(sizeof(struct pipe
));
917 static void initialize_context(struct p_context
*ctx
)
921 ctx
->list_head
=new_pipe();
922 ctx
->pipe
=ctx
->list_head
;
926 done_command(ctx
); /* creates the memory for working child */
929 /* normal return is 0
930 * if a reserved word is found, and processed, return 1
931 * should handle if, then, elif, else, fi, for, while, until, do, done.
932 * case, function, and select are obnoxious, save those for later.
934 struct reserved_combo
{
939 /* Mostly a list of accepted follow-up reserved words.
940 * FLAG_END means we are done with the sequence, and are ready
941 * to turn the compound list into a command.
942 * FLAG_START means the word must start a new compound list.
944 static struct reserved_combo reserved_list
[] = {
945 { "if", RES_IF
, FLAG_THEN
| FLAG_START
},
946 { "then", RES_THEN
, FLAG_ELIF
| FLAG_ELSE
| FLAG_FI
},
947 { "elif", RES_ELIF
, FLAG_THEN
},
948 { "else", RES_ELSE
, FLAG_FI
},
949 { "fi", RES_FI
, FLAG_END
},
950 { "for", RES_FOR
, FLAG_IN
| FLAG_START
},
951 { "while", RES_WHILE
, FLAG_DO
| FLAG_START
},
952 { "until", RES_UNTIL
, FLAG_DO
| FLAG_START
},
953 { "in", RES_IN
, FLAG_DO
},
954 { "do", RES_DO
, FLAG_DONE
},
955 { "done", RES_DONE
, FLAG_END
}
957 #define NRES (sizeof(reserved_list)/sizeof(struct reserved_combo))
959 static int reserved_word(o_string
*dest
, struct p_context
*ctx
)
961 struct reserved_combo
*r
;
962 for (r
=reserved_list
;
963 r
<reserved_list
+NRES
; r
++) {
964 if (strcmp(dest
->data
, r
->literal
) == 0) {
965 debug("found reserved word %s, code %d\n",r
->literal
,r
->code
);
966 if (r
->flag
& FLAG_START
) {
967 struct p_context
*new = xmalloc(sizeof(struct p_context
));
968 debug("push stack\n");
969 if (ctx
->w
== RES_IN
|| ctx
->w
== RES_FOR
) {
976 *new = *ctx
; /* physical copy */
977 initialize_context(ctx
);
979 } else if ( ctx
->w
== RES_NONE
|| ! (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("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
)
1007 struct child_prog
*child
=ctx
->child
;
1008 glob_t
*glob_target
;
1011 debug("done_word: %s %p\n", dest
->data
, child
);
1012 if (dest
->length
== 0 && !dest
->nonnull
) {
1013 debug(" true null, ignored\n");
1018 return 1; /* syntax error, groups and arglists don't mix */
1020 if (!child
->argv
&& (ctx
->type
& FLAG_PARSE_SEMICOLON
)) {
1021 debug("checking %s for reserved-ness\n",dest
->data
);
1022 if (reserved_word(dest
,ctx
))
1023 return ctx
->w
==RES_SNTX
;
1026 glob_target
= &child
->glob_result
;
1028 flags
|= GLOB_APPEND
;
1030 gr
= xglob(dest
, flags
, glob_target
);
1036 child
->argv
= glob_target
->gl_pathv
;
1037 child
->argc
= glob_target
->gl_pathc
;
1039 if (ctx
->w
== RES_FOR
) {
1040 done_word(dest
,ctx
);
1041 done_pipe(ctx
,PIPE_SEQ
);
1046 /* The only possible error here is out of memory, in which case
1048 static int done_command(struct p_context
*ctx
)
1050 /* The child is really already in the pipe structure, so
1051 * advance the pipe counter and make a new, null child.
1052 * Only real trickiness here is that the uncommitted
1053 * child structure, to which ctx->child points, is not
1054 * counted in pi->num_progs. */
1055 struct pipe
*pi
=ctx
->pipe
;
1056 struct child_prog
*prog
=ctx
->child
;
1058 if (prog
&& prog
->group
== NULL
1059 && prog
->argv
== NULL
1061 debug("done_command: skipping null command\n");
1065 debug("done_command: num_progs incremented to %d\n",pi
->num_progs
);
1067 debug("done_command: initializing\n");
1069 pi
->progs
= xrealloc(pi
->progs
, sizeof(*pi
->progs
) * (pi
->num_progs
+1));
1071 prog
= pi
->progs
+ pi
->num_progs
;
1072 prog
->glob_result
.gl_pathv
= NULL
;
1078 prog
->type
= ctx
->type
;
1080 /* but ctx->pipe and ctx->list_head remain unchanged */
1084 static int done_pipe(struct p_context
*ctx
, pipe_style type
)
1087 done_command(ctx
); /* implicit closure of previous command */
1088 debug("done_pipe, type %d\n", type
);
1089 ctx
->pipe
->followup
= type
;
1090 ctx
->pipe
->r_mode
= ctx
->w
;
1092 ctx
->pipe
->next
= new_p
;
1095 done_command(ctx
); /* set up new pipe to accept commands */
1100 /* basically useful version until someone wants to get fancier,
1101 * see the bash man page under "Parameter Expansion" */
1102 static const char *lookup_param(char *src
)
1108 return get_dollar_var(src
[1]);
1113 static int parse_string(o_string
*dest
, struct p_context
*ctx
, const char *src
)
1116 setup_string_in_str(&foo
, src
);
1117 return parse_stream(dest
, ctx
, &foo
, '\0');
1120 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
, struct in_str
*input
)
1139 int ch
= input
->peek(input
); /* first character after the $ */
1140 debug("handle_dollar: ch=%c\n",ch
);
1142 b_addchr(dest
, SPECIAL_VAR_SYMBOL
);
1144 while(ch
=b_peek(input
),isalnum(ch
) || ch
=='_' || ch
=='.') {
1148 b_addchr(dest
, SPECIAL_VAR_SYMBOL
);
1149 } else if (isdigit(ch
)) {
1151 i
= ch
- '0'; /* XXX is $0 special? */
1152 if (i
< ctx
->global_argc
) {
1153 parse_string(dest
, ctx
, ctx
->global_argv
[i
]); /* recursion */
1160 b_addchr(dest
, SPECIAL_VAR_SYMBOL
);
1161 b_addchr(dest
, '$');
1162 b_addchr(dest
, '?');
1163 b_addchr(dest
, SPECIAL_VAR_SYMBOL
);
1167 b_adduint(dest
,ctx
->global_argc
? ctx
->global_argc
-1 : 0);
1171 b_addchr(dest
, SPECIAL_VAR_SYMBOL
);
1174 /* XXX maybe someone will try to escape the '}' */
1175 while(ch
=b_getch(input
),ch
!=EOF
&& ch
!='}') {
1182 b_addchr(dest
, SPECIAL_VAR_SYMBOL
);
1185 b_addqchr(dest
,'$',dest
->quote
);
1188 /* Eat the character if the flag was set. If the compiler
1189 * is smart enough, we could substitute "b_getch(input);"
1190 * for all the "advance = 1;" above, and also end up with
1191 * a nice size-optimized program. Hah! That'll be the day.
1199 /* return code is 0 for normal exit, 1 for syntax error */
1200 static int parse_stream(o_string
*dest
, struct p_context
*ctx
,
1201 struct in_str
*input
, int end_trigger
)
1206 /* Only double-quote state is handled in the state variable dest->quote.
1207 * A single-quote triggers a bypass of the main loop until its mate is
1208 * found. When recursing, quote state is passed in via dest->quote. */
1210 debug("parse_stream, end_trigger=%d\n",end_trigger
);
1211 while ((ch
=b_getch(input
))!=EOF
) {
1213 if (input
->__promptme
== 0)
1215 next
= (ch
== '\n') ? 0 : b_peek(input
);
1217 debug("parse_stream: ch=%c (%d) m=%d quote=%d - %c\n",
1218 ch
>= ' ' ? ch
: '.', ch
, m
,
1219 dest
->quote
, ctx
->stack
== NULL
? '*' : '.');
1221 if (m
==0 || ((m
==1 || m
==2) && dest
->quote
)) {
1222 b_addqchr(dest
, ch
, dest
->quote
);
1224 if (m
==2) { /* unquoted IFS */
1225 if (done_word(dest
, ctx
)) {
1228 /* If we aren't performing a substitution, treat a newline as a
1229 * command separator. */
1230 if (end_trigger
!= '\0' && ch
=='\n')
1231 done_pipe(ctx
,PIPE_SEQ
);
1233 if (ch
== end_trigger
&& !dest
->quote
&& ctx
->w
==RES_NONE
) {
1234 debug("leaving parse_stream (triggered)\n");
1240 if (dest
->length
== 0 && !dest
->quote
) {
1241 while(ch
=b_peek(input
),ch
!=EOF
&& ch
!='\n') {
1245 b_addqchr(dest
, ch
, dest
->quote
);
1253 b_addqchr(dest
, '\\', dest
->quote
);
1254 b_addqchr(dest
, b_getch(input
), dest
->quote
);
1257 if (handle_dollar(dest
, ctx
, input
)!=0)
1262 while(ch
=b_getch(input
),ch
!=EOF
&& ch
!='\'') {
1263 if(input
->__promptme
== 0)
1274 dest
->quote
= !dest
->quote
;
1277 done_word(dest
, ctx
);
1278 done_pipe(ctx
,PIPE_SEQ
);
1281 done_word(dest
, ctx
);
1284 done_pipe(ctx
,PIPE_AND
);
1291 done_word(dest
, ctx
);
1294 done_pipe(ctx
,PIPE_OR
);
1296 /* we could pick up a file descriptor choice here
1297 * with redirect_opt_num(), but bash doesn't do it.
1298 * "echo foo 2| cat" yields "foo 2". */
1304 syntax(); /* this is really an internal logic error */
1310 /* complain if quote? No, maybe we just finished a command substitution
1311 * that was quoted. Example:
1312 * $ echo "`cat foo` plus more"
1313 * and we just got the EOF generated by the subshell that ran "cat foo"
1314 * The only real complaint is if we got an EOF when end_trigger != '\0',
1315 * that is, we were really supposed to get end_trigger, and never got
1316 * one before the EOF. Can't use the standard "syntax error" return code,
1317 * so that parse_stream_outer can distinguish the EOF and exit smoothly. */
1318 debug("leaving parse_stream (EOF)\n");
1319 if (end_trigger
!= '\0') return -1;
1323 static void mapset(const unsigned char *set
, int code
)
1325 const unsigned char *s
;
1326 for (s
=set
; *s
; s
++) map
[*s
] = code
;
1329 static void update_ifs_map(void)
1331 /* char *ifs and char map[256] are both globals. */
1332 ifs
= (uchar
*)getenv("IFS");
1334 if (ifs
== NULL
) ifs
=(uchar
*)" \t\n";
1335 /* Precompute a list of 'flow through' behavior so it can be treated
1336 * quickly up front. Computation is necessary because of IFS.
1337 * Special case handling of IFS == " \t\n" is not implemented.
1338 * The map[] array only really needs two bits each, and on most machines
1339 * that would be faster because of the reduced L1 cache footprint.
1341 memset(map
,0,sizeof(map
)); /* most characters flow through always */
1342 mapset((uchar
*)"\\$'\"", 3); /* never flow through */
1343 mapset((uchar
*)";&|#", 1); /* flow through if quoted */
1344 mapset(ifs
, 2); /* also flow through if quoted */
1347 /* most recursion does not come through here, the exeception is
1348 * from builtin_source() */
1349 static int parse_stream_outer(struct p_context
*ctx
, struct in_str
*inp
, int flag
)
1351 o_string temp
=NULL_O_STRING
;
1356 initialize_context(ctx
);
1358 if (!(flag
& FLAG_PARSE_SEMICOLON
) || (flag
& FLAG_REPARSING
))
1359 mapset((uchar
*)";$&|", 0);
1361 rcode
= parse_stream(&temp
, ctx
, inp
, '\n');
1362 if (rcode
!= 1 && ctx
->old_flag
!= 0) {
1365 if (rcode
!= 1 && ctx
->old_flag
== 0) {
1366 done_word(&temp
, ctx
);
1367 done_pipe(ctx
,PIPE_SEQ
);
1368 if (ctx
->list_head
->num_progs
) {
1369 code
= run_list(ctx
->list_head
);
1371 free_pipe_list(ctx
->list_head
, 0);
1374 if (code
== -2) { /* exit */
1377 /* XXX hackish way to not allow exit from main loop */
1378 if (inp
->peek
== file_peek
) {
1379 printf("exit not allowed from main input shell.\n");
1383 code
= last_return_code
;
1387 if (ctx
->old_flag
!= 0) {
1391 if (inp
->__promptme
== 0)
1392 printf("<INTERRUPT>\n");
1393 inp
->__promptme
= 1;
1397 free_pipe_list(ctx
->list_head
,0);
1400 } while (rcode
!= -1 && !(flag
& FLAG_EXIT_FROM_LOOP
)); /* loop on syntax errors, return on EOF */
1402 return (code
!= 0) ? 1 : 0;
1405 static int parse_string_outer(struct p_context
*ctx
, const char *s
, int flag
)
1407 struct in_str input
;
1415 cp
= strchr(s
, '\n');
1417 p
= xmalloc(strlen(s
) + 2);
1420 setup_string_in_str(&input
, p
);
1421 rcode
= parse_stream_outer(ctx
, &input
, flag
);
1425 setup_string_in_str(&input
, s
);
1426 return parse_stream_outer(ctx
, &input
, flag
);
1430 static char *insert_var_value(char *inp
)
1432 int res_str_len
= 0;
1435 char *p
, *res_str
= NULL
;
1438 while ((p
= strchr(inp
, SPECIAL_VAR_SYMBOL
))) {
1441 res_str
= xrealloc(res_str
, (res_str_len
+ len
));
1442 strncpy((res_str
+ res_str_len
), inp
, len
);
1446 p
= strchr(inp
, SPECIAL_VAR_SYMBOL
);
1448 if ((p1
= lookup_param(inp
))) {
1449 len
= res_str_len
+ strlen(p1
);
1450 res_str
= xrealloc(res_str
, (1 + len
));
1451 strcpy((res_str
+ res_str_len
), p1
);
1454 *p
= SPECIAL_VAR_SYMBOL
;
1459 res_str
= xrealloc(res_str
, (1 + res_str_len
+ strlen(inp
)));
1460 strcpy((res_str
+ res_str_len
), inp
);
1461 while ((p
= strchr(res_str
, '\n'))) {
1465 return (res_str
== NULL
) ? inp
: res_str
;
1468 static char **make_list_in(char **inp
, char *name
)
1471 int name_len
= strlen(name
);
1476 /* create list of variable values */
1477 list
= xmalloc(sizeof(*list
));
1478 for (i
= 0; inp
[i
]; i
++) {
1479 p3
= insert_var_value(inp
[i
]);
1486 if ((p2
= strchr(p1
, ' '))) {
1492 /* we use n + 2 in realloc for list,because we add
1493 * new element and then we will add NULL element */
1494 list
= xrealloc(list
, sizeof(*list
) * (n
+ 2));
1495 list
[n
] = xmalloc(2 + name_len
+ len
);
1496 strcpy(list
[n
], name
);
1497 strcat(list
[n
], "=");
1498 strncat(list
[n
], p1
, len
);
1499 list
[n
++][name_len
+ len
+ 1] = '\0';
1509 /* Make new string for parser */
1510 static char * make_string(char ** inp
)
1517 for (n
= 0; inp
[n
]; n
++) {
1518 p
= insert_var_value(inp
[n
]);
1519 str
= xrealloc(str
, (len
+ strlen(p
)));
1526 len
= strlen(str
) + 3;
1531 *(str
+ len
) = '\n';
1532 *(str
+ len
+ 1) = '\0';
1536 int run_command (const char *cmd
, int flag
)
1538 struct p_context ctx
;
1539 return parse_string_outer(&ctx
, cmd
, FLAG_PARSE_SEMICOLON
);
1542 static int execute_script(const char *path
, int argc
, char *argv
[])
1547 ret
= source_script(path
, argc
, argv
);
1553 static int source_script(const char *path
, int argc
, char *argv
[])
1555 struct p_context ctx
;
1559 ctx
.global_argc
= argc
;
1560 ctx
.global_argv
= argv
;
1562 script
= read_file(path
, NULL
);
1568 ret
= parse_string_outer(&ctx
, script
, FLAG_PARSE_SEMICOLON
);
1578 struct in_str input
;
1579 struct p_context ctx
;
1581 setup_file_in_str(&input
);
1582 rcode
= parse_stream_outer(&ctx
, &input
, FLAG_PARSE_SEMICOLON
);
1586 static int do_sh(cmd_tbl_t
*cmdtp
, int argc
, char *argv
[])
1589 return COMMAND_ERROR_USAGE
;
1591 return execute_script(argv
[1], argc
- 1, argv
+ 1);
1594 static const __maybe_unused
char cmd_sh_help
[] =
1595 "Usage: sh filename [arguments]\n"
1597 "Execute a shell script\n";
1599 U_BOOT_CMD_START(sh
)
1601 .usage
= "run shell script",
1602 U_BOOT_CMD_HELP(cmd_sh_help
)
1605 static int do_source(cmd_tbl_t
*cmdtp
, int argc
, char *argv
[])
1608 return COMMAND_ERROR_USAGE
;
1610 return source_script(argv
[1], argc
- 1, argv
+ 1);
1613 static const char *source_aliases
[] = { ".", NULL
};
1615 static const __maybe_unused
char cmd_source_help
[] =
1616 "Usage: . filename [arguments]\n"
1617 "or source filename [arguments]\n"
1619 "Read and execute commands from filename in the current shell\n"
1620 "environment and return the exit status of the last command exe-\n"
1621 "cuted from filename\n";
1623 static const __maybe_unused
char cmd_source_usage
[] =
1624 "execute shell script in current shell environment";
1626 U_BOOT_CMD_START(source
)
1627 .aliases
= source_aliases
,
1629 .usage
= cmd_source_usage
,
1630 U_BOOT_CMD_HELP(cmd_source_help
)
1635 * @brief A prototype Bourne shell grammar parser
1638 /** @page sh_command Starting shell
1640 * Usage: sh \<filename\> [\<arguments\>]
1642 * Execute a shell script named \<filename\> and forward (if given)
1643 * \<arguments\> to it.
1645 * Usage: . \<filename\> [\<arguments\>]
1646 * or source \<filename\> [\<arguments\>]
1648 * Read and execute commands from \<filename\> in the current shell environment,
1649 * forward (if given) \<arguments\> to it and return the exit status of the last
1650 * command executed from filename.