driver: add dev_name inline
[barebox-mini2440.git] / common / hush.c
blobe4ae631bfff5bf276185049b318c4571b684ba1b
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 <environment.h>
117 #include <command.h> /* find_cmd */
118 #include <driver.h>
119 #include <errno.h>
120 #include <fs.h>
121 #include <libbb.h>
122 #include <glob.h>
124 /*cmd_boot.c*/
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
130 #define EOF -1
131 #define syntax() syntax_err()
132 #define xstrdup strdup
133 #define error_msg printf
135 typedef enum {
136 PIPE_SEQ = 1,
137 PIPE_AND = 2,
138 PIPE_OR = 3,
139 PIPE_BG = 4,
140 } pipe_style;
142 /* might eventually control execution */
143 typedef enum {
144 RES_NONE = 0,
145 RES_IF = 1,
146 RES_THEN = 2,
147 RES_ELIF = 3,
148 RES_ELSE = 4,
149 RES_FI = 5,
150 RES_FOR = 6,
151 RES_WHILE = 7,
152 RES_UNTIL = 8,
153 RES_DO = 9,
154 RES_DONE = 10,
155 RES_XXXX = 11,
156 RES_IN = 12,
157 RES_SNTX = 13
158 } reserved_style;
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 */
178 struct p_context {
179 struct child_prog *child;
180 struct pipe *list_head;
181 struct pipe *pipe;
182 reserved_style w;
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? */
188 char **global_argv;
189 unsigned int global_argc;
193 struct child_prog {
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 */
198 int type;
199 glob_t glob_result; /* result of parameter globbing */
202 struct pipe {
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 */
218 static uchar *ifs;
219 static char map[256];
221 #define B_CHUNK (100)
222 #define B_NOSPAC 1
224 typedef struct {
225 char *data;
226 int length;
227 int maxlen;
228 int quote;
229 int nonnull;
230 } o_string;
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? */
237 struct in_str {
238 const char *p;
239 int __promptme;
240 int promptmode;
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);
285 /* setup: */
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) {
306 free(old_data);
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))
316 return B_NOSPAC;
317 o->data[o->length] = ch;
318 o->length++;
319 o->data[o->length] = '\0';
320 return 0;
323 static void b_reset(o_string *o)
325 o->length = 0;
326 o->nonnull = 0;
327 if (o->data != NULL) *o->data = '\0';
330 static void b_free(o_string *o)
332 b_reset(o);
333 free(o->data);
334 o->data = NULL;
335 o->maxlen = 0;
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)) {
344 int rc;
345 rc = b_addchr(o, '\\');
346 if (rc)
347 return rc;
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];
358 *p-- = '\0';
359 do {
360 *p-- = '0' + i % 10;
361 i /= 10;
362 } while (i > 0);
363 return p + 1;
366 static int b_adduint(o_string *o, unsigned int i)
368 int r;
369 char *p = simple_itoa(i);
370 /* no escape checking necessary */
371 do {
372 r=b_addchr(o, *p++);
373 } while (r==0 && *p);
375 return r;
378 static int static_get(struct in_str *i)
380 int ch=*i->p++;
381 if (ch=='\0')
382 return EOF;
383 return ch;
387 static int static_peek(struct in_str *i)
389 return *i->p;
393 static char *getprompt(void)
395 static char *prompt;
397 if (!prompt)
398 prompt = xmalloc(PATH_MAX + strlen(CONFIG_PROMPT) + 1);
400 sprintf(prompt, "%s%s ", CONFIG_PROMPT, getcwd());
401 return prompt;
404 static void get_user_input(struct in_str *i)
406 int n;
407 static char the_command[CONFIG_CBSIZE];
409 i->__promptme = 1;
410 if (i->promptmode == 1) {
411 n = readline(getprompt(), console_buffer, CONFIG_CBSIZE);
412 } else {
413 n = readline(CONFIG_PROMPT_HUSH_PS2, console_buffer, CONFIG_CBSIZE);
415 if (n == -1 ) {
416 i->__promptme = 0;
417 n = 0;
420 console_buffer[n] = '\n';
421 console_buffer[n+1]= '\0';
422 if (i->promptmode == 1) {
423 strcpy(the_command,console_buffer);
424 i->p = the_command;
425 } else {
426 if (console_buffer[0] != '\n') {
427 if (strlen(the_command) + strlen(console_buffer)
428 < CONFIG_CBSIZE) {
429 n = strlen(the_command);
430 the_command[n-1] = ' ';
431 strcpy(&the_command[n],console_buffer);
433 else {
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)
450 int ch;
452 ch = 0;
453 /* If there is data waiting, eat it up */
454 if (i->p && *i->p) {
455 ch=*i->p++;
456 } else {
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 ) {
460 get_user_input(i);
462 i->promptmode=2;
463 if (i->p && *i->p) {
464 ch=*i->p++;
466 debug("b_getch: got a %d\n", ch);
468 return 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)
476 return *i->p;
479 static void setup_file_in_str(struct in_str *i)
481 i->peek = file_peek;
482 i->get = file_get;
483 i->__promptme=1;
484 i->promptmode=1;
485 i->p = NULL;
488 static void setup_string_in_str(struct in_str *i, const char *s)
490 i->peek = static_peek;
491 i->get = static_get;
492 i->__promptme=1;
493 i->promptmode=1;
494 i->p = s;
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
505 * return value.
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)
516 int i;
517 int nextin;
518 struct child_prog *child;
519 char *p;
520 char *path;
521 int ret;
522 # if __GNUC__
523 /* Avoid longjmp clobbering */
524 (void) &i;
525 (void) &nextin;
526 (void) &child;
527 # endif
529 nextin = 0;
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) {
538 int rcode;
539 debug("non-subshell grouping\n");
540 rcode = run_list_real(child->group);
541 return rcode;
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
553 * variable. */
554 int export_me=0;
555 char *name, *value;
556 name = xstrdup(child->argv[i]);
557 debug("Local environment set: %s\n", name);
558 value = strchr(name, '=');
559 if (value)
560 *value=0;
561 free(name);
562 p = insert_var_value(child->argv[i]);
563 set_local_var(p, export_me);
564 if (p != child->argv[i])
565 free(p);
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]);
571 set_local_var(p, 0);
572 if (p != child->argv[i]) {
573 child->sp--;
574 free(p);
577 if (child->sp) {
578 char * str = NULL;
579 struct p_context ctx;
580 str = make_string((child->argv + i));
581 parse_string_outer(&ctx, str, FLAG_EXIT_FROM_LOOP | FLAG_REPARSING);
582 free(str);
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]);
591 free(path);
592 return ret;
595 return execute_command(child->argc - i, &child->argv[i]);
597 return -1;
600 static int run_list_real(struct pipe *pi)
602 char *save_name = NULL;
603 char **list = NULL;
604 char **save_list = NULL;
605 struct pipe *rpipe;
606 int flag_rep = 0;
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)) {
616 syntax();
617 return 1;
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)) {
624 syntax();
625 return 1;
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) {
631 /* check Ctrl-C */
632 if (ctrlc())
633 return 1;
634 flag_restore = 0;
635 if (!rpipe) {
636 flag_rep = 0;
637 rpipe = pi;
640 rmode = pi->r_mode;
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;
644 continue;
646 flag_skip = 1;
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)
651 continue;
652 if (rmode == RES_ELSE && !if_code)
653 continue;
654 if (rmode == RES_ELIF && !if_code)
655 break;
656 if (rmode == RES_FOR && pi->num_progs) {
657 if (!list) {
658 /* if no variable values after "in" we skip "for" */
659 if (!pi->next->progs->argv)
660 continue;
661 /* create list of variable values */
662 list = make_list_in(pi->next->progs->argv,
663 pi->progs->argv[0]);
664 save_list = list;
665 save_name = pi->progs->argv[0];
666 pi->progs->argv[0] = NULL;
667 flag_rep = 1;
669 if (!(*list)) {
670 free(pi->progs->argv[0]);
671 free(save_list);
672 list = NULL;
673 flag_rep = 0;
674 pi->progs->argv[0] = save_name;
675 continue;
676 } else {
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++;
683 if (rmode == RES_IN)
684 continue;
685 if (rmode == RES_DO) {
686 if (!flag_rep)
687 continue;
689 if ((rmode == RES_DONE)) {
690 if (flag_rep) {
691 flag_restore = 1;
692 } else {
693 rpipe = NULL;
696 if (pi->num_progs == 0)
697 continue;
698 rcode = run_pipe_real(pi);
699 debug("run_pipe_real returned %d\n",rcode);
700 if (rcode < -1) {
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;
715 return rcode;
718 #ifdef DEBUG
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];
725 #endif
727 /* return code is the exit status of the pipe */
728 static int free_pipe(struct pipe *pi, int indent)
730 char **p;
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);
737 if (child->argv) {
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);
742 child->argv=NULL;
743 } else if (child->group) {
744 ret_code = free_pipe_list(child->group,indent+3);
745 final_printf("%s end group\n",indenter(indent));
746 } else {
747 final_printf("%s (nil)\n",indenter(indent));
750 free(pi->progs); /* children are an array, they get freed all at once */
751 pi->progs=NULL;
752 return ret_code;
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);
763 next=pi->next;
764 pi->next=NULL;
765 free(pi);
767 return rcode;
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)
779 int cnt=0, pathc;
780 const char *s;
781 char *dest;
782 for (cnt=1, s=src; s && *s; s++) {
783 if (*s == '\\') s++;
784 cnt++;
786 dest = xmalloc(cnt);
787 if (!(flags & GLOB_APPEND)) {
788 pglob->gl_pathv = NULL;
789 pglob->gl_pathc = 0;
790 pglob->gl_offs = 0;
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++) {
797 if (*s == '\\') s++;
798 *dest = *s;
800 *dest='\0';
801 return 0;
804 /* XXX broken if the last character is '\\', check that before calling */
805 static int glob_needed(const char *s)
807 #ifdef CONFIG_GLOB
808 for (; *s; s++) {
809 if (*s == '\\') s++;
810 if (strchr("*[?",*s))
811 return 1;
813 #endif
814 return 0;
817 static int xglob(o_string *dest, int flags, glob_t *pglob)
819 int gr;
821 /* short-circuit for null word */
822 /* we can code this better when the debug's are gone */
823 if (dest->length == 0) {
824 if (dest->nonnull) {
825 /* bash man page calls this an "explicit" null */
826 gr = globhack(dest->data, flags, pglob);
827 debug("globhack returned %d\n",gr);
828 } else {
829 return 0;
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);
839 } else {
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); */
847 return gr;
850 /* Select which version we will use */
851 static int run_list(struct pipe *pi)
853 int rcode = 0;
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);
861 return rcode;
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)
872 char *name, *value;
873 int ret;
875 /* might be possible! */
876 if (!isalpha(*s))
877 return -1;
879 name = strdup(s);
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) {
886 free(name);
887 return -1;
889 *value++ = 0;
891 ret = setenv(name, value);
892 free(name);
894 return ret;
899 static int is_assignment(const char *s)
901 if (s == NULL)
902 return 0;
904 if (!isalpha(*s))
905 return 0;
906 ++s;
907 while(isalnum(*s) || *s=='_' || *s=='.')
908 ++s;
909 return *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)
919 ctx->pipe=NULL;
920 ctx->child=NULL;
921 ctx->list_head=new_pipe();
922 ctx->pipe=ctx->list_head;
923 ctx->w=RES_NONE;
924 ctx->stack=NULL;
925 ctx->old_flag=0;
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 {
935 char *literal;
936 int code;
937 long flag;
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) {
970 syntax();
971 free(new);
972 ctx->w = RES_SNTX;
973 b_reset(dest);
974 return 1;
976 *new = *ctx; /* physical copy */
977 initialize_context(ctx);
978 ctx->stack=new;
979 } else if ( ctx->w == RES_NONE || ! (ctx->old_flag & (1<<r->code))) {
980 syntax();
981 ctx->w = RES_SNTX;
982 b_reset(dest);
983 return 1;
985 ctx->w=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);
991 old = ctx->stack;
992 old->child->group = ctx->list_head;
993 *ctx = *old; /* physical copy */
994 free(old);
996 b_reset (dest);
997 return 1;
1000 return 0;
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;
1009 int gr, flags = 0;
1011 debug("done_word: %s %p\n", dest->data, child);
1012 if (dest->length == 0 && !dest->nonnull) {
1013 debug(" true null, ignored\n");
1014 return 0;
1016 if (child->group) {
1017 syntax();
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;
1027 if (child->argv)
1028 flags |= GLOB_APPEND;
1030 gr = xglob(dest, flags, glob_target);
1031 if (gr)
1032 return 1;
1034 b_reset(dest);
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);
1043 return 0;
1046 /* The only possible error here is out of memory, in which case
1047 * xmalloc exits. */
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");
1062 return 0;
1063 } else if (prog) {
1064 pi->num_progs++;
1065 debug("done_command: num_progs incremented to %d\n",pi->num_progs);
1066 } else {
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;
1074 prog->argv = NULL;
1075 prog->group = NULL;
1076 prog->sp = 0;
1077 ctx->child = prog;
1078 prog->type = ctx->type;
1080 /* but ctx->pipe and ctx->list_head remain unchanged */
1081 return 0;
1084 static int done_pipe(struct p_context *ctx, pipe_style type)
1086 struct pipe *new_p;
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;
1091 new_p=new_pipe();
1092 ctx->pipe->next = new_p;
1093 ctx->pipe = new_p;
1094 ctx->child = NULL;
1095 done_command(ctx); /* set up new pipe to accept commands */
1096 return 0;
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)
1104 if (!src)
1105 return NULL;
1107 if (*src == '$')
1108 return get_dollar_var(src[1]);
1110 return getenv(src);
1113 static int parse_string(o_string *dest, struct p_context *ctx, const char *src)
1115 struct in_str foo;
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];
1124 buf[0] = '\0';
1125 switch (ch) {
1126 case '?':
1127 sprintf(buf, "%u", (unsigned int)last_return_code);
1128 break;
1129 default:
1130 return NULL;
1132 return buf;
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)
1138 int advance = 0, i;
1139 int ch = input->peek(input); /* first character after the $ */
1140 debug("handle_dollar: ch=%c\n",ch);
1141 if (isalpha(ch)) {
1142 b_addchr(dest, SPECIAL_VAR_SYMBOL);
1143 ctx->child->sp++;
1144 while(ch=b_peek(input),isalnum(ch) || ch=='_' || ch=='.') {
1145 b_getch(input);
1146 b_addchr(dest,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 */
1155 advance = 1;
1156 } else {
1157 switch (ch) {
1158 case '?':
1159 ctx->child->sp++;
1160 b_addchr(dest, SPECIAL_VAR_SYMBOL);
1161 b_addchr(dest, '$');
1162 b_addchr(dest, '?');
1163 b_addchr(dest, SPECIAL_VAR_SYMBOL);
1164 advance = 1;
1165 break;
1166 case '#':
1167 b_adduint(dest,ctx->global_argc ? ctx->global_argc-1 : 0);
1168 advance = 1;
1169 break;
1170 case '{':
1171 b_addchr(dest, SPECIAL_VAR_SYMBOL);
1172 ctx->child->sp++;
1173 b_getch(input);
1174 /* XXX maybe someone will try to escape the '}' */
1175 while(ch=b_getch(input),ch!=EOF && ch!='}') {
1176 b_addchr(dest,ch);
1178 if (ch != '}') {
1179 syntax();
1180 return 1;
1182 b_addchr(dest, SPECIAL_VAR_SYMBOL);
1183 break;
1184 default:
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.
1193 if (advance)
1194 b_getch(input);
1195 return 0;
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)
1203 unsigned int ch, m;
1204 int next;
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) {
1212 m = map[ch];
1213 if (input->__promptme == 0)
1214 return 1;
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);
1223 } else {
1224 if (m==2) { /* unquoted IFS */
1225 if (done_word(dest, ctx)) {
1226 return 1;
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");
1235 return 0;
1237 if (m!=2) {
1238 switch (ch) {
1239 case '#':
1240 if (dest->length == 0 && !dest->quote) {
1241 while(ch=b_peek(input),ch!=EOF && ch!='\n') {
1242 b_getch(input);
1244 } else {
1245 b_addqchr(dest, ch, dest->quote);
1247 break;
1248 case '\\':
1249 if (next == EOF) {
1250 syntax();
1251 return 1;
1253 b_addqchr(dest, '\\', dest->quote);
1254 b_addqchr(dest, b_getch(input), dest->quote);
1255 break;
1256 case '$':
1257 if (handle_dollar(dest, ctx, input)!=0)
1258 return 1;
1259 break;
1260 case '\'':
1261 dest->nonnull = 1;
1262 while(ch=b_getch(input),ch!=EOF && ch!='\'') {
1263 if(input->__promptme == 0)
1264 return 1;
1265 b_addchr(dest,ch);
1267 if (ch==EOF) {
1268 syntax();
1269 return 1;
1271 break;
1272 case '"':
1273 dest->nonnull = 1;
1274 dest->quote = !dest->quote;
1275 break;
1276 case ';':
1277 done_word(dest, ctx);
1278 done_pipe(ctx,PIPE_SEQ);
1279 break;
1280 case '&':
1281 done_word(dest, ctx);
1282 if (next=='&') {
1283 b_getch(input);
1284 done_pipe(ctx,PIPE_AND);
1285 } else {
1286 syntax_err();
1287 return 1;
1289 break;
1290 case '|':
1291 done_word(dest, ctx);
1292 if (next=='|') {
1293 b_getch(input);
1294 done_pipe(ctx,PIPE_OR);
1295 } else {
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". */
1299 syntax_err();
1300 return 1;
1302 break;
1303 default:
1304 syntax(); /* this is really an internal logic error */
1305 return 1;
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;
1320 return 0;
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");
1333 ifs = NULL;
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;
1352 int rcode;
1353 int code = 0;
1354 do {
1355 ctx->type = flag;
1356 initialize_context(ctx);
1357 update_ifs_map();
1358 if (!(flag & FLAG_PARSE_SEMICOLON) || (flag & FLAG_REPARSING))
1359 mapset((uchar *)";$&|", 0);
1360 inp->promptmode=1;
1361 rcode = parse_stream(&temp, ctx, inp, '\n');
1362 if (rcode != 1 && ctx->old_flag != 0) {
1363 syntax();
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);
1370 } else {
1371 free_pipe_list(ctx->list_head, 0);
1372 continue;
1374 if (code == -2) { /* exit */
1375 b_free(&temp);
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");
1380 code = 0;
1381 continue;
1383 code = last_return_code;
1384 break;
1386 } else {
1387 if (ctx->old_flag != 0) {
1388 free(ctx->stack);
1389 b_reset(&temp);
1391 if (inp->__promptme == 0)
1392 printf("<INTERRUPT>\n");
1393 inp->__promptme = 1;
1394 temp.nonnull = 0;
1395 temp.quote = 0;
1396 inp->p = NULL;
1397 free_pipe_list(ctx->list_head,0);
1399 b_free(&temp);
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;
1408 char *p;
1409 const char *cp;
1410 int rcode;
1412 if ( !s || !*s)
1413 return 1;
1415 cp = strchr(s, '\n');
1416 if (!cp || *++cp) {
1417 p = xmalloc(strlen(s) + 2);
1418 strcpy(p, s);
1419 strcat(p, "\n");
1420 setup_string_in_str(&input, p);
1421 rcode = parse_stream_outer(ctx, &input, flag);
1422 free(p);
1423 return rcode;
1424 } else {
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;
1433 int len;
1434 int done = 0;
1435 char *p, *res_str = NULL;
1436 const char *p1;
1438 while ((p = strchr(inp, SPECIAL_VAR_SYMBOL))) {
1439 if (p != inp) {
1440 len = p - inp;
1441 res_str = xrealloc(res_str, (res_str_len + len));
1442 strncpy((res_str + res_str_len), inp, len);
1443 res_str_len += len;
1445 inp = ++p;
1446 p = strchr(inp, SPECIAL_VAR_SYMBOL);
1447 *p = '\0';
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);
1452 res_str_len = len;
1454 *p = SPECIAL_VAR_SYMBOL;
1455 inp = ++p;
1456 done = 1;
1458 if (done) {
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'))) {
1462 *p = ' ';
1465 return (res_str == NULL) ? inp : res_str;
1468 static char **make_list_in(char **inp, char *name)
1470 int len, i;
1471 int name_len = strlen(name);
1472 int n = 0;
1473 char **list;
1474 char *p1, *p2, *p3;
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]);
1480 p1 = p3;
1481 while (*p1) {
1482 if ((*p1 == ' ')) {
1483 p1++;
1484 continue;
1486 if ((p2 = strchr(p1, ' '))) {
1487 len = p2 - p1;
1488 } else {
1489 len = strlen(p1);
1490 p2 = p1 + len;
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';
1500 p1 = p2;
1502 if (p3 != inp[i])
1503 free(p3);
1505 list[n] = NULL;
1506 return list;
1509 /* Make new string for parser */
1510 static char * make_string(char ** inp)
1512 char *p;
1513 char *str = NULL;
1514 int n;
1515 int len = 2;
1517 for (n = 0; inp[n]; n++) {
1518 p = insert_var_value(inp[n]);
1519 str = xrealloc(str, (len + strlen(p)));
1520 if (n) {
1521 strcat(str, " ");
1522 } else {
1523 *str = '\0';
1525 strcat(str, p);
1526 len = strlen(str) + 3;
1527 if (p != inp[n])
1528 free(p);
1530 len = strlen(str);
1531 *(str + len) = '\n';
1532 *(str + len + 1) = '\0';
1533 return str;
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[])
1544 int ret;
1546 env_push_context();
1547 ret = source_script(path, argc, argv);
1548 env_pop_context();
1550 return ret;
1553 static int source_script(const char *path, int argc, char *argv[])
1555 struct p_context ctx;
1556 char *script;
1557 int ret;
1559 ctx.global_argc = argc;
1560 ctx.global_argv = argv;
1562 script = read_file(path, NULL);
1563 if (!script) {
1564 perror("sh");
1565 return 1;
1568 ret = parse_string_outer(&ctx, script, FLAG_PARSE_SEMICOLON);
1570 free(script);
1572 return ret;
1575 int run_shell(void)
1577 int rcode;
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);
1583 return rcode;
1586 static int do_sh(cmd_tbl_t *cmdtp, int argc, char *argv[])
1588 if (argc < 2)
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"
1596 "\n"
1597 "Execute a shell script\n";
1599 U_BOOT_CMD_START(sh)
1600 .cmd = do_sh,
1601 .usage = "run shell script",
1602 U_BOOT_CMD_HELP(cmd_sh_help)
1603 U_BOOT_CMD_END
1605 static int do_source(cmd_tbl_t *cmdtp, int argc, char *argv[])
1607 if (argc < 2)
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"
1618 "\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,
1628 .cmd = do_source,
1629 .usage = cmd_source_usage,
1630 U_BOOT_CMD_HELP(cmd_source_help)
1631 U_BOOT_CMD_END
1634 * @file
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.