tftp: remove never reached state STATE_BAD_MAGIC
[barebox-mini2440.git] / common / hush.c
blob0ad5977218bf2615f482cb6077a12a3beecb1fac
1 /* vi: set sw=8 ts=8: */
2 /*
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>
10 * Credits:
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.
20 * Other credits:
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
34 * today's BusyBox.
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)
49 * - $_
50 * - ! negation operator for pipes
51 * - &> and >& redirection of stdout+stderr
52 * - Brace Expansion
53 * - Tilde Expansion
54 * - fancy forms of Parameter Expansion
55 * - aliases
56 * - Arithmetic Expansion
57 * - <(list) and >(list) Process Substitution
58 * - reserved words: case, esac, select, function
59 * - Here Documents ( << word )
60 * - Functions
62 * Major bugs:
63 * - job handling woefully incomplete and buggy
64 * - reserved word execution woefully incomplete and buggy
66 * to-do:
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
71 * - test magic exec
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)
90 * - recursion
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*/
113 #include <xfuncs.h>
114 #include <linux/ctype.h> /* isalpha, isdigit */
115 #include <common.h> /* readline */
116 #include <hush.h>
117 #include <environment.h>
118 #include <command.h> /* find_cmd */
119 #include <driver.h>
120 #include <errno.h>
121 #include <fs.h>
122 #include <libbb.h>
123 #include <glob.h>
125 /*cmd_boot.c*/
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
131 #define EOF -1
132 #define syntax() syntax_err()
133 #define xstrdup strdup
134 #define error_msg printf
136 typedef enum {
137 PIPE_SEQ = 1,
138 PIPE_AND = 2,
139 PIPE_OR = 3,
140 PIPE_BG = 4,
141 } pipe_style;
143 /* might eventually control execution */
144 typedef enum {
145 RES_NONE = 0,
146 RES_IF = 1,
147 RES_THEN = 2,
148 RES_ELIF = 3,
149 RES_ELSE = 4,
150 RES_FI = 5,
151 RES_FOR = 6,
152 RES_WHILE = 7,
153 RES_UNTIL = 8,
154 RES_DO = 9,
155 RES_DONE = 10,
156 RES_XXXX = 11,
157 RES_IN = 12,
158 RES_SNTX = 13
159 } reserved_style;
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 */
175 struct p_context {
176 struct child_prog *child;
177 struct pipe *list_head;
178 struct pipe *pipe;
179 reserved_style w;
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? */
185 char **global_argv;
186 unsigned int global_argc;
190 struct child_prog {
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 */
195 int type;
196 glob_t glob_result; /* result of parameter globbing */
199 struct pipe {
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 */
215 static uchar *ifs;
216 static char map[256];
218 #define B_CHUNK (100)
219 #define B_NOSPAC 1
221 typedef struct {
222 char *data;
223 int length;
224 int maxlen;
225 int quote;
226 int nonnull;
227 } o_string;
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? */
234 struct in_str {
235 const char *p;
236 int __promptme;
237 int promptmode;
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);
282 /* setup: */
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) {
303 free(old_data);
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))
313 return B_NOSPAC;
314 o->data[o->length] = ch;
315 o->length++;
316 o->data[o->length] = '\0';
317 return 0;
320 static void b_reset(o_string *o)
322 o->length = 0;
323 o->nonnull = 0;
324 if (o->data != NULL) *o->data = '\0';
327 static void b_free(o_string *o)
329 b_reset(o);
330 free(o->data);
331 o->data = NULL;
332 o->maxlen = 0;
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)) {
341 int rc;
342 rc = b_addchr(o, '\\');
343 if (rc)
344 return rc;
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];
355 *p-- = '\0';
356 do {
357 *p-- = '0' + i % 10;
358 i /= 10;
359 } while (i > 0);
360 return p + 1;
363 static int b_adduint(o_string *o, unsigned int i)
365 int r;
366 char *p = simple_itoa(i);
367 /* no escape checking necessary */
368 do {
369 r=b_addchr(o, *p++);
370 } while (r==0 && *p);
372 return r;
375 static int static_get(struct in_str *i)
377 int ch=*i->p++;
378 if (ch=='\0')
379 return EOF;
380 return ch;
384 static int static_peek(struct in_str *i)
386 return *i->p;
390 static char *getprompt(void)
392 static char *prompt;
394 if (!prompt)
395 prompt = xmalloc(PATH_MAX + strlen(CONFIG_PROMPT) + 1);
397 sprintf(prompt, "%s%s ", CONFIG_PROMPT, getcwd());
398 return prompt;
401 static void get_user_input(struct in_str *i)
403 int n;
404 static char the_command[CONFIG_CBSIZE];
406 i->__promptme = 1;
407 if (i->promptmode == 1) {
408 n = readline(getprompt(), console_buffer, CONFIG_CBSIZE);
409 } else {
410 n = readline(CONFIG_PROMPT_HUSH_PS2, console_buffer, CONFIG_CBSIZE);
412 if (n == -1 ) {
413 i->__promptme = 0;
414 n = 0;
417 console_buffer[n] = '\n';
418 console_buffer[n+1]= '\0';
419 if (i->promptmode == 1) {
420 strcpy(the_command,console_buffer);
421 i->p = the_command;
422 } else {
423 if (console_buffer[0] != '\n') {
424 if (strlen(the_command) + strlen(console_buffer)
425 < CONFIG_CBSIZE) {
426 n = strlen(the_command);
427 the_command[n-1] = ' ';
428 strcpy(&the_command[n],console_buffer);
430 else {
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)
447 int ch;
449 ch = 0;
450 /* If there is data waiting, eat it up */
451 if (i->p && *i->p) {
452 ch=*i->p++;
453 } else {
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 ) {
457 get_user_input(i);
459 i->promptmode=2;
460 if (i->p && *i->p) {
461 ch=*i->p++;
463 debug("b_getch: got a %d\n", ch);
465 return 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)
473 return *i->p;
476 static void setup_file_in_str(struct in_str *i)
478 i->peek = file_peek;
479 i->get = file_get;
480 i->__promptme=1;
481 i->promptmode=1;
482 i->p = NULL;
485 static void setup_string_in_str(struct in_str *i, const char *s)
487 i->peek = static_peek;
488 i->get = static_get;
489 i->__promptme=1;
490 i->promptmode=1;
491 i->p = s;
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
502 * return value.
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)
513 int i;
514 int nextin;
515 struct child_prog *child;
516 cmd_tbl_t *cmdtp;
517 char *p;
518 char *path;
519 int ret;
520 # if __GNUC__
521 /* Avoid longjmp clobbering */
522 (void) &i;
523 (void) &nextin;
524 (void) &child;
525 # endif
527 nextin = 0;
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) {
536 int rcode;
537 debug("non-subshell grouping\n");
538 rcode = run_list_real(child->group);
539 return rcode;
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
551 * variable. */
552 int export_me=0;
553 char *name, *value;
554 name = xstrdup(child->argv[i]);
555 debug("Local environment set: %s\n", name);
556 value = strchr(name, '=');
557 if (value)
558 *value=0;
559 free(name);
560 p = insert_var_value(child->argv[i]);
561 set_local_var(p, export_me);
562 if (p != child->argv[i])
563 free(p);
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]);
569 set_local_var(p, 0);
570 if (p != child->argv[i]) {
571 child->sp--;
572 free(p);
575 if (child->sp) {
576 char * str = NULL;
577 struct p_context ctx;
578 str = make_string((child->argv + i));
579 parse_string_outer(&ctx, str, FLAG_EXIT_FROM_LOOP | FLAG_REPARSING);
580 free(str);
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]);
589 free(path);
590 return ret;
592 /* Look up command in command table */
593 if ((cmdtp = find_cmd(child->argv[i]))) {
594 int rcode;
596 /* found - check max args */
597 if ((child->argc - i) > cmdtp->maxargs) {
598 printf ("Usage:\n%s\n", cmdtp->usage);
599 return -1;
601 /* OK - call function to do the command */
602 rcode = cmdtp->cmd(cmdtp, child->argc-i, &child->argv[i]);
604 return rcode;
605 } else {
606 printf ("Unknown command '%s' - try 'help'\n", child->argv[i]);
607 return -1; /* give up after bad command */
610 return -1;
613 static int run_list_real(struct pipe *pi)
615 char *save_name = NULL;
616 char **list = NULL;
617 char **save_list = NULL;
618 struct pipe *rpipe;
619 int flag_rep = 0;
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)) {
629 syntax();
630 return 1;
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)) {
637 syntax();
638 return 1;
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) {
644 /* check Ctrl-C */
645 if (ctrlc())
646 return 1;
647 flag_restore = 0;
648 if (!rpipe) {
649 flag_rep = 0;
650 rpipe = pi;
653 rmode = pi->r_mode;
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;
657 continue;
659 flag_skip = 1;
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)
664 continue;
665 if (rmode == RES_ELSE && !if_code)
666 continue;
667 if (rmode == RES_ELIF && !if_code)
668 break;
669 if (rmode == RES_FOR && pi->num_progs) {
670 if (!list) {
671 /* if no variable values after "in" we skip "for" */
672 if (!pi->next->progs->argv)
673 continue;
674 /* create list of variable values */
675 list = make_list_in(pi->next->progs->argv,
676 pi->progs->argv[0]);
677 save_list = list;
678 save_name = pi->progs->argv[0];
679 pi->progs->argv[0] = NULL;
680 flag_rep = 1;
682 if (!(*list)) {
683 free(pi->progs->argv[0]);
684 free(save_list);
685 list = NULL;
686 flag_rep = 0;
687 pi->progs->argv[0] = save_name;
688 continue;
689 } else {
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++;
696 if (rmode == RES_IN)
697 continue;
698 if (rmode == RES_DO) {
699 if (!flag_rep)
700 continue;
702 if ((rmode == RES_DONE)) {
703 if (flag_rep) {
704 flag_restore = 1;
705 } else {
706 rpipe = NULL;
709 if (pi->num_progs == 0)
710 continue;
711 rcode = run_pipe_real(pi);
712 debug("run_pipe_real returned %d\n",rcode);
713 if (rcode < -1) {
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;
728 return rcode;
731 #ifdef DEBUG
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];
738 #endif
740 /* return code is the exit status of the pipe */
741 static int free_pipe(struct pipe *pi, int indent)
743 char **p;
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);
750 if (child->argv) {
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);
755 child->argv=NULL;
756 } else if (child->group) {
757 ret_code = free_pipe_list(child->group,indent+3);
758 final_printf("%s end group\n",indenter(indent));
759 } else {
760 final_printf("%s (nil)\n",indenter(indent));
763 free(pi->progs); /* children are an array, they get freed all at once */
764 pi->progs=NULL;
765 return ret_code;
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);
776 next=pi->next;
777 pi->next=NULL;
778 free(pi);
780 return rcode;
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)
792 int cnt=0, pathc;
793 const char *s;
794 char *dest;
795 for (cnt=1, s=src; s && *s; s++) {
796 if (*s == '\\') s++;
797 cnt++;
799 dest = xmalloc(cnt);
800 if (!(flags & GLOB_APPEND)) {
801 pglob->gl_pathv = NULL;
802 pglob->gl_pathc = 0;
803 pglob->gl_offs = 0;
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++) {
810 if (*s == '\\') s++;
811 *dest = *s;
813 *dest='\0';
814 return 0;
817 /* XXX broken if the last character is '\\', check that before calling */
818 static int glob_needed(const char *s)
820 #ifdef CONFIG_GLOB
821 for (; *s; s++) {
822 if (*s == '\\') s++;
823 if (strchr("*[?",*s))
824 return 1;
826 #endif
827 return 0;
830 static int xglob(o_string *dest, int flags, glob_t *pglob)
832 int gr;
834 /* short-circuit for null word */
835 /* we can code this better when the debug's are gone */
836 if (dest->length == 0) {
837 if (dest->nonnull) {
838 /* bash man page calls this an "explicit" null */
839 gr = globhack(dest->data, flags, pglob);
840 debug("globhack returned %d\n",gr);
841 } else {
842 return 0;
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);
852 } else {
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); */
860 return gr;
863 /* Select which version we will use */
864 static int run_list(struct pipe *pi)
866 int rcode = 0;
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);
874 return rcode;
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)
885 char *name, *value;
886 int ret;
888 /* might be possible! */
889 if (!isalpha(*s))
890 return -1;
892 name = strdup(s);
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) {
899 free(name);
900 return -1;
902 *value++ = 0;
904 ret = setenv(name, value);
905 free(name);
907 return ret;
912 static int is_assignment(const char *s)
914 if (s == NULL)
915 return 0;
917 if (!isalpha(*s))
918 return 0;
919 ++s;
920 while(isalnum(*s) || *s=='_' || *s=='.')
921 ++s;
922 return *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)
932 ctx->pipe=NULL;
933 ctx->child=NULL;
934 ctx->list_head=new_pipe();
935 ctx->pipe=ctx->list_head;
936 ctx->w=RES_NONE;
937 ctx->stack=NULL;
938 ctx->old_flag=0;
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 {
948 char *literal;
949 int code;
950 long flag;
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) {
983 syntax();
984 free(new);
985 ctx->w = RES_SNTX;
986 b_reset(dest);
987 return 1;
989 *new = *ctx; /* physical copy */
990 initialize_context(ctx);
991 ctx->stack=new;
992 } else if ( ctx->w == RES_NONE || ! (ctx->old_flag & (1<<r->code))) {
993 syntax();
994 ctx->w = RES_SNTX;
995 b_reset(dest);
996 return 1;
998 ctx->w=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);
1004 old = ctx->stack;
1005 old->child->group = ctx->list_head;
1006 *ctx = *old; /* physical copy */
1007 free(old);
1009 b_reset (dest);
1010 return 1;
1013 return 0;
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;
1022 int gr, flags = 0;
1024 debug("done_word: %s %p\n", dest->data, child);
1025 if (dest->length == 0 && !dest->nonnull) {
1026 debug(" true null, ignored\n");
1027 return 0;
1029 if (child->group) {
1030 syntax();
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;
1040 if (child->argv)
1041 flags |= GLOB_APPEND;
1043 gr = xglob(dest, flags, glob_target);
1044 if (gr)
1045 return 1;
1047 b_reset(dest);
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);
1056 return 0;
1059 /* The only possible error here is out of memory, in which case
1060 * xmalloc exits. */
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");
1075 return 0;
1076 } else if (prog) {
1077 pi->num_progs++;
1078 debug("done_command: num_progs incremented to %d\n",pi->num_progs);
1079 } else {
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;
1087 prog->argv = NULL;
1088 prog->group = NULL;
1089 prog->sp = 0;
1090 ctx->child = prog;
1091 prog->type = ctx->type;
1093 /* but ctx->pipe and ctx->list_head remain unchanged */
1094 return 0;
1097 static int done_pipe(struct p_context *ctx, pipe_style type)
1099 struct pipe *new_p;
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;
1104 new_p=new_pipe();
1105 ctx->pipe->next = new_p;
1106 ctx->pipe = new_p;
1107 ctx->child = NULL;
1108 done_command(ctx); /* set up new pipe to accept commands */
1109 return 0;
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)
1117 if (!src)
1118 return NULL;
1120 if (*src == '$')
1121 return get_dollar_var(src[1]);
1123 return getenv(src);
1126 static int parse_string(o_string *dest, struct p_context *ctx, const char *src)
1128 struct in_str foo;
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];
1137 buf[0] = '\0';
1138 switch (ch) {
1139 case '?':
1140 sprintf(buf, "%u", (unsigned int)last_return_code);
1141 break;
1142 default:
1143 return NULL;
1145 return buf;
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)
1151 int advance = 0, i;
1152 int ch = input->peek(input); /* first character after the $ */
1153 debug("handle_dollar: ch=%c\n",ch);
1154 if (isalpha(ch)) {
1155 b_addchr(dest, SPECIAL_VAR_SYMBOL);
1156 ctx->child->sp++;
1157 while(ch=b_peek(input),isalnum(ch) || ch=='_' || ch=='.') {
1158 b_getch(input);
1159 b_addchr(dest,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 */
1168 advance = 1;
1169 } else {
1170 switch (ch) {
1171 case '?':
1172 ctx->child->sp++;
1173 b_addchr(dest, SPECIAL_VAR_SYMBOL);
1174 b_addchr(dest, '$');
1175 b_addchr(dest, '?');
1176 b_addchr(dest, SPECIAL_VAR_SYMBOL);
1177 advance = 1;
1178 break;
1179 case '#':
1180 b_adduint(dest,ctx->global_argc ? ctx->global_argc-1 : 0);
1181 advance = 1;
1182 break;
1183 case '{':
1184 b_addchr(dest, SPECIAL_VAR_SYMBOL);
1185 ctx->child->sp++;
1186 b_getch(input);
1187 /* XXX maybe someone will try to escape the '}' */
1188 while(ch=b_getch(input),ch!=EOF && ch!='}') {
1189 b_addchr(dest,ch);
1191 if (ch != '}') {
1192 syntax();
1193 return 1;
1195 b_addchr(dest, SPECIAL_VAR_SYMBOL);
1196 break;
1197 default:
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.
1206 if (advance)
1207 b_getch(input);
1208 return 0;
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)
1216 unsigned int ch, m;
1217 int next;
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) {
1225 m = map[ch];
1226 if (input->__promptme == 0)
1227 return 1;
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);
1236 } else {
1237 if (m==2) { /* unquoted IFS */
1238 if (done_word(dest, ctx)) {
1239 return 1;
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");
1248 return 0;
1250 if (m!=2) {
1251 switch (ch) {
1252 case '#':
1253 if (dest->length == 0 && !dest->quote) {
1254 while(ch=b_peek(input),ch!=EOF && ch!='\n') {
1255 b_getch(input);
1257 } else {
1258 b_addqchr(dest, ch, dest->quote);
1260 break;
1261 case '\\':
1262 if (next == EOF) {
1263 syntax();
1264 return 1;
1266 b_addqchr(dest, '\\', dest->quote);
1267 b_addqchr(dest, b_getch(input), dest->quote);
1268 break;
1269 case '$':
1270 if (handle_dollar(dest, ctx, input)!=0)
1271 return 1;
1272 break;
1273 case '\'':
1274 dest->nonnull = 1;
1275 while(ch=b_getch(input),ch!=EOF && ch!='\'') {
1276 if(input->__promptme == 0)
1277 return 1;
1278 b_addchr(dest,ch);
1280 if (ch==EOF) {
1281 syntax();
1282 return 1;
1284 break;
1285 case '"':
1286 dest->nonnull = 1;
1287 dest->quote = !dest->quote;
1288 break;
1289 case ';':
1290 done_word(dest, ctx);
1291 done_pipe(ctx,PIPE_SEQ);
1292 break;
1293 case '&':
1294 done_word(dest, ctx);
1295 if (next=='&') {
1296 b_getch(input);
1297 done_pipe(ctx,PIPE_AND);
1298 } else {
1299 syntax_err();
1300 return 1;
1302 break;
1303 case '|':
1304 done_word(dest, ctx);
1305 if (next=='|') {
1306 b_getch(input);
1307 done_pipe(ctx,PIPE_OR);
1308 } else {
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". */
1312 syntax_err();
1313 return 1;
1315 break;
1316 default:
1317 syntax(); /* this is really an internal logic error */
1318 return 1;
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;
1333 return 0;
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");
1346 ifs = NULL;
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;
1365 int rcode;
1366 int code = 0;
1367 do {
1368 ctx->type = flag;
1369 initialize_context(ctx);
1370 update_ifs_map();
1371 if (!(flag & FLAG_PARSE_SEMICOLON) || (flag & FLAG_REPARSING))
1372 mapset((uchar *)";$&|", 0);
1373 inp->promptmode=1;
1374 rcode = parse_stream(&temp, ctx, inp, '\n');
1375 if (rcode != 1 && ctx->old_flag != 0) {
1376 syntax();
1378 if (rcode != 1 && ctx->old_flag == 0) {
1379 done_word(&temp, ctx);
1380 done_pipe(ctx,PIPE_SEQ);
1381 if (ctx->list_head->num_progs) {
1382 code = run_list(ctx->list_head);
1383 } else {
1384 free_pipe_list(ctx->list_head, 0);
1385 continue;
1387 if (code == -2) { /* exit */
1388 b_free(&temp);
1390 /* XXX hackish way to not allow exit from main loop */
1391 if (inp->peek == file_peek) {
1392 printf("exit not allowed from main input shell.\n");
1393 code = 0;
1394 continue;
1396 code = last_return_code;
1397 break;
1399 } else {
1400 if (ctx->old_flag != 0) {
1401 free(ctx->stack);
1402 b_reset(&temp);
1404 if (inp->__promptme == 0)
1405 printf("<INTERRUPT>\n");
1406 inp->__promptme = 1;
1407 temp.nonnull = 0;
1408 temp.quote = 0;
1409 inp->p = NULL;
1410 free_pipe_list(ctx->list_head,0);
1412 b_free(&temp);
1413 } while (rcode != -1 && !(flag & FLAG_EXIT_FROM_LOOP)); /* loop on syntax errors, return on EOF */
1415 return (code != 0) ? 1 : 0;
1418 static int parse_string_outer(struct p_context *ctx, const char *s, int flag)
1420 struct in_str input;
1421 char *p;
1422 const char *cp;
1423 int rcode;
1425 if ( !s || !*s)
1426 return 1;
1428 cp = strchr(s, '\n');
1429 if (!cp || *++cp) {
1430 p = xmalloc(strlen(s) + 2);
1431 strcpy(p, s);
1432 strcat(p, "\n");
1433 setup_string_in_str(&input, p);
1434 rcode = parse_stream_outer(ctx, &input, flag);
1435 free(p);
1436 return rcode;
1437 } else {
1438 setup_string_in_str(&input, s);
1439 return parse_stream_outer(ctx, &input, flag);
1443 static char *insert_var_value(char *inp)
1445 int res_str_len = 0;
1446 int len;
1447 int done = 0;
1448 char *p, *res_str = NULL;
1449 const char *p1;
1451 while ((p = strchr(inp, SPECIAL_VAR_SYMBOL))) {
1452 if (p != inp) {
1453 len = p - inp;
1454 res_str = xrealloc(res_str, (res_str_len + len));
1455 strncpy((res_str + res_str_len), inp, len);
1456 res_str_len += len;
1458 inp = ++p;
1459 p = strchr(inp, SPECIAL_VAR_SYMBOL);
1460 *p = '\0';
1461 if ((p1 = lookup_param(inp))) {
1462 len = res_str_len + strlen(p1);
1463 res_str = xrealloc(res_str, (1 + len));
1464 strcpy((res_str + res_str_len), p1);
1465 res_str_len = len;
1467 *p = SPECIAL_VAR_SYMBOL;
1468 inp = ++p;
1469 done = 1;
1471 if (done) {
1472 res_str = xrealloc(res_str, (1 + res_str_len + strlen(inp)));
1473 strcpy((res_str + res_str_len), inp);
1474 while ((p = strchr(res_str, '\n'))) {
1475 *p = ' ';
1478 return (res_str == NULL) ? inp : res_str;
1481 static char **make_list_in(char **inp, char *name)
1483 int len, i;
1484 int name_len = strlen(name);
1485 int n = 0;
1486 char **list;
1487 char *p1, *p2, *p3;
1489 /* create list of variable values */
1490 list = xmalloc(sizeof(*list));
1491 for (i = 0; inp[i]; i++) {
1492 p3 = insert_var_value(inp[i]);
1493 p1 = p3;
1494 while (*p1) {
1495 if ((*p1 == ' ')) {
1496 p1++;
1497 continue;
1499 if ((p2 = strchr(p1, ' '))) {
1500 len = p2 - p1;
1501 } else {
1502 len = strlen(p1);
1503 p2 = p1 + len;
1505 /* we use n + 2 in realloc for list,because we add
1506 * new element and then we will add NULL element */
1507 list = xrealloc(list, sizeof(*list) * (n + 2));
1508 list[n] = xmalloc(2 + name_len + len);
1509 strcpy(list[n], name);
1510 strcat(list[n], "=");
1511 strncat(list[n], p1, len);
1512 list[n++][name_len + len + 1] = '\0';
1513 p1 = p2;
1515 if (p3 != inp[i])
1516 free(p3);
1518 list[n] = NULL;
1519 return list;
1522 /* Make new string for parser */
1523 static char * make_string(char ** inp)
1525 char *p;
1526 char *str = NULL;
1527 int n;
1528 int len = 2;
1530 for (n = 0; inp[n]; n++) {
1531 p = insert_var_value(inp[n]);
1532 str = xrealloc(str, (len + strlen(p)));
1533 if (n) {
1534 strcat(str, " ");
1535 } else {
1536 *str = '\0';
1538 strcat(str, p);
1539 len = strlen(str) + 3;
1540 if (p != inp[n])
1541 free(p);
1543 len = strlen(str);
1544 *(str + len) = '\n';
1545 *(str + len + 1) = '\0';
1546 return str;
1549 int run_command (const char *cmd, int flag)
1551 struct p_context ctx;
1552 return parse_string_outer(&ctx, cmd, FLAG_PARSE_SEMICOLON);
1555 static int execute_script(const char *path, int argc, char *argv[])
1557 int ret;
1559 env_push_context();
1560 ret = source_script(path, argc, argv);
1561 env_pop_context();
1563 return ret;
1566 static int source_script(const char *path, int argc, char *argv[])
1568 struct p_context ctx;
1569 char *script;
1570 int ret;
1572 ctx.global_argc = argc;
1573 ctx.global_argv = argv;
1575 script = read_file(path, NULL);
1576 if (!script) {
1577 perror("sh");
1578 return 1;
1581 ret = parse_string_outer(&ctx, script, FLAG_PARSE_SEMICOLON);
1583 free(script);
1585 return ret;
1588 int run_shell(void)
1590 int rcode;
1591 struct in_str input;
1592 struct p_context ctx;
1594 setup_file_in_str(&input);
1595 rcode = parse_stream_outer(&ctx, &input, FLAG_PARSE_SEMICOLON);
1596 return rcode;
1599 static int do_sh(cmd_tbl_t *cmdtp, int argc, char *argv[])
1601 if (argc < 2) {
1602 printf ("Usage:\n%s\n", cmdtp->usage);
1603 return 1;
1606 return execute_script(argv[1], argc - 1, argv + 1);
1609 static const __maybe_unused char cmd_sh_help[] =
1610 "Usage: sh filename [arguments]\n"
1611 "\n"
1612 "Execute a shell script\n";
1614 U_BOOT_CMD_START(sh)
1615 .maxargs = CONFIG_MAXARGS,
1616 .cmd = do_sh,
1617 .usage = "run shell script",
1618 U_BOOT_CMD_HELP(cmd_sh_help)
1619 U_BOOT_CMD_END
1621 static int do_source(cmd_tbl_t *cmdtp, int argc, char *argv[])
1623 if (argc < 2) {
1624 printf ("Usage:\n%s\n", cmdtp->usage);
1625 return 1;
1628 return source_script(argv[1], argc - 1, argv + 1);
1631 static const char *source_aliases[] = { ".", NULL};
1633 static const __maybe_unused char cmd_source_help[] =
1634 "Usage: . filename [arguments]\n"
1635 "or source filename [arguments]\n"
1636 "\n"
1637 "Read and execute commands from filename in the current shell\n"
1638 "environment and return the exit status of the last command exe-\n"
1639 "cuted from filename\n";
1641 static const __maybe_unused char cmd_source_usage[] =
1642 "execute shell script in current shell environment";
1644 U_BOOT_CMD_START(source)
1645 .maxargs = CONFIG_MAXARGS,
1646 .aliases = source_aliases,
1647 .cmd = do_source,
1648 .usage = cmd_source_usage,
1649 U_BOOT_CMD_HELP(cmd_source_help)
1650 U_BOOT_CMD_END
1653 * @file
1654 * @brief A prototype Bourne shell grammar parser
1657 /** @page sh_command Starting shell
1659 * Usage: sh \<filename\> [\<arguments\>]
1661 * Execute a shell script named \<filename\> and forward (if given)
1662 * \<arguments\> to it.
1664 * Usage: . \<filename\> [\<arguments\>]
1665 * or source \<filename\> [\<arguments\>]
1667 * Read and execute commands from \<filename\> in the current shell environment,
1668 * forward (if given) \<arguments\> to it and return the exit status of the last
1669 * command executed from filename.