uboot/common/cli_hush.c
<<
>>
Prefs
   1/*
   2 * sh.c -- a prototype Bourne shell grammar parser
   3 *      Intended to follow the original Thompson and Ritchie
   4 *      "small and simple is beautiful" philosophy, which
   5 *      incidentally is a good match to today's BusyBox.
   6 *
   7 * Copyright (C) 2000,2001  Larry Doolittle  <larry@doolittle.boa.org>
   8 *
   9 * Credits:
  10 *      The parser routines proper are all original material, first
  11 *      written Dec 2000 and Jan 2001 by Larry Doolittle.
  12 *      The execution engine, the builtins, and much of the underlying
  13 *      support has been adapted from busybox-0.49pre's lash,
  14 *      which is Copyright (C) 2000 by Lineo, Inc., and
  15 *      written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>.
  16 *      That, in turn, is based in part on ladsh.c, by Michael K. Johnson and
  17 *      Erik W. Troan, which they placed in the public domain.  I don't know
  18 *      how much of the Johnson/Troan code has survived the repeated rewrites.
  19 * Other credits:
  20 *      b_addchr() derived from similar w_addchar function in glibc-2.2
  21 *      setup_redirect(), redirect_opt_num(), and big chunks of main()
  22 *        and many builtins derived from contributions by Erik Andersen
  23 *      miscellaneous bugfixes from Matt Kraai
  24 *
  25 * There are two big (and related) architecture differences between
  26 * this parser and the lash parser.  One is that this version is
  27 * actually designed from the ground up to understand nearly all
  28 * of the Bourne grammar.  The second, consequential change is that
  29 * the parser and input reader have been turned inside out.  Now,
  30 * the parser is in control, and asks for input as needed.  The old
  31 * way had the input reader in control, and it asked for parsing to
  32 * take place as needed.  The new way makes it much easier to properly
  33 * handle the recursion implicit in the various substitutions, especially
  34 * across continuation lines.
  35 *
  36 * Bash grammar not implemented: (how many of these were in original sh?)
  37 *      $@ (those sure look like weird quoting rules)
  38 *      $_
  39 *      ! negation operator for pipes
  40 *      &> and >& redirection of stdout+stderr
  41 *      Brace Expansion
  42 *      Tilde Expansion
  43 *      fancy forms of Parameter Expansion
  44 *      aliases
  45 *      Arithmetic Expansion
  46 *      <(list) and >(list) Process Substitution
  47 *      reserved words: case, esac, select, function
  48 *      Here Documents ( << word )
  49 *      Functions
  50 * Major bugs:
  51 *      job handling woefully incomplete and buggy
  52 *      reserved word execution woefully incomplete and buggy
  53 * to-do:
  54 *      port selected bugfixes from post-0.49 busybox lash - done?
  55 *      finish implementing reserved words: for, while, until, do, done
  56 *      change { and } from special chars to reserved words
  57 *      builtins: break, continue, eval, return, set, trap, ulimit
  58 *      test magic exec
  59 *      handle children going into background
  60 *      clean up recognition of null pipes
  61 *      check setting of global_argc and global_argv
  62 *      control-C handling, probably with longjmp
  63 *      follow IFS rules more precisely, including update semantics
  64 *      figure out what to do with backslash-newline
  65 *      explain why we use signal instead of sigaction
  66 *      propagate syntax errors, die on resource errors?
  67 *      continuation lines, both explicit and implicit - done?
  68 *      memory leak finding and plugging - done?
  69 *      more testing, especially quoting rules and redirection
  70 *      document how quoting rules not precisely followed for variable assignments
  71 *      maybe change map[] to use 2-bit entries
  72 *      (eventually) remove all the printf's
  73 *
  74 * SPDX-License-Identifier:     GPL-2.0+
  75 */
  76
  77#define __U_BOOT__
  78#ifdef __U_BOOT__
  79#include <malloc.h>         /* malloc, free, realloc*/
  80#include <linux/ctype.h>    /* isalpha, isdigit */
  81#include <common.h>        /* readline */
  82#include <bootretry.h>
  83#include <cli.h>
  84#include <cli_hush.h>
  85#include <command.h>        /* find_cmd */
  86#ifndef CONFIG_SYS_PROMPT_HUSH_PS2
  87#define CONFIG_SYS_PROMPT_HUSH_PS2      "> "
  88#endif
  89#endif
  90#ifndef __U_BOOT__
  91#include <ctype.h>     /* isalpha, isdigit */
  92#include <unistd.h>    /* getpid */
  93#include <stdlib.h>    /* getenv, atoi */
  94#include <string.h>    /* strchr */
  95#include <stdio.h>     /* popen etc. */
  96#include <glob.h>      /* glob, of course */
  97#include <stdarg.h>    /* va_list */
  98#include <errno.h>
  99#include <fcntl.h>
 100#include <getopt.h>    /* should be pretty obvious */
 101
 102#include <sys/stat.h>  /* ulimit */
 103#include <sys/types.h>
 104#include <sys/wait.h>
 105#include <signal.h>
 106
 107/* #include <dmalloc.h> */
 108
 109#if 1
 110#include "busybox.h"
 111#include "cmdedit.h"
 112#else
 113#define applet_name "hush"
 114#include "standalone.h"
 115#define hush_main main
 116#undef CONFIG_FEATURE_SH_FANCY_PROMPT
 117#define BB_BANNER
 118#endif
 119#endif
 120#define SPECIAL_VAR_SYMBOL 03
 121#define SUBSTED_VAR_SYMBOL 04
 122#ifndef __U_BOOT__
 123#define FLAG_EXIT_FROM_LOOP 1
 124#define FLAG_PARSE_SEMICOLON (1 << 1)           /* symbol ';' is special for parser */
 125#define FLAG_REPARSING       (1 << 2)           /* >= 2nd pass */
 126
 127#endif
 128
 129#ifdef __U_BOOT__
 130DECLARE_GLOBAL_DATA_PTR;
 131
 132#define EXIT_SUCCESS 0
 133#define EOF -1
 134#define syntax() syntax_err()
 135#define xstrdup strdup
 136#define error_msg printf
 137#else
 138typedef enum {
 139        REDIRECT_INPUT     = 1,
 140        REDIRECT_OVERWRITE = 2,
 141        REDIRECT_APPEND    = 3,
 142        REDIRECT_HEREIS    = 4,
 143        REDIRECT_IO        = 5
 144} redir_type;
 145
 146/* The descrip member of this structure is only used to make debugging
 147 * output pretty */
 148struct {int mode; int default_fd; char *descrip;} redir_table[] = {
 149        { 0,                         0, "()" },
 150        { O_RDONLY,                  0, "<"  },
 151        { O_CREAT|O_TRUNC|O_WRONLY,  1, ">"  },
 152        { O_CREAT|O_APPEND|O_WRONLY, 1, ">>" },
 153        { O_RDONLY,                 -1, "<<" },
 154        { O_RDWR,                    1, "<>" }
 155};
 156#endif
 157
 158typedef enum {
 159        PIPE_SEQ = 1,
 160        PIPE_AND = 2,
 161        PIPE_OR  = 3,
 162        PIPE_BG  = 4,
 163} pipe_style;
 164
 165/* might eventually control execution */
 166typedef enum {
 167        RES_NONE  = 0,
 168        RES_IF    = 1,
 169        RES_THEN  = 2,
 170        RES_ELIF  = 3,
 171        RES_ELSE  = 4,
 172        RES_FI    = 5,
 173        RES_FOR   = 6,
 174        RES_WHILE = 7,
 175        RES_UNTIL = 8,
 176        RES_DO    = 9,
 177        RES_DONE  = 10,
 178        RES_XXXX  = 11,
 179        RES_IN    = 12,
 180        RES_SNTX  = 13
 181} reserved_style;
 182#define FLAG_END   (1<<RES_NONE)
 183#define FLAG_IF    (1<<RES_IF)
 184#define FLAG_THEN  (1<<RES_THEN)
 185#define FLAG_ELIF  (1<<RES_ELIF)
 186#define FLAG_ELSE  (1<<RES_ELSE)
 187#define FLAG_FI    (1<<RES_FI)
 188#define FLAG_FOR   (1<<RES_FOR)
 189#define FLAG_WHILE (1<<RES_WHILE)
 190#define FLAG_UNTIL (1<<RES_UNTIL)
 191#define FLAG_DO    (1<<RES_DO)
 192#define FLAG_DONE  (1<<RES_DONE)
 193#define FLAG_IN    (1<<RES_IN)
 194#define FLAG_START (1<<RES_XXXX)
 195
 196/* This holds pointers to the various results of parsing */
 197struct p_context {
 198        struct child_prog *child;
 199        struct pipe *list_head;
 200        struct pipe *pipe;
 201#ifndef __U_BOOT__
 202        struct redir_struct *pending_redirect;
 203#endif
 204        reserved_style w;
 205        int old_flag;                           /* for figuring out valid reserved words */
 206        struct p_context *stack;
 207        int type;                       /* define type of parser : ";$" common or special symbol */
 208        /* How about quoting status? */
 209};
 210
 211#ifndef __U_BOOT__
 212struct redir_struct {
 213        redir_type type;                        /* type of redirection */
 214        int fd;                                         /* file descriptor being redirected */
 215        int dup;                                        /* -1, or file descriptor being duplicated */
 216        struct redir_struct *next;      /* pointer to the next redirect in the list */
 217        glob_t word;                            /* *word.gl_pathv is the filename */
 218};
 219#endif
 220
 221struct child_prog {
 222#ifndef __U_BOOT__
 223        pid_t pid;                                      /* 0 if exited */
 224#endif
 225        char **argv;                            /* program name and arguments */
 226        /* was quoted when parsed; copy of struct o_string.nonnull field */
 227        int *argv_nonnull;
 228#ifdef __U_BOOT__
 229        int    argc;                            /* number of program arguments */
 230#endif
 231        struct pipe *group;                     /* if non-NULL, first in group or subshell */
 232#ifndef __U_BOOT__
 233        int subshell;                           /* flag, non-zero if group must be forked */
 234        struct redir_struct *redirects; /* I/O redirections */
 235        glob_t glob_result;                     /* result of parameter globbing */
 236        int is_stopped;                         /* is the program currently running? */
 237        struct pipe *family;            /* pointer back to the child's parent pipe */
 238#endif
 239        int sp;                         /* number of SPECIAL_VAR_SYMBOL */
 240        int type;
 241};
 242
 243struct pipe {
 244#ifndef __U_BOOT__
 245        int jobid;                                      /* job number */
 246#endif
 247        int num_progs;                          /* total number of programs in job */
 248#ifndef __U_BOOT__
 249        int running_progs;                      /* number of programs running */
 250        char *text;                                     /* name of job */
 251        char *cmdbuf;                           /* buffer various argv's point into */
 252        pid_t pgrp;                                     /* process group ID for the job */
 253#endif
 254        struct child_prog *progs;       /* array of commands in pipe */
 255        struct pipe *next;                      /* to track background commands */
 256#ifndef __U_BOOT__
 257        int stopped_progs;                      /* number of programs alive, but stopped */
 258        int job_context;                        /* bitmask defining current context */
 259#endif
 260        pipe_style followup;            /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */
 261        reserved_style r_mode;          /* supports if, for, while, until */
 262};
 263
 264#ifndef __U_BOOT__
 265struct close_me {
 266        int fd;
 267        struct close_me *next;
 268};
 269#endif
 270
 271struct variables {
 272        char *name;
 273        char *value;
 274        int flg_export;
 275        int flg_read_only;
 276        struct variables *next;
 277};
 278
 279/* globals, connect us to the outside world
 280 * the first three support $?, $#, and $1 */
 281#ifndef __U_BOOT__
 282char **global_argv;
 283unsigned int global_argc;
 284#endif
 285static unsigned int last_return_code;
 286#ifndef __U_BOOT__
 287extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */
 288#endif
 289
 290/* "globals" within this file */
 291static uchar *ifs;
 292static char map[256];
 293#ifndef __U_BOOT__
 294static int fake_mode;
 295static int interactive;
 296static struct close_me *close_me_head;
 297static const char *cwd;
 298static struct pipe *job_list;
 299static unsigned int last_bg_pid;
 300static unsigned int last_jobid;
 301static unsigned int shell_terminal;
 302static char *PS1;
 303static char *PS2;
 304struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 };
 305struct variables *top_vars = &shell_ver;
 306#else
 307static int flag_repeat = 0;
 308static int do_repeat = 0;
 309static struct variables *top_vars = NULL ;
 310#endif /*__U_BOOT__ */
 311
 312#define B_CHUNK (100)
 313#define B_NOSPAC 1
 314
 315typedef struct {
 316        char *data;
 317        int length;
 318        int maxlen;
 319        int quote;
 320        int nonnull;
 321} o_string;
 322#define NULL_O_STRING {NULL,0,0,0,0}
 323/* used for initialization:
 324        o_string foo = NULL_O_STRING; */
 325
 326/* I can almost use ordinary FILE *.  Is open_memstream() universally
 327 * available?  Where is it documented? */
 328struct in_str {
 329        const char *p;
 330#ifndef __U_BOOT__
 331        char peek_buf[2];
 332#endif
 333        int __promptme;
 334        int promptmode;
 335#ifndef __U_BOOT__
 336        FILE *file;
 337#endif
 338        int (*get) (struct in_str *);
 339        int (*peek) (struct in_str *);
 340};
 341#define b_getch(input) ((input)->get(input))
 342#define b_peek(input) ((input)->peek(input))
 343
 344#ifndef __U_BOOT__
 345#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
 346
 347struct built_in_command {
 348        char *cmd;                                      /* name */
 349        char *descr;                            /* description */
 350        int (*function) (struct child_prog *);  /* function ptr */
 351};
 352#endif
 353
 354/* define DEBUG_SHELL for debugging output (obviously ;-)) */
 355#if 0
 356#define DEBUG_SHELL
 357#endif
 358
 359/* This should be in utility.c */
 360#ifdef DEBUG_SHELL
 361#ifndef __U_BOOT__
 362static void debug_printf(const char *format, ...)
 363{
 364        va_list args;
 365        va_start(args, format);
 366        vfprintf(stderr, format, args);
 367        va_end(args);
 368}
 369#else
 370#define debug_printf(fmt,args...)       printf (fmt ,##args)
 371#endif
 372#else
 373static inline void debug_printf(const char *format, ...) { }
 374#endif
 375#define final_printf debug_printf
 376
 377#ifdef __U_BOOT__
 378static void syntax_err(void) {
 379         printf("syntax error\n");
 380}
 381#else
 382static void __syntax(char *file, int line) {
 383        error_msg("syntax error %s:%d", file, line);
 384}
 385#define syntax() __syntax(__FILE__, __LINE__)
 386#endif
 387
 388#ifdef __U_BOOT__
 389static void *xmalloc(size_t size);
 390static void *xrealloc(void *ptr, size_t size);
 391#else
 392/* Index of subroutines: */
 393/*   function prototypes for builtins */
 394static int builtin_cd(struct child_prog *child);
 395static int builtin_env(struct child_prog *child);
 396static int builtin_eval(struct child_prog *child);
 397static int builtin_exec(struct child_prog *child);
 398static int builtin_exit(struct child_prog *child);
 399static int builtin_export(struct child_prog *child);
 400static int builtin_fg_bg(struct child_prog *child);
 401static int builtin_help(struct child_prog *child);
 402static int builtin_jobs(struct child_prog *child);
 403static int builtin_pwd(struct child_prog *child);
 404static int builtin_read(struct child_prog *child);
 405static int builtin_set(struct child_prog *child);
 406static int builtin_shift(struct child_prog *child);
 407static int builtin_source(struct child_prog *child);
 408static int builtin_umask(struct child_prog *child);
 409static int builtin_unset(struct child_prog *child);
 410static int builtin_not_written(struct child_prog *child);
 411#endif
 412/*   o_string manipulation: */
 413static int b_check_space(o_string *o, int len);
 414static int b_addchr(o_string *o, int ch);
 415static void b_reset(o_string *o);
 416static int b_addqchr(o_string *o, int ch, int quote);
 417#ifndef __U_BOOT__
 418static int b_adduint(o_string *o, unsigned int i);
 419#endif
 420/*  in_str manipulations: */
 421static int static_get(struct in_str *i);
 422static int static_peek(struct in_str *i);
 423static int file_get(struct in_str *i);
 424static int file_peek(struct in_str *i);
 425#ifndef __U_BOOT__
 426static void setup_file_in_str(struct in_str *i, FILE *f);
 427#else
 428static void setup_file_in_str(struct in_str *i);
 429#endif
 430static void setup_string_in_str(struct in_str *i, const char *s);
 431#ifndef __U_BOOT__
 432/*  close_me manipulations: */
 433static void mark_open(int fd);
 434static void mark_closed(int fd);
 435static void close_all(void);
 436#endif
 437/*  "run" the final data structures: */
 438static char *indenter(int i);
 439static int free_pipe_list(struct pipe *head, int indent);
 440static int free_pipe(struct pipe *pi, int indent);
 441/*  really run the final data structures: */
 442#ifndef __U_BOOT__
 443static int setup_redirects(struct child_prog *prog, int squirrel[]);
 444#endif
 445static int run_list_real(struct pipe *pi);
 446#ifndef __U_BOOT__
 447static void pseudo_exec(struct child_prog *child) __attribute__ ((noreturn));
 448#endif
 449static int run_pipe_real(struct pipe *pi);
 450/*   extended glob support: */
 451#ifndef __U_BOOT__
 452static int globhack(const char *src, int flags, glob_t *pglob);
 453static int glob_needed(const char *s);
 454static int xglob(o_string *dest, int flags, glob_t *pglob);
 455#endif
 456/*   variable assignment: */
 457static int is_assignment(const char *s);
 458/*   data structure manipulation: */
 459#ifndef __U_BOOT__
 460static int setup_redirect(struct p_context *ctx, int fd, redir_type style, struct in_str *input);
 461#endif
 462static void initialize_context(struct p_context *ctx);
 463static int done_word(o_string *dest, struct p_context *ctx);
 464static int done_command(struct p_context *ctx);
 465static int done_pipe(struct p_context *ctx, pipe_style type);
 466/*   primary string parsing: */
 467#ifndef __U_BOOT__
 468static int redirect_dup_num(struct in_str *input);
 469static int redirect_opt_num(o_string *o);
 470static int process_command_subs(o_string *dest, struct p_context *ctx, struct in_str *input, int subst_end);
 471static int parse_group(o_string *dest, struct p_context *ctx, struct in_str *input, int ch);
 472#endif
 473static char *lookup_param(char *src);
 474static char *make_string(char **inp, int *nonnull);
 475static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input);
 476#ifndef __U_BOOT__
 477static int parse_string(o_string *dest, struct p_context *ctx, const char *src);
 478#endif
 479static int parse_stream(o_string *dest, struct p_context *ctx, struct in_str *input0, int end_trigger);
 480/*   setup: */
 481static int parse_stream_outer(struct in_str *inp, int flag);
 482#ifndef __U_BOOT__
 483static int parse_string_outer(const char *s, int flag);
 484static int parse_file_outer(FILE *f);
 485#endif
 486#ifndef __U_BOOT__
 487/*   job management: */
 488static int checkjobs(struct pipe* fg_pipe);
 489static void insert_bg_job(struct pipe *pi);
 490static void remove_bg_job(struct pipe *pi);
 491#endif
 492/*     local variable support */
 493static char **make_list_in(char **inp, char *name);
 494static char *insert_var_value(char *inp);
 495static char *insert_var_value_sub(char *inp, int tag_subst);
 496
 497#ifndef __U_BOOT__
 498/* Table of built-in functions.  They can be forked or not, depending on
 499 * context: within pipes, they fork.  As simple commands, they do not.
 500 * When used in non-forking context, they can change global variables
 501 * in the parent shell process.  If forked, of course they can not.
 502 * For example, 'unset foo | whatever' will parse and run, but foo will
 503 * still be set at the end. */
 504static struct built_in_command bltins[] = {
 505        {"bg", "Resume a job in the background", builtin_fg_bg},
 506        {"break", "Exit for, while or until loop", builtin_not_written},
 507        {"cd", "Change working directory", builtin_cd},
 508        {"continue", "Continue for, while or until loop", builtin_not_written},
 509        {"env", "Print all environment variables", builtin_env},
 510        {"eval", "Construct and run shell command", builtin_eval},
 511        {"exec", "Exec command, replacing this shell with the exec'd process",
 512                builtin_exec},
 513        {"exit", "Exit from shell()", builtin_exit},
 514        {"export", "Set environment variable", builtin_export},
 515        {"fg", "Bring job into the foreground", builtin_fg_bg},
 516        {"jobs", "Lists the active jobs", builtin_jobs},
 517        {"pwd", "Print current directory", builtin_pwd},
 518        {"read", "Input environment variable", builtin_read},
 519        {"return", "Return from a function", builtin_not_written},
 520        {"set", "Set/unset shell local variables", builtin_set},
 521        {"shift", "Shift positional parameters", builtin_shift},
 522        {"trap", "Trap signals", builtin_not_written},
 523        {"ulimit","Controls resource limits", builtin_not_written},
 524        {"umask","Sets file creation mask", builtin_umask},
 525        {"unset", "Unset environment variable", builtin_unset},
 526        {".", "Source-in and run commands in a file", builtin_source},
 527        {"help", "List shell built-in commands", builtin_help},
 528        {NULL, NULL, NULL}
 529};
 530
 531static const char *set_cwd(void)
 532{
 533        if(cwd==unknown)
 534                cwd = NULL;     /* xgetcwd(arg) called free(arg) */
 535        cwd = xgetcwd((char *)cwd);
 536        if (!cwd)
 537                cwd = unknown;
 538        return cwd;
 539}
 540
 541/* built-in 'eval' handler */
 542static int builtin_eval(struct child_prog *child)
 543{
 544        char *str = NULL;
 545        int rcode = EXIT_SUCCESS;
 546
 547        if (child->argv[1]) {
 548                str = make_string(child->argv + 1);
 549                parse_string_outer(str, FLAG_EXIT_FROM_LOOP |
 550                                        FLAG_PARSE_SEMICOLON);
 551                free(str);
 552                rcode = last_return_code;
 553        }
 554        return rcode;
 555}
 556
 557/* built-in 'cd <path>' handler */
 558static int builtin_cd(struct child_prog *child)
 559{
 560        char *newdir;
 561        if (child->argv[1] == NULL)
 562                newdir = getenv("HOME");
 563        else
 564                newdir = child->argv[1];
 565        if (chdir(newdir)) {
 566                printf("cd: %s: %s\n", newdir, strerror(errno));
 567                return EXIT_FAILURE;
 568        }
 569        set_cwd();
 570        return EXIT_SUCCESS;
 571}
 572
 573/* built-in 'env' handler */
 574static int builtin_env(struct child_prog *dummy)
 575{
 576        char **e = environ;
 577        if (e == NULL) return EXIT_FAILURE;
 578        for (; *e; e++) {
 579                puts(*e);
 580        }
 581        return EXIT_SUCCESS;
 582}
 583
 584/* built-in 'exec' handler */
 585static int builtin_exec(struct child_prog *child)
 586{
 587        if (child->argv[1] == NULL)
 588                return EXIT_SUCCESS;   /* Really? */
 589        child->argv++;
 590        pseudo_exec(child);
 591        /* never returns */
 592}
 593
 594/* built-in 'exit' handler */
 595static int builtin_exit(struct child_prog *child)
 596{
 597        if (child->argv[1] == NULL)
 598                exit(last_return_code);
 599        exit (atoi(child->argv[1]));
 600}
 601
 602/* built-in 'export VAR=value' handler */
 603static int builtin_export(struct child_prog *child)
 604{
 605        int res = 0;
 606        char *name = child->argv[1];
 607
 608        if (name == NULL) {
 609                return (builtin_env(child));
 610        }
 611
 612        name = strdup(name);
 613
 614        if(name) {
 615                char *value = strchr(name, '=');
 616
 617                if (!value) {
 618                        char *tmp;
 619                        /* They are exporting something without an =VALUE */
 620
 621                        value = get_local_var(name);
 622                        if (value) {
 623                                size_t ln = strlen(name);
 624
 625                                tmp = realloc(name, ln+strlen(value)+2);
 626                                if(tmp==NULL)
 627                                        res = -1;
 628                                else {
 629                                        sprintf(tmp+ln, "=%s", value);
 630                                        name = tmp;
 631                                }
 632                        } else {
 633                                /* bash does not return an error when trying to export
 634                                 * an undefined variable.  Do likewise. */
 635                                res = 1;
 636                        }
 637                }
 638        }
 639        if (res<0)
 640                perror_msg("export");
 641        else if(res==0)
 642                res = set_local_var(name, 1);
 643        else
 644                res = 0;
 645        free(name);
 646        return res;
 647}
 648
 649/* built-in 'fg' and 'bg' handler */
 650static int builtin_fg_bg(struct child_prog *child)
 651{
 652        int i, jobnum;
 653        struct pipe *pi=NULL;
 654
 655        if (!interactive)
 656                return EXIT_FAILURE;
 657        /* If they gave us no args, assume they want the last backgrounded task */
 658        if (!child->argv[1]) {
 659                for (pi = job_list; pi; pi = pi->next) {
 660                        if (pi->jobid == last_jobid) {
 661                                break;
 662                        }
 663                }
 664                if (!pi) {
 665                        error_msg("%s: no current job", child->argv[0]);
 666                        return EXIT_FAILURE;
 667                }
 668        } else {
 669                if (sscanf(child->argv[1], "%%%d", &jobnum) != 1) {
 670                        error_msg("%s: bad argument '%s'", child->argv[0], child->argv[1]);
 671                        return EXIT_FAILURE;
 672                }
 673                for (pi = job_list; pi; pi = pi->next) {
 674                        if (pi->jobid == jobnum) {
 675                                break;
 676                        }
 677                }
 678                if (!pi) {
 679                        error_msg("%s: %d: no such job", child->argv[0], jobnum);
 680                        return EXIT_FAILURE;
 681                }
 682        }
 683
 684        if (*child->argv[0] == 'f') {
 685                /* Put the job into the foreground.  */
 686                tcsetpgrp(shell_terminal, pi->pgrp);
 687        }
 688
 689        /* Restart the processes in the job */
 690        for (i = 0; i < pi->num_progs; i++)
 691                pi->progs[i].is_stopped = 0;
 692
 693        if ( (i=kill(- pi->pgrp, SIGCONT)) < 0) {
 694                if (i == ESRCH) {
 695                        remove_bg_job(pi);
 696                } else {
 697                        perror_msg("kill (SIGCONT)");
 698                }
 699        }
 700
 701        pi->stopped_progs = 0;
 702        return EXIT_SUCCESS;
 703}
 704
 705/* built-in 'help' handler */
 706static int builtin_help(struct child_prog *dummy)
 707{
 708        struct built_in_command *x;
 709
 710        printf("\nBuilt-in commands:\n");
 711        printf("-------------------\n");
 712        for (x = bltins; x->cmd; x++) {
 713                if (x->descr==NULL)
 714                        continue;
 715                printf("%s\t%s\n", x->cmd, x->descr);
 716        }
 717        printf("\n\n");
 718        return EXIT_SUCCESS;
 719}
 720
 721/* built-in 'jobs' handler */
 722static int builtin_jobs(struct child_prog *child)
 723{
 724        struct pipe *job;
 725        char *status_string;
 726
 727        for (job = job_list; job; job = job->next) {
 728                if (job->running_progs == job->stopped_progs)
 729                        status_string = "Stopped";
 730                else
 731                        status_string = "Running";
 732
 733                printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text);
 734        }
 735        return EXIT_SUCCESS;
 736}
 737
 738
 739/* built-in 'pwd' handler */
 740static int builtin_pwd(struct child_prog *dummy)
 741{
 742        puts(set_cwd());
 743        return EXIT_SUCCESS;
 744}
 745
 746/* built-in 'read VAR' handler */
 747static int builtin_read(struct child_prog *child)
 748{
 749        int res;
 750
 751        if (child->argv[1]) {
 752                char string[BUFSIZ];
 753                char *var = 0;
 754
 755                string[0] = 0;  /* In case stdin has only EOF */
 756                /* read string */
 757                fgets(string, sizeof(string), stdin);
 758                chomp(string);
 759                var = malloc(strlen(child->argv[1])+strlen(string)+2);
 760                if(var) {
 761                        sprintf(var, "%s=%s", child->argv[1], string);
 762                        res = set_local_var(var, 0);
 763                } else
 764                        res = -1;
 765                if (res)
 766                        fprintf(stderr, "read: %m\n");
 767                free(var);      /* So not move up to avoid breaking errno */
 768                return res;
 769        } else {
 770                do res=getchar(); while(res!='\n' && res!=EOF);
 771                return 0;
 772        }
 773}
 774
 775/* built-in 'set VAR=value' handler */
 776static int builtin_set(struct child_prog *child)
 777{
 778        char *temp = child->argv[1];
 779        struct variables *e;
 780
 781        if (temp == NULL)
 782                for(e = top_vars; e; e=e->next)
 783                        printf("%s=%s\n", e->name, e->value);
 784        else
 785                set_local_var(temp, 0);
 786
 787                return EXIT_SUCCESS;
 788}
 789
 790
 791/* Built-in 'shift' handler */
 792static int builtin_shift(struct child_prog *child)
 793{
 794        int n=1;
 795        if (child->argv[1]) {
 796                n=atoi(child->argv[1]);
 797        }
 798        if (n>=0 && n<global_argc) {
 799                /* XXX This probably breaks $0 */
 800                global_argc -= n;
 801                global_argv += n;
 802                return EXIT_SUCCESS;
 803        } else {
 804                return EXIT_FAILURE;
 805        }
 806}
 807
 808/* Built-in '.' handler (read-in and execute commands from file) */
 809static int builtin_source(struct child_prog *child)
 810{
 811        FILE *input;
 812        int status;
 813
 814        if (child->argv[1] == NULL)
 815                return EXIT_FAILURE;
 816
 817        /* XXX search through $PATH is missing */
 818        input = fopen(child->argv[1], "r");
 819        if (!input) {
 820                error_msg("Couldn't open file '%s'", child->argv[1]);
 821                return EXIT_FAILURE;
 822        }
 823
 824        /* Now run the file */
 825        /* XXX argv and argc are broken; need to save old global_argv
 826         * (pointer only is OK!) on this stack frame,
 827         * set global_argv=child->argv+1, recurse, and restore. */
 828        mark_open(fileno(input));
 829        status = parse_file_outer(input);
 830        mark_closed(fileno(input));
 831        fclose(input);
 832        return (status);
 833}
 834
 835static int builtin_umask(struct child_prog *child)
 836{
 837        mode_t new_umask;
 838        const char *arg = child->argv[1];
 839        char *end;
 840        if (arg) {
 841                new_umask=strtoul(arg, &end, 8);
 842                if (*end!='\0' || end == arg) {
 843                        return EXIT_FAILURE;
 844                }
 845        } else {
 846                printf("%.3o\n", (unsigned int) (new_umask=umask(0)));
 847        }
 848        umask(new_umask);
 849        return EXIT_SUCCESS;
 850}
 851
 852/* built-in 'unset VAR' handler */
 853static int builtin_unset(struct child_prog *child)
 854{
 855        /* bash returned already true */
 856        unset_local_var(child->argv[1]);
 857        return EXIT_SUCCESS;
 858}
 859
 860static int builtin_not_written(struct child_prog *child)
 861{
 862        printf("builtin_%s not written\n",child->argv[0]);
 863        return EXIT_FAILURE;
 864}
 865#endif
 866
 867static int b_check_space(o_string *o, int len)
 868{
 869        /* It would be easy to drop a more restrictive policy
 870         * in here, such as setting a maximum string length */
 871        if (o->length + len > o->maxlen) {
 872                char *old_data = o->data;
 873                /* assert (data == NULL || o->maxlen != 0); */
 874                o->maxlen += max(2*len, B_CHUNK);
 875                o->data = realloc(o->data, 1 + o->maxlen);
 876                if (o->data == NULL) {
 877                        free(old_data);
 878                }
 879        }
 880        return o->data == NULL;
 881}
 882
 883static int b_addchr(o_string *o, int ch)
 884{
 885        debug_printf("b_addchr: %c %d %p\n", ch, o->length, o);
 886        if (b_check_space(o, 1)) return B_NOSPAC;
 887        o->data[o->length] = ch;
 888        o->length++;
 889        o->data[o->length] = '\0';
 890        return 0;
 891}
 892
 893static void b_reset(o_string *o)
 894{
 895        o->length = 0;
 896        o->nonnull = 0;
 897        if (o->data != NULL) *o->data = '\0';
 898}
 899
 900static void b_free(o_string *o)
 901{
 902        b_reset(o);
 903        free(o->data);
 904        o->data = NULL;
 905        o->maxlen = 0;
 906}
 907
 908/* My analysis of quoting semantics tells me that state information
 909 * is associated with a destination, not a source.
 910 */
 911static int b_addqchr(o_string *o, int ch, int quote)
 912{
 913        if (quote && strchr("*?[\\",ch)) {
 914                int rc;
 915                rc = b_addchr(o, '\\');
 916                if (rc) return rc;
 917        }
 918        return b_addchr(o, ch);
 919}
 920
 921#ifndef __U_BOOT__
 922static int b_adduint(o_string *o, unsigned int i)
 923{
 924        int r;
 925        char *p = simple_itoa(i);
 926        /* no escape checking necessary */
 927        do r=b_addchr(o, *p++); while (r==0 && *p);
 928        return r;
 929}
 930#endif
 931
 932static int static_get(struct in_str *i)
 933{
 934        int ch = *i->p++;
 935        if (ch=='\0') return EOF;
 936        return ch;
 937}
 938
 939static int static_peek(struct in_str *i)
 940{
 941        return *i->p;
 942}
 943
 944#ifndef __U_BOOT__
 945static inline void cmdedit_set_initial_prompt(void)
 946{
 947#ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
 948        PS1 = NULL;
 949#else
 950        PS1 = getenv("PS1");
 951        if(PS1==0)
 952                PS1 = "\\w \\$ ";
 953#endif
 954}
 955
 956static inline void setup_prompt_string(int promptmode, char **prompt_str)
 957{
 958        debug_printf("setup_prompt_string %d ",promptmode);
 959#ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
 960        /* Set up the prompt */
 961        if (promptmode == 1) {
 962                free(PS1);
 963                PS1=xmalloc(strlen(cwd)+4);
 964                sprintf(PS1, "%s %s", cwd, ( geteuid() != 0 ) ?  "$ ":"# ");
 965                *prompt_str = PS1;
 966        } else {
 967                *prompt_str = PS2;
 968        }
 969#else
 970        *prompt_str = (promptmode==1)? PS1 : PS2;
 971#endif
 972        debug_printf("result %s\n",*prompt_str);
 973}
 974#endif
 975
 976static void get_user_input(struct in_str *i)
 977{
 978#ifndef __U_BOOT__
 979        char *prompt_str;
 980        static char the_command[BUFSIZ];
 981
 982        setup_prompt_string(i->promptmode, &prompt_str);
 983#ifdef CONFIG_FEATURE_COMMAND_EDITING
 984        /*
 985         ** enable command line editing only while a command line
 986         ** is actually being read; otherwise, we'll end up bequeathing
 987         ** atexit() handlers and other unwanted stuff to our
 988         ** child processes (rob@sysgo.de)
 989         */
 990        cmdedit_read_input(prompt_str, the_command);
 991#else
 992        fputs(prompt_str, stdout);
 993        fflush(stdout);
 994        the_command[0]=fgetc(i->file);
 995        the_command[1]='\0';
 996#endif
 997        fflush(stdout);
 998        i->p = the_command;
 999#else
1000        int n;
1001        static char the_command[CONFIG_SYS_CBSIZE + 1];
1002
1003        bootretry_reset_cmd_timeout();
1004        i->__promptme = 1;
1005        if (i->promptmode == 1) {
1006                n = cli_readline(CONFIG_SYS_PROMPT);
1007        } else {
1008                n = cli_readline(CONFIG_SYS_PROMPT_HUSH_PS2);
1009        }
1010#ifdef CONFIG_BOOT_RETRY_TIME
1011        if (n == -2) {
1012          puts("\nTimeout waiting for command\n");
1013#  ifdef CONFIG_RESET_TO_RETRY
1014          do_reset(NULL, 0, 0, NULL);
1015#  else
1016#       error "This currently only works with CONFIG_RESET_TO_RETRY enabled"
1017#  endif
1018        }
1019#endif
1020        if (n == -1 ) {
1021                flag_repeat = 0;
1022                i->__promptme = 0;
1023        }
1024        n = strlen(console_buffer);
1025        console_buffer[n] = '\n';
1026        console_buffer[n+1]= '\0';
1027        if (had_ctrlc()) flag_repeat = 0;
1028        clear_ctrlc();
1029        do_repeat = 0;
1030        if (i->promptmode == 1) {
1031                if (console_buffer[0] == '\n'&& flag_repeat == 0) {
1032                        strcpy(the_command,console_buffer);
1033                }
1034                else {
1035                        if (console_buffer[0] != '\n') {
1036                                strcpy(the_command,console_buffer);
1037                                flag_repeat = 1;
1038                        }
1039                        else {
1040                                do_repeat = 1;
1041                        }
1042                }
1043                i->p = the_command;
1044        }
1045        else {
1046                if (console_buffer[0] != '\n') {
1047                        if (strlen(the_command) + strlen(console_buffer)
1048                            < CONFIG_SYS_CBSIZE) {
1049                                n = strlen(the_command);
1050                                the_command[n-1] = ' ';
1051                                strcpy(&the_command[n],console_buffer);
1052                        }
1053                        else {
1054                                the_command[0] = '\n';
1055                                the_command[1] = '\0';
1056                                flag_repeat = 0;
1057                        }
1058                }
1059                if (i->__promptme == 0) {
1060                        the_command[0] = '\n';
1061                        the_command[1] = '\0';
1062                }
1063                i->p = console_buffer;
1064        }
1065#endif
1066}
1067
1068/* This is the magic location that prints prompts
1069 * and gets data back from the user */
1070static int file_get(struct in_str *i)
1071{
1072        int ch;
1073
1074        ch = 0;
1075        /* If there is data waiting, eat it up */
1076        if (i->p && *i->p) {
1077                ch = *i->p++;
1078        } else {
1079                /* need to double check i->file because we might be doing something
1080                 * more complicated by now, like sourcing or substituting. */
1081#ifndef __U_BOOT__
1082                if (i->__promptme && interactive && i->file == stdin) {
1083                        while(! i->p || (interactive && strlen(i->p)==0) ) {
1084#else
1085                        while(! i->p  || strlen(i->p)==0 ) {
1086#endif
1087                                get_user_input(i);
1088                        }
1089                        i->promptmode=2;
1090#ifndef __U_BOOT__
1091                        i->__promptme = 0;
1092#endif
1093                        if (i->p && *i->p) {
1094                                ch = *i->p++;
1095                        }
1096#ifndef __U_BOOT__
1097                } else {
1098                        ch = fgetc(i->file);
1099                }
1100
1101#endif
1102                debug_printf("b_getch: got a %d\n", ch);
1103        }
1104#ifndef __U_BOOT__
1105        if (ch == '\n') i->__promptme=1;
1106#endif
1107        return ch;
1108}
1109
1110/* All the callers guarantee this routine will never be
1111 * used right after a newline, so prompting is not needed.
1112 */
1113static int file_peek(struct in_str *i)
1114{
1115#ifndef __U_BOOT__
1116        if (i->p && *i->p) {
1117#endif
1118                return *i->p;
1119#ifndef __U_BOOT__
1120        } else {
1121                i->peek_buf[0] = fgetc(i->file);
1122                i->peek_buf[1] = '\0';
1123                i->p = i->peek_buf;
1124                debug_printf("b_peek: got a %d\n", *i->p);
1125                return *i->p;
1126        }
1127#endif
1128}
1129
1130#ifndef __U_BOOT__
1131static void setup_file_in_str(struct in_str *i, FILE *f)
1132#else
1133static void setup_file_in_str(struct in_str *i)
1134#endif
1135{
1136        i->peek = file_peek;
1137        i->get = file_get;
1138        i->__promptme=1;
1139        i->promptmode=1;
1140#ifndef __U_BOOT__
1141        i->file = f;
1142#endif
1143        i->p = NULL;
1144}
1145
1146static void setup_string_in_str(struct in_str *i, const char *s)
1147{
1148        i->peek = static_peek;
1149        i->get = static_get;
1150        i->__promptme=1;
1151        i->promptmode=1;
1152        i->p = s;
1153}
1154
1155#ifndef __U_BOOT__
1156static void mark_open(int fd)
1157{
1158        struct close_me *new = xmalloc(sizeof(struct close_me));
1159        new->fd = fd;
1160        new->next = close_me_head;
1161        close_me_head = new;
1162}
1163
1164static void mark_closed(int fd)
1165{
1166        struct close_me *tmp;
1167        if (close_me_head == NULL || close_me_head->fd != fd)
1168                error_msg_and_die("corrupt close_me");
1169        tmp = close_me_head;
1170        close_me_head = close_me_head->next;
1171        free(tmp);
1172}
1173
1174static void close_all(void)
1175{
1176        struct close_me *c;
1177        for (c=close_me_head; c; c=c->next) {
1178                close(c->fd);
1179        }
1180        close_me_head = NULL;
1181}
1182
1183/* squirrel != NULL means we squirrel away copies of stdin, stdout,
1184 * and stderr if they are redirected. */
1185static int setup_redirects(struct child_prog *prog, int squirrel[])
1186{
1187        int openfd, mode;
1188        struct redir_struct *redir;
1189
1190        for (redir=prog->redirects; redir; redir=redir->next) {
1191                if (redir->dup == -1 && redir->word.gl_pathv == NULL) {
1192                        /* something went wrong in the parse.  Pretend it didn't happen */
1193                        continue;
1194                }
1195                if (redir->dup == -1) {
1196                        mode=redir_table[redir->type].mode;
1197                        openfd = open(redir->word.gl_pathv[0], mode, 0666);
1198                        if (openfd < 0) {
1199                        /* this could get lost if stderr has been redirected, but
1200                           bash and ash both lose it as well (though zsh doesn't!) */
1201                                perror_msg("error opening %s", redir->word.gl_pathv[0]);
1202                                return 1;
1203                        }
1204                } else {
1205                        openfd = redir->dup;
1206                }
1207
1208                if (openfd != redir->fd) {
1209                        if (squirrel && redir->fd < 3) {
1210                                squirrel[redir->fd] = dup(redir->fd);
1211                        }
1212                        if (openfd == -3) {
1213                                close(openfd);
1214                        } else {
1215                                dup2(openfd, redir->fd);
1216                                if (redir->dup == -1)
1217                                        close (openfd);
1218                        }
1219                }
1220        }
1221        return 0;
1222}
1223
1224static void restore_redirects(int squirrel[])
1225{
1226        int i, fd;
1227        for (i=0; i<3; i++) {
1228                fd = squirrel[i];
1229                if (fd != -1) {
1230                        /* No error checking.  I sure wouldn't know what
1231                         * to do with an error if I found one! */
1232                        dup2(fd, i);
1233                        close(fd);
1234                }
1235        }
1236}
1237
1238/* never returns */
1239/* XXX no exit() here.  If you don't exec, use _exit instead.
1240 * The at_exit handlers apparently confuse the calling process,
1241 * in particular stdin handling.  Not sure why? */
1242static void pseudo_exec(struct child_prog *child)
1243{
1244        int i, rcode;
1245        char *p;
1246        struct built_in_command *x;
1247        if (child->argv) {
1248                for (i=0; is_assignment(child->argv[i]); i++) {
1249                        debug_printf("pid %d environment modification: %s\n",getpid(),child->argv[i]);
1250                        p = insert_var_value(child->argv[i]);
1251                        putenv(strdup(p));
1252                        if (p != child->argv[i]) free(p);
1253                }
1254                child->argv+=i;  /* XXX this hack isn't so horrible, since we are about
1255                                        to exit, and therefore don't need to keep data
1256                                        structures consistent for free() use. */
1257                /* If a variable is assigned in a forest, and nobody listens,
1258                 * was it ever really set?
1259                 */
1260                if (child->argv[0] == NULL) {
1261                        _exit(EXIT_SUCCESS);
1262                }
1263
1264                /*
1265                 * Check if the command matches any of the builtins.
1266                 * Depending on context, this might be redundant.  But it's
1267                 * easier to waste a few CPU cycles than it is to figure out
1268                 * if this is one of those cases.
1269                 */
1270                for (x = bltins; x->cmd; x++) {
1271                        if (strcmp(child->argv[0], x->cmd) == 0 ) {
1272                                debug_printf("builtin exec %s\n", child->argv[0]);
1273                                rcode = x->function(child);
1274                                fflush(stdout);
1275                                _exit(rcode);
1276                        }
1277                }
1278
1279                /* Check if the command matches any busybox internal commands
1280                 * ("applets") here.
1281                 * FIXME: This feature is not 100% safe, since
1282                 * BusyBox is not fully reentrant, so we have no guarantee the things
1283                 * from the .bss are still zeroed, or that things from .data are still
1284                 * at their defaults.  We could exec ourself from /proc/self/exe, but I
1285                 * really dislike relying on /proc for things.  We could exec ourself
1286                 * from global_argv[0], but if we are in a chroot, we may not be able
1287                 * to find ourself... */
1288#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
1289                {
1290                        int argc_l;
1291                        char** argv_l=child->argv;
1292                        char *name = child->argv[0];
1293
1294#ifdef CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN
1295                        /* Following discussions from November 2000 on the busybox mailing
1296                         * list, the default configuration, (without
1297                         * get_last_path_component()) lets the user force use of an
1298                         * external command by specifying the full (with slashes) filename.
1299                         * If you enable CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN then applets
1300                         * _aways_ override external commands, so if you want to run
1301                         * /bin/cat, it will use BusyBox cat even if /bin/cat exists on the
1302                         * filesystem and is _not_ busybox.  Some systems may want this,
1303                         * most do not.  */
1304                        name = get_last_path_component(name);
1305#endif
1306                        /* Count argc for use in a second... */
1307                        for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++);
1308                        optind = 1;
1309                        debug_printf("running applet %s\n", name);
1310                        run_applet_by_name(name, argc_l, child->argv);
1311                }
1312#endif
1313                debug_printf("exec of %s\n",child->argv[0]);
1314                execvp(child->argv[0],child->argv);
1315                perror_msg("couldn't exec: %s",child->argv[0]);
1316                _exit(1);
1317        } else if (child->group) {
1318                debug_printf("runtime nesting to group\n");
1319                interactive=0;    /* crucial!!!! */
1320                rcode = run_list_real(child->group);
1321                /* OK to leak memory by not calling free_pipe_list,
1322                 * since this process is about to exit */
1323                _exit(rcode);
1324        } else {
1325                /* Can happen.  See what bash does with ">foo" by itself. */
1326                debug_printf("trying to pseudo_exec null command\n");
1327                _exit(EXIT_SUCCESS);
1328        }
1329}
1330
1331static void insert_bg_job(struct pipe *pi)
1332{
1333        struct pipe *thejob;
1334
1335        /* Linear search for the ID of the job to use */
1336        pi->jobid = 1;
1337        for (thejob = job_list; thejob; thejob = thejob->next)
1338                if (thejob->jobid >= pi->jobid)
1339                        pi->jobid = thejob->jobid + 1;
1340
1341        /* add thejob to the list of running jobs */
1342        if (!job_list) {
1343                thejob = job_list = xmalloc(sizeof(*thejob));
1344        } else {
1345                for (thejob = job_list; thejob->next; thejob = thejob->next) /* nothing */;
1346                thejob->next = xmalloc(sizeof(*thejob));
1347                thejob = thejob->next;
1348        }
1349
1350        /* physically copy the struct job */
1351        memcpy(thejob, pi, sizeof(struct pipe));
1352        thejob->next = NULL;
1353        thejob->running_progs = thejob->num_progs;
1354        thejob->stopped_progs = 0;
1355        thejob->text = xmalloc(BUFSIZ); /* cmdedit buffer size */
1356
1357        /*if (pi->progs[0] && pi->progs[0].argv && pi->progs[0].argv[0]) */
1358        {
1359                char *bar=thejob->text;
1360                char **foo=pi->progs[0].argv;
1361                while(foo && *foo) {
1362                        bar += sprintf(bar, "%s ", *foo++);
1363                }
1364        }
1365
1366        /* we don't wait for background thejobs to return -- append it
1367           to the list of backgrounded thejobs and leave it alone */
1368        printf("[%d] %d\n", thejob->jobid, thejob->progs[0].pid);
1369        last_bg_pid = thejob->progs[0].pid;
1370        last_jobid = thejob->jobid;
1371}
1372
1373/* remove a backgrounded job */
1374static void remove_bg_job(struct pipe *pi)
1375{
1376        struct pipe *prev_pipe;
1377
1378        if (pi == job_list) {
1379                job_list = pi->next;
1380        } else {
1381                prev_pipe = job_list;
1382                while (prev_pipe->next != pi)
1383                        prev_pipe = prev_pipe->next;
1384                prev_pipe->next = pi->next;
1385        }
1386        if (job_list)
1387                last_jobid = job_list->jobid;
1388        else
1389                last_jobid = 0;
1390
1391        pi->stopped_progs = 0;
1392        free_pipe(pi, 0);
1393        free(pi);
1394}
1395
1396/* Checks to see if any processes have exited -- if they
1397   have, figure out why and see if a job has completed */
1398static int checkjobs(struct pipe* fg_pipe)
1399{
1400        int attributes;
1401        int status;
1402        int prognum = 0;
1403        struct pipe *pi;
1404        pid_t childpid;
1405
1406        attributes = WUNTRACED;
1407        if (fg_pipe==NULL) {
1408                attributes |= WNOHANG;
1409        }
1410
1411        while ((childpid = waitpid(-1, &status, attributes)) > 0) {
1412                if (fg_pipe) {
1413                        int i, rcode = 0;
1414                        for (i=0; i < fg_pipe->num_progs; i++) {
1415                                if (fg_pipe->progs[i].pid == childpid) {
1416                                        if (i==fg_pipe->num_progs-1)
1417                                                rcode=WEXITSTATUS(status);
1418                                        (fg_pipe->num_progs)--;
1419                                        return(rcode);
1420                                }
1421                        }
1422                }
1423
1424                for (pi = job_list; pi; pi = pi->next) {
1425                        prognum = 0;
1426                        while (prognum < pi->num_progs && pi->progs[prognum].pid != childpid) {
1427                                prognum++;
1428                        }
1429                        if (prognum < pi->num_progs)
1430                                break;
1431                }
1432
1433                if(pi==NULL) {
1434                        debug_printf("checkjobs: pid %d was not in our list!\n", childpid);
1435                        continue;
1436                }
1437
1438                if (WIFEXITED(status) || WIFSIGNALED(status)) {
1439                        /* child exited */
1440                        pi->running_progs--;
1441                        pi->progs[prognum].pid = 0;
1442
1443                        if (!pi->running_progs) {
1444                                printf(JOB_STATUS_FORMAT, pi->jobid, "Done", pi->text);
1445                                remove_bg_job(pi);
1446                        }
1447                } else {
1448                        /* child stopped */
1449                        pi->stopped_progs++;
1450                        pi->progs[prognum].is_stopped = 1;
1451
1452#if 0
1453                        /* Printing this stuff is a pain, since it tends to
1454                         * overwrite the prompt an inconveinient moments.  So
1455                         * don't do that.  */
1456                        if (pi->stopped_progs == pi->num_progs) {
1457                                printf("\n"JOB_STATUS_FORMAT, pi->jobid, "Stopped", pi->text);
1458                        }
1459#endif
1460                }
1461        }
1462
1463        if (childpid == -1 && errno != ECHILD)
1464                perror_msg("waitpid");
1465
1466        /* move the shell to the foreground */
1467        /*if (interactive && tcsetpgrp(shell_terminal, getpgid(0))) */
1468        /*      perror_msg("tcsetpgrp-2"); */
1469        return -1;
1470}
1471
1472/* Figure out our controlling tty, checking in order stderr,
1473 * stdin, and stdout.  If check_pgrp is set, also check that
1474 * we belong to the foreground process group associated with
1475 * that tty.  The value of shell_terminal is needed in order to call
1476 * tcsetpgrp(shell_terminal, ...); */
1477void controlling_tty(int check_pgrp)
1478{
1479        pid_t curpgrp;
1480
1481        if ((curpgrp = tcgetpgrp(shell_terminal = 2)) < 0
1482                        && (curpgrp = tcgetpgrp(shell_terminal = 0)) < 0
1483                        && (curpgrp = tcgetpgrp(shell_terminal = 1)) < 0)
1484                goto shell_terminal_error;
1485
1486        if (check_pgrp && curpgrp != getpgid(0))
1487                goto shell_terminal_error;
1488
1489        return;
1490
1491shell_terminal_error:
1492                shell_terminal = -1;
1493                return;
1494}
1495#endif
1496
1497/* run_pipe_real() starts all the jobs, but doesn't wait for anything
1498 * to finish.  See checkjobs().
1499 *
1500 * return code is normally -1, when the caller has to wait for children
1501 * to finish to determine the exit status of the pipe.  If the pipe
1502 * is a simple builtin command, however, the action is done by the
1503 * time run_pipe_real returns, and the exit code is provided as the
1504 * return value.
1505 *
1506 * The input of the pipe is always stdin, the output is always
1507 * stdout.  The outpipe[] mechanism in BusyBox-0.48 lash is bogus,
1508 * because it tries to avoid running the command substitution in
1509 * subshell, when that is in fact necessary.  The subshell process
1510 * now has its stdout directed to the input of the appropriate pipe,
1511 * so this routine is noticeably simpler.
1512 */
1513static int run_pipe_real(struct pipe *pi)
1514{
1515        int i;
1516#ifndef __U_BOOT__
1517        int nextin, nextout;
1518        int pipefds[2];                         /* pipefds[0] is for reading */
1519        struct child_prog *child;
1520        struct built_in_command *x;
1521        char *p;
1522# if __GNUC__
1523        /* Avoid longjmp clobbering */
1524        (void) &i;
1525        (void) &nextin;
1526        (void) &nextout;
1527        (void) &child;
1528# endif
1529#else
1530        int nextin;
1531        int flag = do_repeat ? CMD_FLAG_REPEAT : 0;
1532        struct child_prog *child;
1533        char *p;
1534# if __GNUC__
1535        /* Avoid longjmp clobbering */
1536        (void) &i;
1537        (void) &nextin;
1538        (void) &child;
1539# endif
1540#endif  /* __U_BOOT__ */
1541
1542        nextin = 0;
1543#ifndef __U_BOOT__
1544        pi->pgrp = -1;
1545#endif
1546
1547        /* Check if this is a simple builtin (not part of a pipe).
1548         * Builtins within pipes have to fork anyway, and are handled in
1549         * pseudo_exec.  "echo foo | read bar" doesn't work on bash, either.
1550         */
1551        if (pi->num_progs == 1) child = & (pi->progs[0]);
1552#ifndef __U_BOOT__
1553        if (pi->num_progs == 1 && child->group && child->subshell == 0) {
1554                int squirrel[] = {-1, -1, -1};
1555                int rcode;
1556                debug_printf("non-subshell grouping\n");
1557                setup_redirects(child, squirrel);
1558                /* XXX could we merge code with following builtin case,
1559                 * by creating a pseudo builtin that calls run_list_real? */
1560                rcode = run_list_real(child->group);
1561                restore_redirects(squirrel);
1562#else
1563                if (pi->num_progs == 1 && child->group) {
1564                int rcode;
1565                debug_printf("non-subshell grouping\n");
1566                rcode = run_list_real(child->group);
1567#endif
1568                return rcode;
1569        } else if (pi->num_progs == 1 && pi->progs[0].argv != NULL) {
1570                for (i=0; is_assignment(child->argv[i]); i++) { /* nothing */ }
1571                if (i!=0 && child->argv[i]==NULL) {
1572                        /* assignments, but no command: set the local environment */
1573                        for (i=0; child->argv[i]!=NULL; i++) {
1574
1575                                /* Ok, this case is tricky.  We have to decide if this is a
1576                                 * local variable, or an already exported variable.  If it is
1577                                 * already exported, we have to export the new value.  If it is
1578                                 * not exported, we need only set this as a local variable.
1579                                 * This junk is all to decide whether or not to export this
1580                                 * variable. */
1581                                int export_me=0;
1582                                char *name, *value;
1583                                name = xstrdup(child->argv[i]);
1584                                debug_printf("Local environment set: %s\n", name);
1585                                value = strchr(name, '=');
1586                                if (value)
1587                                        *value=0;
1588#ifndef __U_BOOT__
1589                                if ( get_local_var(name)) {
1590                                        export_me=1;
1591                                }
1592#endif
1593                                free(name);
1594                                p = insert_var_value(child->argv[i]);
1595                                set_local_var(p, export_me);
1596                                if (p != child->argv[i]) free(p);
1597                        }
1598                        return EXIT_SUCCESS;   /* don't worry about errors in set_local_var() yet */
1599                }
1600                for (i = 0; is_assignment(child->argv[i]); i++) {
1601                        p = insert_var_value(child->argv[i]);
1602#ifndef __U_BOOT__
1603                        putenv(strdup(p));
1604#else
1605                        set_local_var(p, 0);
1606#endif
1607                        if (p != child->argv[i]) {
1608                                child->sp--;
1609                                free(p);
1610                        }
1611                }
1612                if (child->sp) {
1613                        char * str = NULL;
1614
1615                        str = make_string(child->argv + i,
1616                                          child->argv_nonnull + i);
1617                        parse_string_outer(str, FLAG_EXIT_FROM_LOOP | FLAG_REPARSING);
1618                        free(str);
1619                        return last_return_code;
1620                }
1621#ifndef __U_BOOT__
1622                for (x = bltins; x->cmd; x++) {
1623                        if (strcmp(child->argv[i], x->cmd) == 0 ) {
1624                                int squirrel[] = {-1, -1, -1};
1625                                int rcode;
1626                                if (x->function == builtin_exec && child->argv[i+1]==NULL) {
1627                                        debug_printf("magic exec\n");
1628                                        setup_redirects(child,NULL);
1629                                        return EXIT_SUCCESS;
1630                                }
1631                                debug_printf("builtin inline %s\n", child->argv[0]);
1632                                /* XXX setup_redirects acts on file descriptors, not FILEs.
1633                                 * This is perfect for work that comes after exec().
1634                                 * Is it really safe for inline use?  Experimentally,
1635                                 * things seem to work with glibc. */
1636                                setup_redirects(child, squirrel);
1637
1638                                child->argv += i;  /* XXX horrible hack */
1639                                rcode = x->function(child);
1640                                /* XXX restore hack so free() can work right */
1641                                child->argv -= i;
1642                                restore_redirects(squirrel);
1643                        }
1644                        return rcode;
1645                }
1646#else
1647                /* check ";", because ,example , argv consist from
1648                 * "help;flinfo" must not execute
1649                 */
1650                if (strchr(child->argv[i], ';')) {
1651                        printf("Unknown command '%s' - try 'help' or use "
1652                                        "'run' command\n", child->argv[i]);
1653                        return -1;
1654                }
1655                /* Process the command */
1656                return cmd_process(flag, child->argc, child->argv,
1657                                   &flag_repeat, NULL);
1658#endif
1659        }
1660#ifndef __U_BOOT__
1661
1662        for (i = 0; i < pi->num_progs; i++) {
1663                child = & (pi->progs[i]);
1664
1665                /* pipes are inserted between pairs of commands */
1666                if ((i + 1) < pi->num_progs) {
1667                        if (pipe(pipefds)<0) perror_msg_and_die("pipe");
1668                        nextout = pipefds[1];
1669                } else {
1670                        nextout=1;
1671                        pipefds[0] = -1;
1672                }
1673
1674                /* XXX test for failed fork()? */
1675                if (!(child->pid = fork())) {
1676                        /* Set the handling for job control signals back to the default.  */
1677                        signal(SIGINT, SIG_DFL);
1678                        signal(SIGQUIT, SIG_DFL);
1679                        signal(SIGTERM, SIG_DFL);
1680                        signal(SIGTSTP, SIG_DFL);
1681                        signal(SIGTTIN, SIG_DFL);
1682                        signal(SIGTTOU, SIG_DFL);
1683                        signal(SIGCHLD, SIG_DFL);
1684
1685                        close_all();
1686
1687                        if (nextin != 0) {
1688                                dup2(nextin, 0);
1689                                close(nextin);
1690                        }
1691                        if (nextout != 1) {
1692                                dup2(nextout, 1);
1693                                close(nextout);
1694                        }
1695                        if (pipefds[0]!=-1) {
1696                                close(pipefds[0]);  /* opposite end of our output pipe */
1697                        }
1698
1699                        /* Like bash, explicit redirects override pipes,
1700                         * and the pipe fd is available for dup'ing. */
1701                        setup_redirects(child,NULL);
1702
1703                        if (interactive && pi->followup!=PIPE_BG) {
1704                                /* If we (the child) win the race, put ourselves in the process
1705                                 * group whose leader is the first process in this pipe. */
1706                                if (pi->pgrp < 0) {
1707                                        pi->pgrp = getpid();
1708                                }
1709                                if (setpgid(0, pi->pgrp) == 0) {
1710                                        tcsetpgrp(2, pi->pgrp);
1711                                }
1712                        }
1713
1714                        pseudo_exec(child);
1715                }
1716
1717
1718                /* put our child in the process group whose leader is the
1719                   first process in this pipe */
1720                if (pi->pgrp < 0) {
1721                        pi->pgrp = child->pid;
1722                }
1723                /* Don't check for errors.  The child may be dead already,
1724                 * in which case setpgid returns error code EACCES. */
1725                setpgid(child->pid, pi->pgrp);
1726
1727                if (nextin != 0)
1728                        close(nextin);
1729                if (nextout != 1)
1730                        close(nextout);
1731
1732                /* If there isn't another process, nextin is garbage
1733                   but it doesn't matter */
1734                nextin = pipefds[0];
1735        }
1736#endif
1737        return -1;
1738}
1739
1740static int run_list_real(struct pipe *pi)
1741{
1742        char *save_name = NULL;
1743        char **list = NULL;
1744        char **save_list = NULL;
1745        struct pipe *rpipe;
1746        int flag_rep = 0;
1747#ifndef __U_BOOT__
1748        int save_num_progs;
1749#endif
1750        int rcode=0, flag_skip=1;
1751        int flag_restore = 0;
1752        int if_code=0, next_if_code=0;  /* need double-buffer to handle elif */
1753        reserved_style rmode, skip_more_in_this_rmode=RES_XXXX;
1754        /* check syntax for "for" */
1755        for (rpipe = pi; rpipe; rpipe = rpipe->next) {
1756                if ((rpipe->r_mode == RES_IN ||
1757                    rpipe->r_mode == RES_FOR) &&
1758                    (rpipe->next == NULL)) {
1759                                syntax();
1760#ifdef __U_BOOT__
1761                                flag_repeat = 0;
1762#endif
1763                                return 1;
1764                }
1765                if ((rpipe->r_mode == RES_IN &&
1766                        (rpipe->next->r_mode == RES_IN &&
1767                        rpipe->next->progs->argv != NULL))||
1768                        (rpipe->r_mode == RES_FOR &&
1769                        rpipe->next->r_mode != RES_IN)) {
1770                                syntax();
1771#ifdef __U_BOOT__
1772                                flag_repeat = 0;
1773#endif
1774                                return 1;
1775                }
1776        }
1777        for (; pi; pi = (flag_restore != 0) ? rpipe : pi->next) {
1778                if (pi->r_mode == RES_WHILE || pi->r_mode == RES_UNTIL ||
1779                        pi->r_mode == RES_FOR) {
1780#ifdef __U_BOOT__
1781                                /* check Ctrl-C */
1782                                ctrlc();
1783                                if ((had_ctrlc())) {
1784                                        return 1;
1785                                }
1786#endif
1787                                flag_restore = 0;
1788                                if (!rpipe) {
1789                                        flag_rep = 0;
1790                                        rpipe = pi;
1791                                }
1792                }
1793                rmode = pi->r_mode;
1794                debug_printf("rmode=%d  if_code=%d  next_if_code=%d skip_more=%d\n", rmode, if_code, next_if_code, skip_more_in_this_rmode);
1795                if (rmode == skip_more_in_this_rmode && flag_skip) {
1796                        if (pi->followup == PIPE_SEQ) flag_skip=0;
1797                        continue;
1798                }
1799                flag_skip = 1;
1800                skip_more_in_this_rmode = RES_XXXX;
1801                if (rmode == RES_THEN || rmode == RES_ELSE) if_code = next_if_code;
1802                if (rmode == RES_THEN &&  if_code) continue;
1803                if (rmode == RES_ELSE && !if_code) continue;
1804                if (rmode == RES_ELIF && !if_code) break;
1805                if (rmode == RES_FOR && pi->num_progs) {
1806                        if (!list) {
1807                                /* if no variable values after "in" we skip "for" */
1808                                if (!pi->next->progs->argv) continue;
1809                                /* create list of variable values */
1810                                list = make_list_in(pi->next->progs->argv,
1811                                        pi->progs->argv[0]);
1812                                save_list = list;
1813                                save_name = pi->progs->argv[0];
1814                                pi->progs->argv[0] = NULL;
1815                                flag_rep = 1;
1816                        }
1817                        if (!(*list)) {
1818                                free(pi->progs->argv[0]);
1819                                free(save_list);
1820                                list = NULL;
1821                                flag_rep = 0;
1822                                pi->progs->argv[0] = save_name;
1823#ifndef __U_BOOT__
1824                                pi->progs->glob_result.gl_pathv[0] =
1825                                        pi->progs->argv[0];
1826#endif
1827                                continue;
1828                        } else {
1829                                /* insert new value from list for variable */
1830                                if (pi->progs->argv[0])
1831                                        free(pi->progs->argv[0]);
1832                                pi->progs->argv[0] = *list++;
1833#ifndef __U_BOOT__
1834                                pi->progs->glob_result.gl_pathv[0] =
1835                                        pi->progs->argv[0];
1836#endif
1837                        }
1838                }
1839                if (rmode == RES_IN) continue;
1840                if (rmode == RES_DO) {
1841                        if (!flag_rep) continue;
1842                }
1843                if (rmode == RES_DONE) {
1844                        if (flag_rep) {
1845                                flag_restore = 1;
1846                        } else {
1847                                rpipe = NULL;
1848                        }
1849                }
1850                if (pi->num_progs == 0) continue;
1851#ifndef __U_BOOT__
1852                save_num_progs = pi->num_progs; /* save number of programs */
1853#endif
1854                rcode = run_pipe_real(pi);
1855                debug_printf("run_pipe_real returned %d\n",rcode);
1856#ifndef __U_BOOT__
1857                if (rcode!=-1) {
1858                        /* We only ran a builtin: rcode was set by the return value
1859                         * of run_pipe_real(), and we don't need to wait for anything. */
1860                } else if (pi->followup==PIPE_BG) {
1861                        /* XXX check bash's behavior with nontrivial pipes */
1862                        /* XXX compute jobid */
1863                        /* XXX what does bash do with attempts to background builtins? */
1864                        insert_bg_job(pi);
1865                        rcode = EXIT_SUCCESS;
1866                } else {
1867                        if (interactive) {
1868                                /* move the new process group into the foreground */
1869                                if (tcsetpgrp(shell_terminal, pi->pgrp) && errno != ENOTTY)
1870                                        perror_msg("tcsetpgrp-3");
1871                                rcode = checkjobs(pi);
1872                                /* move the shell to the foreground */
1873                                if (tcsetpgrp(shell_terminal, getpgid(0)) && errno != ENOTTY)
1874                                        perror_msg("tcsetpgrp-4");
1875                        } else {
1876                                rcode = checkjobs(pi);
1877                        }
1878                        debug_printf("checkjobs returned %d\n",rcode);
1879                }
1880                last_return_code=rcode;
1881#else
1882                if (rcode < -1) {
1883                        last_return_code = -rcode - 2;
1884                        return -2;      /* exit */
1885                }
1886                last_return_code=(rcode == 0) ? 0 : 1;
1887#endif
1888#ifndef __U_BOOT__
1889                pi->num_progs = save_num_progs; /* restore number of programs */
1890#endif
1891                if ( rmode == RES_IF || rmode == RES_ELIF )
1892                        next_if_code=rcode;  /* can be overwritten a number of times */
1893                if (rmode == RES_WHILE)
1894                        flag_rep = !last_return_code;
1895                if (rmode == RES_UNTIL)
1896                        flag_rep = last_return_code;
1897                if ( (rcode==EXIT_SUCCESS && pi->followup==PIPE_OR) ||
1898                     (rcode!=EXIT_SUCCESS && pi->followup==PIPE_AND) )
1899                        skip_more_in_this_rmode=rmode;
1900#ifndef __U_BOOT__
1901                checkjobs(NULL);
1902#endif
1903        }
1904        return rcode;
1905}
1906
1907/* broken, of course, but OK for testing */
1908static char *indenter(int i)
1909{
1910        static char blanks[]="                                    ";
1911        return &blanks[sizeof(blanks)-i-1];
1912}
1913
1914/* return code is the exit status of the pipe */
1915static int free_pipe(struct pipe *pi, int indent)
1916{
1917        char **p;
1918        struct child_prog *child;
1919#ifndef __U_BOOT__
1920        struct redir_struct *r, *rnext;
1921#endif
1922        int a, i, ret_code=0;
1923        char *ind = indenter(indent);
1924
1925#ifndef __U_BOOT__
1926        if (pi->stopped_progs > 0)
1927                return ret_code;
1928        final_printf("%s run pipe: (pid %d)\n",ind,getpid());
1929#endif
1930        for (i=0; i<pi->num_progs; i++) {
1931                child = &pi->progs[i];
1932                final_printf("%s  command %d:\n",ind,i);
1933                if (child->argv) {
1934                        for (a=0,p=child->argv; *p; a++,p++) {
1935                                final_printf("%s   argv[%d] = %s\n",ind,a,*p);
1936                        }
1937#ifndef __U_BOOT__
1938                        globfree(&child->glob_result);
1939#else
1940                        for (a = 0; a < child->argc; a++) {
1941                                free(child->argv[a]);
1942                        }
1943                        free(child->argv);
1944                        free(child->argv_nonnull);
1945                        child->argc = 0;
1946#endif
1947                        child->argv=NULL;
1948                } else if (child->group) {
1949#ifndef __U_BOOT__
1950                        final_printf("%s   begin group (subshell:%d)\n",ind, child->subshell);
1951#endif
1952                        ret_code = free_pipe_list(child->group,indent+3);
1953                        final_printf("%s   end group\n",ind);
1954                } else {
1955                        final_printf("%s   (nil)\n",ind);
1956                }
1957#ifndef __U_BOOT__
1958                for (r=child->redirects; r; r=rnext) {
1959                        final_printf("%s   redirect %d%s", ind, r->fd, redir_table[r->type].descrip);
1960                        if (r->dup == -1) {
1961                                /* guard against the case >$FOO, where foo is unset or blank */
1962                                if (r->word.gl_pathv) {
1963                                        final_printf(" %s\n", *r->word.gl_pathv);
1964                                        globfree(&r->word);
1965                                }
1966                        } else {
1967                                final_printf("&%d\n", r->dup);
1968                        }
1969                        rnext=r->next;
1970                        free(r);
1971                }
1972                child->redirects=NULL;
1973#endif
1974        }
1975        free(pi->progs);   /* children are an array, they get freed all at once */
1976        pi->progs=NULL;
1977        return ret_code;
1978}
1979
1980static int free_pipe_list(struct pipe *head, int indent)
1981{
1982        int rcode=0;   /* if list has no members */
1983        struct pipe *pi, *next;
1984        char *ind = indenter(indent);
1985        for (pi=head; pi; pi=next) {
1986                final_printf("%s pipe reserved mode %d\n", ind, pi->r_mode);
1987                rcode = free_pipe(pi, indent);
1988                final_printf("%s pipe followup code %d\n", ind, pi->followup);
1989                next=pi->next;
1990                pi->next=NULL;
1991                free(pi);
1992        }
1993        return rcode;
1994}
1995
1996/* Select which version we will use */
1997static int run_list(struct pipe *pi)
1998{
1999        int rcode=0;
2000#ifndef __U_BOOT__
2001        if (fake_mode==0) {
2002#endif
2003                rcode = run_list_real(pi);
2004#ifndef __U_BOOT__
2005        }
2006#endif
2007        /* free_pipe_list has the side effect of clearing memory
2008         * In the long run that function can be merged with run_list_real,
2009         * but doing that now would hobble the debugging effort. */
2010        free_pipe_list(pi,0);
2011        return rcode;
2012}
2013
2014/* The API for glob is arguably broken.  This routine pushes a non-matching
2015 * string into the output structure, removing non-backslashed backslashes.
2016 * If someone can prove me wrong, by performing this function within the
2017 * original glob(3) api, feel free to rewrite this routine into oblivion.
2018 * Return code (0 vs. GLOB_NOSPACE) matches glob(3).
2019 * XXX broken if the last character is '\\', check that before calling.
2020 */
2021#ifndef __U_BOOT__
2022static int globhack(const char *src, int flags, glob_t *pglob)
2023{
2024        int cnt=0, pathc;
2025        const char *s;
2026        char *dest;
2027        for (cnt=1, s=src; s && *s; s++) {
2028                if (*s == '\\') s++;
2029                cnt++;
2030        }
2031        dest = malloc(cnt);
2032        if (!dest) return GLOB_NOSPACE;
2033        if (!(flags & GLOB_APPEND)) {
2034                pglob->gl_pathv=NULL;
2035                pglob->gl_pathc=0;
2036                pglob->gl_offs=0;
2037                pglob->gl_offs=0;
2038        }
2039        pathc = ++pglob->gl_pathc;
2040        pglob->gl_pathv = realloc(pglob->gl_pathv, (pathc+1)*sizeof(*pglob->gl_pathv));
2041        if (pglob->gl_pathv == NULL) return GLOB_NOSPACE;
2042        pglob->gl_pathv[pathc-1]=dest;
2043        pglob->gl_pathv[pathc]=NULL;
2044        for (s=src; s && *s; s++, dest++) {
2045                if (*s == '\\') s++;
2046                *dest = *s;
2047        }
2048        *dest='\0';
2049        return 0;
2050}
2051
2052/* XXX broken if the last character is '\\', check that before calling */
2053static int glob_needed(const char *s)
2054{
2055        for (; *s; s++) {
2056                if (*s == '\\') s++;
2057                if (strchr("*[?",*s)) return 1;
2058        }
2059        return 0;
2060}
2061
2062#if 0
2063static void globprint(glob_t *pglob)
2064{
2065        int i;
2066        debug_printf("glob_t at %p:\n", pglob);
2067        debug_printf("  gl_pathc=%d  gl_pathv=%p  gl_offs=%d  gl_flags=%d\n",
2068                pglob->gl_pathc, pglob->gl_pathv, pglob->gl_offs, pglob->gl_flags);
2069        for (i=0; i<pglob->gl_pathc; i++)
2070                debug_printf("pglob->gl_pathv[%d] = %p = %s\n", i,
2071                        pglob->gl_pathv[i], pglob->gl_pathv[i]);
2072}
2073#endif
2074
2075static int xglob(o_string *dest, int flags, glob_t *pglob)
2076{
2077        int gr;
2078
2079        /* short-circuit for null word */
2080        /* we can code this better when the debug_printf's are gone */
2081        if (dest->length == 0) {
2082                if (dest->nonnull) {
2083                        /* bash man page calls this an "explicit" null */
2084                        gr = globhack(dest->data, flags, pglob);
2085                        debug_printf("globhack returned %d\n",gr);
2086                } else {
2087                        return 0;
2088                }
2089        } else if (glob_needed(dest->data)) {
2090                gr = glob(dest->data, flags, NULL, pglob);
2091                debug_printf("glob returned %d\n",gr);
2092                if (gr == GLOB_NOMATCH) {
2093                        /* quote removal, or more accurately, backslash removal */
2094                        gr = globhack(dest->data, flags, pglob);
2095                        debug_printf("globhack returned %d\n",gr);
2096                }
2097        } else {
2098                gr = globhack(dest->data, flags, pglob);
2099                debug_printf("globhack returned %d\n",gr);
2100        }
2101        if (gr == GLOB_NOSPACE)
2102                error_msg_and_die("out of memory during glob");
2103        if (gr != 0) { /* GLOB_ABORTED ? */
2104                error_msg("glob(3) error %d",gr);
2105        }
2106        /* globprint(glob_target); */
2107        return gr;
2108}
2109#endif
2110
2111#ifdef __U_BOOT__
2112static char *get_dollar_var(char ch);
2113#endif
2114
2115/* This is used to get/check local shell variables */
2116char *get_local_var(const char *s)
2117{
2118        struct variables *cur;
2119
2120        if (!s)
2121                return NULL;
2122
2123#ifdef __U_BOOT__
2124        if (*s == '$')
2125                return get_dollar_var(s[1]);
2126#endif
2127
2128        for (cur = top_vars; cur; cur=cur->next)
2129                if(strcmp(cur->name, s)==0)
2130                        return cur->value;
2131        return NULL;
2132}
2133
2134/* This is used to set local shell variables
2135   flg_export==0 if only local (not exporting) variable
2136   flg_export==1 if "new" exporting environ
2137   flg_export>1  if current startup environ (not call putenv()) */
2138int set_local_var(const char *s, int flg_export)
2139{
2140        char *name, *value;
2141        int result=0;
2142        struct variables *cur;
2143
2144#ifdef __U_BOOT__
2145        /* might be possible! */
2146        if (!isalpha(*s))
2147                return -1;
2148#endif
2149
2150        name=strdup(s);
2151
2152#ifdef __U_BOOT__
2153        if (getenv(name) != NULL) {
2154                printf ("ERROR: "
2155                                "There is a global environment variable with the same name.\n");
2156                free(name);
2157                return -1;
2158        }
2159#endif
2160        /* Assume when we enter this function that we are already in
2161         * NAME=VALUE format.  So the first order of business is to
2162         * split 's' on the '=' into 'name' and 'value' */
2163        value = strchr(name, '=');
2164        if (value == NULL && ++value == NULL) {
2165                free(name);
2166                return -1;
2167        }
2168        *value++ = 0;
2169
2170        for(cur = top_vars; cur; cur = cur->next) {
2171                if(strcmp(cur->name, name)==0)
2172                        break;
2173        }
2174
2175        if(cur) {
2176                if(strcmp(cur->value, value)==0) {
2177                        if(flg_export>0 && cur->flg_export==0)
2178                                cur->flg_export=flg_export;
2179                        else
2180                                result++;
2181                } else {
2182                        if(cur->flg_read_only) {
2183                                error_msg("%s: readonly variable", name);
2184                                result = -1;
2185                        } else {
2186                                if(flg_export>0 || cur->flg_export>1)
2187                                        cur->flg_export=1;
2188                                free(cur->value);
2189
2190                                cur->value = strdup(value);
2191                        }
2192                }
2193        } else {
2194                cur = malloc(sizeof(struct variables));
2195                if(!cur) {
2196                        result = -1;
2197                } else {
2198                        cur->name = strdup(name);
2199                        if (cur->name == NULL) {
2200                                free(cur);
2201                                result = -1;
2202                        } else {
2203                                struct variables *bottom = top_vars;
2204                                cur->value = strdup(value);
2205                                cur->next = NULL;
2206                                cur->flg_export = flg_export;
2207                                cur->flg_read_only = 0;
2208                                while(bottom->next) bottom=bottom->next;
2209                                bottom->next = cur;
2210                        }
2211                }
2212        }
2213
2214#ifndef __U_BOOT__
2215        if(result==0 && cur->flg_export==1) {
2216                *(value-1) = '=';
2217                result = putenv(name);
2218        } else {
2219#endif
2220                free(name);
2221#ifndef __U_BOOT__
2222                if(result>0)            /* equivalent to previous set */
2223                        result = 0;
2224        }
2225#endif
2226        return result;
2227}
2228
2229void unset_local_var(const char *name)
2230{
2231        struct variables *cur;
2232
2233        if (name) {
2234                for (cur = top_vars; cur; cur=cur->next) {
2235                        if(strcmp(cur->name, name)==0)
2236                                break;
2237                }
2238                if (cur != NULL) {
2239                        struct variables *next = top_vars;
2240                        if(cur->flg_read_only) {
2241                                error_msg("%s: readonly variable", name);
2242                                return;
2243                        } else {
2244#ifndef __U_BOOT__
2245                                if(cur->flg_export)
2246                                        unsetenv(cur->name);
2247#endif
2248                                free(cur->name);
2249                                free(cur->value);
2250                                while (next->next != cur)
2251                                        next = next->next;
2252                                next->next = cur->next;
2253                        }
2254                        free(cur);
2255                }
2256        }
2257}
2258
2259static int is_assignment(const char *s)
2260{
2261        if (s == NULL)
2262                return 0;
2263
2264        if (!isalpha(*s)) return 0;
2265        ++s;
2266        while(isalnum(*s) || *s=='_') ++s;
2267        return *s=='=';
2268}
2269
2270#ifndef __U_BOOT__
2271/* the src parameter allows us to peek forward to a possible &n syntax
2272 * for file descriptor duplication, e.g., "2>&1".
2273 * Return code is 0 normally, 1 if a syntax error is detected in src.
2274 * Resource errors (in xmalloc) cause the process to exit */
2275static int setup_redirect(struct p_context *ctx, int fd, redir_type style,
2276        struct in_str *input)
2277{
2278        struct child_prog *child=ctx->child;
2279        struct redir_struct *redir = child->redirects;
2280        struct redir_struct *last_redir=NULL;
2281
2282        /* Create a new redir_struct and drop it onto the end of the linked list */
2283        while(redir) {
2284                last_redir=redir;
2285                redir=redir->next;
2286        }
2287        redir = xmalloc(sizeof(struct redir_struct));
2288        redir->next=NULL;
2289        redir->word.gl_pathv=NULL;
2290        if (last_redir) {
2291                last_redir->next=redir;
2292        } else {
2293                child->redirects=redir;
2294        }
2295
2296        redir->type=style;
2297        redir->fd= (fd==-1) ? redir_table[style].default_fd : fd ;
2298
2299        debug_printf("Redirect type %d%s\n", redir->fd, redir_table[style].descrip);
2300
2301        /* Check for a '2>&1' type redirect */
2302        redir->dup = redirect_dup_num(input);
2303        if (redir->dup == -2) return 1;  /* syntax error */
2304        if (redir->dup != -1) {
2305                /* Erik had a check here that the file descriptor in question
2306                 * is legit; I postpone that to "run time"
2307                 * A "-" representation of "close me" shows up as a -3 here */
2308                debug_printf("Duplicating redirect '%d>&%d'\n", redir->fd, redir->dup);
2309        } else {
2310                /* We do _not_ try to open the file that src points to,
2311                 * since we need to return and let src be expanded first.
2312                 * Set ctx->pending_redirect, so we know what to do at the
2313                 * end of the next parsed word.
2314                 */
2315                ctx->pending_redirect = redir;
2316        }
2317        return 0;
2318}
2319#endif
2320
2321static struct pipe *new_pipe(void)
2322{
2323        struct pipe *pi;
2324        pi = xmalloc(sizeof(struct pipe));
2325        pi->num_progs = 0;
2326        pi->progs = NULL;
2327        pi->next = NULL;
2328        pi->followup = 0;  /* invalid */
2329        pi->r_mode = RES_NONE;
2330        return pi;
2331}
2332
2333static void initialize_context(struct p_context *ctx)
2334{
2335        ctx->pipe=NULL;
2336#ifndef __U_BOOT__
2337        ctx->pending_redirect=NULL;
2338#endif
2339        ctx->child=NULL;
2340        ctx->list_head=new_pipe();
2341        ctx->pipe=ctx->list_head;
2342        ctx->w=RES_NONE;
2343        ctx->stack=NULL;
2344#ifdef __U_BOOT__
2345        ctx->old_flag=0;
2346#endif
2347        done_command(ctx);   /* creates the memory for working child */
2348}
2349
2350/* normal return is 0
2351 * if a reserved word is found, and processed, return 1
2352 * should handle if, then, elif, else, fi, for, while, until, do, done.
2353 * case, function, and select are obnoxious, save those for later.
2354 */
2355struct reserved_combo {
2356        char *literal;
2357        int code;
2358        long flag;
2359};
2360/* Mostly a list of accepted follow-up reserved words.
2361 * FLAG_END means we are done with the sequence, and are ready
2362 * to turn the compound list into a command.
2363 * FLAG_START means the word must start a new compound list.
2364 */
2365static struct reserved_combo reserved_list[] = {
2366        { "if",    RES_IF,    FLAG_THEN | FLAG_START },
2367        { "then",  RES_THEN,  FLAG_ELIF | FLAG_ELSE | FLAG_FI },
2368        { "elif",  RES_ELIF,  FLAG_THEN },
2369        { "else",  RES_ELSE,  FLAG_FI   },
2370        { "fi",    RES_FI,    FLAG_END  },
2371        { "for",   RES_FOR,   FLAG_IN   | FLAG_START },
2372        { "while", RES_WHILE, FLAG_DO   | FLAG_START },
2373        { "until", RES_UNTIL, FLAG_DO   | FLAG_START },
2374        { "in",    RES_IN,    FLAG_DO   },
2375        { "do",    RES_DO,    FLAG_DONE },
2376        { "done",  RES_DONE,  FLAG_END  }
2377};
2378#define NRES (sizeof(reserved_list)/sizeof(struct reserved_combo))
2379
2380static int reserved_word(o_string *dest, struct p_context *ctx)
2381{
2382        struct reserved_combo *r;
2383        for (r=reserved_list;
2384                r<reserved_list+NRES; r++) {
2385                if (strcmp(dest->data, r->literal) == 0) {
2386                        debug_printf("found reserved word %s, code %d\n",r->literal,r->code);
2387                        if (r->flag & FLAG_START) {
2388                                struct p_context *new = xmalloc(sizeof(struct p_context));
2389                                debug_printf("push stack\n");
2390                                if (ctx->w == RES_IN || ctx->w == RES_FOR) {
2391                                        syntax();
2392                                        free(new);
2393                                        ctx->w = RES_SNTX;
2394                                        b_reset(dest);
2395                                        return 1;
2396                                }
2397                                *new = *ctx;   /* physical copy */
2398                                initialize_context(ctx);
2399                                ctx->stack=new;
2400                        } else if ( ctx->w == RES_NONE || ! (ctx->old_flag & (1<<r->code))) {
2401                                syntax();
2402                                ctx->w = RES_SNTX;
2403                                b_reset(dest);
2404                                return 1;
2405                        }
2406                        ctx->w=r->code;
2407                        ctx->old_flag = r->flag;
2408                        if (ctx->old_flag & FLAG_END) {
2409                                struct p_context *old;
2410                                debug_printf("pop stack\n");
2411                                done_pipe(ctx,PIPE_SEQ);
2412                                old = ctx->stack;
2413                                old->child->group = ctx->list_head;
2414#ifndef __U_BOOT__
2415                                old->child->subshell = 0;
2416#endif
2417                                *ctx = *old;   /* physical copy */
2418                                free(old);
2419                        }
2420                        b_reset (dest);
2421                        return 1;
2422                }
2423        }
2424        return 0;
2425}
2426
2427/* normal return is 0.
2428 * Syntax or xglob errors return 1. */
2429static int done_word(o_string *dest, struct p_context *ctx)
2430{
2431        struct child_prog *child=ctx->child;
2432#ifndef __U_BOOT__
2433        glob_t *glob_target;
2434        int gr, flags = 0;
2435#else
2436        char *str, *s;
2437        int argc, cnt;
2438#endif
2439
2440        debug_printf("done_word: %s %p\n", dest->data, child);
2441        if (dest->length == 0 && !dest->nonnull) {
2442                debug_printf("  true null, ignored\n");
2443                return 0;
2444        }
2445#ifndef __U_BOOT__
2446        if (ctx->pending_redirect) {
2447                glob_target = &ctx->pending_redirect->word;
2448        } else {
2449#endif
2450                if (child->group) {
2451                        syntax();
2452                        return 1;  /* syntax error, groups and arglists don't mix */
2453                }
2454                if (!child->argv && (ctx->type & FLAG_PARSE_SEMICOLON)) {
2455                        debug_printf("checking %s for reserved-ness\n",dest->data);
2456                        if (reserved_word(dest,ctx)) return ctx->w==RES_SNTX;
2457                }
2458#ifndef __U_BOOT__
2459                glob_target = &child->glob_result;
2460                if (child->argv) flags |= GLOB_APPEND;
2461#else
2462                for (cnt = 1, s = dest->data; s && *s; s++) {
2463                        if (*s == '\\') s++;
2464                        cnt++;
2465                }
2466                str = malloc(cnt);
2467                if (!str) return 1;
2468                if ( child->argv == NULL) {
2469                        child->argc=0;
2470                }
2471                argc = ++child->argc;
2472                child->argv = realloc(child->argv, (argc+1)*sizeof(*child->argv));
2473                if (child->argv == NULL) return 1;
2474                child->argv_nonnull = realloc(child->argv_nonnull,
2475                                        (argc+1)*sizeof(*child->argv_nonnull));
2476                if (child->argv_nonnull == NULL)
2477                        return 1;
2478                child->argv[argc-1]=str;
2479                child->argv_nonnull[argc-1] = dest->nonnull;
2480                child->argv[argc]=NULL;
2481                child->argv_nonnull[argc] = 0;
2482                for (s = dest->data; s && *s; s++,str++) {
2483                        if (*s == '\\') s++;
2484                        *str = *s;
2485                }
2486                *str = '\0';
2487#endif
2488#ifndef __U_BOOT__
2489        }
2490        gr = xglob(dest, flags, glob_target);
2491        if (gr != 0) return 1;
2492#endif
2493
2494        b_reset(dest);
2495#ifndef __U_BOOT__
2496        if (ctx->pending_redirect) {
2497                ctx->pending_redirect=NULL;
2498                if (glob_target->gl_pathc != 1) {
2499                        error_msg("ambiguous redirect");
2500                        return 1;
2501                }
2502        } else {
2503                child->argv = glob_target->gl_pathv;
2504        }
2505#endif
2506        if (ctx->w == RES_FOR) {
2507                done_word(dest,ctx);
2508                done_pipe(ctx,PIPE_SEQ);
2509        }
2510        return 0;
2511}
2512
2513/* The only possible error here is out of memory, in which case
2514 * xmalloc exits. */
2515static int done_command(struct p_context *ctx)
2516{
2517        /* The child is really already in the pipe structure, so
2518         * advance the pipe counter and make a new, null child.
2519         * Only real trickiness here is that the uncommitted
2520         * child structure, to which ctx->child points, is not
2521         * counted in pi->num_progs. */
2522        struct pipe *pi=ctx->pipe;
2523        struct child_prog *prog=ctx->child;
2524
2525        if (prog && prog->group == NULL
2526                 && prog->argv == NULL
2527#ifndef __U_BOOT__
2528                 && prog->redirects == NULL) {
2529#else
2530                                                                                ) {
2531#endif
2532                debug_printf("done_command: skipping null command\n");
2533                return 0;
2534        } else if (prog) {
2535                pi->num_progs++;
2536                debug_printf("done_command: num_progs incremented to %d\n",pi->num_progs);
2537        } else {
2538                debug_printf("done_command: initializing\n");
2539        }
2540        pi->progs = xrealloc(pi->progs, sizeof(*pi->progs) * (pi->num_progs+1));
2541
2542        prog = pi->progs + pi->num_progs;
2543#ifndef __U_BOOT__
2544        prog->redirects = NULL;
2545#endif
2546        prog->argv = NULL;
2547        prog->argv_nonnull = NULL;
2548#ifndef __U_BOOT__
2549        prog->is_stopped = 0;
2550#endif
2551        prog->group = NULL;
2552#ifndef __U_BOOT__
2553        prog->glob_result.gl_pathv = NULL;
2554        prog->family = pi;
2555#endif
2556        prog->sp = 0;
2557        ctx->child = prog;
2558        prog->type = ctx->type;
2559
2560        /* but ctx->pipe and ctx->list_head remain unchanged */
2561        return 0;
2562}
2563
2564static int done_pipe(struct p_context *ctx, pipe_style type)
2565{
2566        struct pipe *new_p;
2567        done_command(ctx);  /* implicit closure of previous command */
2568        debug_printf("done_pipe, type %d\n", type);
2569        ctx->pipe->followup = type;
2570        ctx->pipe->r_mode = ctx->w;
2571        new_p=new_pipe();
2572        ctx->pipe->next = new_p;
2573        ctx->pipe = new_p;
2574        ctx->child = NULL;
2575        done_command(ctx);  /* set up new pipe to accept commands */
2576        return 0;
2577}
2578
2579#ifndef __U_BOOT__
2580/* peek ahead in the in_str to find out if we have a "&n" construct,
2581 * as in "2>&1", that represents duplicating a file descriptor.
2582 * returns either -2 (syntax error), -1 (no &), or the number found.
2583 */
2584static int redirect_dup_num(struct in_str *input)
2585{
2586        int ch, d=0, ok=0;
2587        ch = b_peek(input);
2588        if (ch != '&') return -1;
2589
2590        b_getch(input);  /* get the & */
2591        ch=b_peek(input);
2592        if (ch == '-') {
2593                b_getch(input);
2594                return -3;  /* "-" represents "close me" */
2595        }
2596        while (isdigit(ch)) {
2597                d = d*10+(ch-'0');
2598                ok=1;
2599                b_getch(input);
2600                ch = b_peek(input);
2601        }
2602        if (ok) return d;
2603
2604        error_msg("ambiguous redirect");
2605        return -2;
2606}
2607
2608/* If a redirect is immediately preceded by a number, that number is
2609 * supposed to tell which file descriptor to redirect.  This routine
2610 * looks for such preceding numbers.  In an ideal world this routine
2611 * needs to handle all the following classes of redirects...
2612 *     echo 2>foo     # redirects fd  2 to file "foo", nothing passed to echo
2613 *     echo 49>foo    # redirects fd 49 to file "foo", nothing passed to echo
2614 *     echo -2>foo    # redirects fd  1 to file "foo",    "-2" passed to echo
2615 *     echo 49x>foo   # redirects fd  1 to file "foo",   "49x" passed to echo
2616 * A -1 output from this program means no valid number was found, so the
2617 * caller should use the appropriate default for this redirection.
2618 */
2619static int redirect_opt_num(o_string *o)
2620{
2621        int num;
2622
2623        if (o->length==0) return -1;
2624        for(num=0; num<o->length; num++) {
2625                if (!isdigit(*(o->data+num))) {
2626                        return -1;
2627                }
2628        }
2629        /* reuse num (and save an int) */
2630        num=atoi(o->data);
2631        b_reset(o);
2632        return num;
2633}
2634
2635FILE *generate_stream_from_list(struct pipe *head)
2636{
2637        FILE *pf;
2638#if 1
2639        int pid, channel[2];
2640        if (pipe(channel)<0) perror_msg_and_die("pipe");
2641        pid=fork();
2642        if (pid<0) {
2643                perror_msg_and_die("fork");
2644        } else if (pid==0) {
2645                close(channel[0]);
2646                if (channel[1] != 1) {
2647                        dup2(channel[1],1);
2648                        close(channel[1]);
2649                }
2650#if 0
2651#define SURROGATE "surrogate response"
2652                write(1,SURROGATE,sizeof(SURROGATE));
2653                _exit(run_list(head));
2654#else
2655                _exit(run_list_real(head));   /* leaks memory */
2656#endif
2657        }
2658        debug_printf("forked child %d\n",pid);
2659        close(channel[1]);
2660        pf = fdopen(channel[0],"r");
2661        debug_printf("pipe on FILE *%p\n",pf);
2662#else
2663        free_pipe_list(head,0);
2664        pf=popen("echo surrogate response","r");
2665        debug_printf("started fake pipe on FILE *%p\n",pf);
2666#endif
2667        return pf;
2668}
2669
2670/* this version hacked for testing purposes */
2671/* return code is exit status of the process that is run. */
2672static int process_command_subs(o_string *dest, struct p_context *ctx, struct in_str *input, int subst_end)
2673{
2674        int retcode;
2675        o_string result=NULL_O_STRING;
2676        struct p_context inner;
2677        FILE *p;
2678        struct in_str pipe_str;
2679        initialize_context(&inner);
2680
2681        /* recursion to generate command */
2682        retcode = parse_stream(&result, &inner, input, subst_end);
2683        if (retcode != 0) return retcode;  /* syntax error or EOF */
2684        done_word(&result, &inner);
2685        done_pipe(&inner, PIPE_SEQ);
2686        b_free(&result);
2687
2688        p=generate_stream_from_list(inner.list_head);
2689        if (p==NULL) return 1;
2690        mark_open(fileno(p));
2691        setup_file_in_str(&pipe_str, p);
2692
2693        /* now send results of command back into original context */
2694        retcode = parse_stream(dest, ctx, &pipe_str, '\0');
2695        /* XXX In case of a syntax error, should we try to kill the child?
2696         * That would be tough to do right, so just read until EOF. */
2697        if (retcode == 1) {
2698                while (b_getch(&pipe_str)!=EOF) { /* discard */ };
2699        }
2700
2701        debug_printf("done reading from pipe, pclose()ing\n");
2702        /* This is the step that wait()s for the child.  Should be pretty
2703         * safe, since we just read an EOF from its stdout.  We could try
2704         * to better, by using wait(), and keeping track of background jobs
2705         * at the same time.  That would be a lot of work, and contrary
2706         * to the KISS philosophy of this program. */
2707        mark_closed(fileno(p));
2708        retcode=pclose(p);
2709        free_pipe_list(inner.list_head,0);
2710        debug_printf("pclosed, retcode=%d\n",retcode);
2711        /* XXX this process fails to trim a single trailing newline */
2712        return retcode;
2713}
2714
2715static int parse_group(o_string *dest, struct p_context *ctx,
2716        struct in_str *input, int ch)
2717{
2718        int rcode, endch=0;
2719        struct p_context sub;
2720        struct child_prog *child = ctx->child;
2721        if (child->argv) {
2722                syntax();
2723                return 1;  /* syntax error, groups and arglists don't mix */
2724        }
2725        initialize_context(&sub);
2726        switch(ch) {
2727                case '(': endch=')'; child->subshell=1; break;
2728                case '{': endch='}'; break;
2729                default: syntax();   /* really logic error */
2730        }
2731        rcode=parse_stream(dest,&sub,input,endch);
2732        done_word(dest,&sub); /* finish off the final word in the subcontext */
2733        done_pipe(&sub, PIPE_SEQ);  /* and the final command there, too */
2734        child->group = sub.list_head;
2735        return rcode;
2736        /* child remains "open", available for possible redirects */
2737}
2738#endif
2739
2740/* basically useful version until someone wants to get fancier,
2741 * see the bash man page under "Parameter Expansion" */
2742static char *lookup_param(char *src)
2743{
2744        char *p;
2745        char *sep;
2746        char *default_val = NULL;
2747        int assign = 0;
2748        int expand_empty = 0;
2749
2750        if (!src)
2751                return NULL;
2752
2753        sep = strchr(src, ':');
2754
2755        if (sep) {
2756                *sep = '\0';
2757                if (*(sep + 1) == '-')
2758                        default_val = sep+2;
2759                if (*(sep + 1) == '=') {
2760                        default_val = sep+2;
2761                        assign = 1;
2762                }
2763                if (*(sep + 1) == '+') {
2764                        default_val = sep+2;
2765                        expand_empty = 1;
2766                }
2767        }
2768
2769        p = getenv(src);
2770        if (!p)
2771                p = get_local_var(src);
2772
2773        if (!p || strlen(p) == 0) {
2774                p = default_val;
2775                if (assign) {
2776                        char *var = malloc(strlen(src)+strlen(default_val)+2);
2777                        if (var) {
2778                                sprintf(var, "%s=%s", src, default_val);
2779                                set_local_var(var, 0);
2780                        }
2781                        free(var);
2782                }
2783        } else if (expand_empty) {
2784                p += strlen(p);
2785        }
2786
2787        if (sep)
2788                *sep = ':';
2789
2790        return p;
2791}
2792
2793#ifdef __U_BOOT__
2794static char *get_dollar_var(char ch)
2795{
2796        static char buf[40];
2797
2798        buf[0] = '\0';
2799        switch (ch) {
2800                case '?':
2801                        sprintf(buf, "%u", (unsigned int)last_return_code);
2802                        break;
2803                default:
2804                        return NULL;
2805        }
2806        return buf;
2807}
2808#endif
2809
2810/* return code: 0 for OK, 1 for syntax error */
2811static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input)
2812{
2813#ifndef __U_BOOT__
2814        int i, advance=0;
2815#else
2816        int advance=0;
2817#endif
2818#ifndef __U_BOOT__
2819        char sep[]=" ";
2820#endif
2821        int ch = input->peek(input);  /* first character after the $ */
2822        debug_printf("handle_dollar: ch=%c\n",ch);
2823        if (isalpha(ch)) {
2824                b_addchr(dest, SPECIAL_VAR_SYMBOL);
2825                ctx->child->sp++;
2826                while(ch=b_peek(input),isalnum(ch) || ch=='_') {
2827                        b_getch(input);
2828                        b_addchr(dest,ch);
2829                }
2830                b_addchr(dest, SPECIAL_VAR_SYMBOL);
2831#ifndef __U_BOOT__
2832        } else if (isdigit(ch)) {
2833                i = ch-'0';  /* XXX is $0 special? */
2834                if (i<global_argc) {
2835                        parse_string(dest, ctx, global_argv[i]); /* recursion */
2836                }
2837                advance = 1;
2838#endif
2839        } else switch (ch) {
2840#ifndef __U_BOOT__
2841                case '$':
2842                        b_adduint(dest,getpid());
2843                        advance = 1;
2844                        break;
2845                case '!':
2846                        if (last_bg_pid > 0) b_adduint(dest, last_bg_pid);
2847                        advance = 1;
2848                        break;
2849#endif
2850                case '?':
2851#ifndef __U_BOOT__
2852                        b_adduint(dest,last_return_code);
2853#else
2854                        ctx->child->sp++;
2855                        b_addchr(dest, SPECIAL_VAR_SYMBOL);
2856                        b_addchr(dest, '$');
2857                        b_addchr(dest, '?');
2858                        b_addchr(dest, SPECIAL_VAR_SYMBOL);
2859#endif
2860                        advance = 1;
2861                        break;
2862#ifndef __U_BOOT__
2863                case '#':
2864                        b_adduint(dest,global_argc ? global_argc-1 : 0);
2865                        advance = 1;
2866                        break;
2867#endif
2868                case '{':
2869                        b_addchr(dest, SPECIAL_VAR_SYMBOL);
2870                        ctx->child->sp++;
2871                        b_getch(input);
2872                        /* XXX maybe someone will try to escape the '}' */
2873                        while(ch=b_getch(input),ch!=EOF && ch!='}') {
2874                                b_addchr(dest,ch);
2875                        }
2876                        if (ch != '}') {
2877                                syntax();
2878                                return 1;
2879                        }
2880                        b_addchr(dest, SPECIAL_VAR_SYMBOL);
2881                        break;
2882#ifndef __U_BOOT__
2883                case '(':
2884                        b_getch(input);
2885                        process_command_subs(dest, ctx, input, ')');
2886                        break;
2887                case '*':
2888                        sep[0]=ifs[0];
2889                        for (i=1; i<global_argc; i++) {
2890                                parse_string(dest, ctx, global_argv[i]);
2891                                if (i+1 < global_argc) parse_string(dest, ctx, sep);
2892                        }
2893                        break;
2894                case '@':
2895                case '-':
2896                case '_':
2897                        /* still unhandled, but should be eventually */
2898                        error_msg("unhandled syntax: $%c",ch);
2899                        return 1;
2900                        break;
2901#endif
2902                default:
2903                        b_addqchr(dest,'$',dest->quote);
2904        }
2905        /* Eat the character if the flag was set.  If the compiler
2906         * is smart enough, we could substitute "b_getch(input);"
2907         * for all the "advance = 1;" above, and also end up with
2908         * a nice size-optimized program.  Hah!  That'll be the day.
2909         */
2910        if (advance) b_getch(input);
2911        return 0;
2912}
2913
2914#ifndef __U_BOOT__
2915int parse_string(o_string *dest, struct p_context *ctx, const char *src)
2916{
2917        struct in_str foo;
2918        setup_string_in_str(&foo, src);
2919        return parse_stream(dest, ctx, &foo, '\0');
2920}
2921#endif
2922
2923/* return code is 0 for normal exit, 1 for syntax error */
2924static int parse_stream(o_string *dest, struct p_context *ctx,
2925                        struct in_str *input, int end_trigger)
2926{
2927        unsigned int ch, m;
2928#ifndef __U_BOOT__
2929        int redir_fd;
2930        redir_type redir_style;
2931#endif
2932        int next;
2933
2934        /* Only double-quote state is handled in the state variable dest->quote.
2935         * A single-quote triggers a bypass of the main loop until its mate is
2936         * found.  When recursing, quote state is passed in via dest->quote. */
2937
2938        debug_printf("parse_stream, end_trigger=%d\n",end_trigger);
2939        while ((ch=b_getch(input))!=EOF) {
2940                m = map[ch];
2941#ifdef __U_BOOT__
2942                if (input->__promptme == 0) return 1;
2943#endif
2944                next = (ch == '\n') ? 0 : b_peek(input);
2945
2946                debug_printf("parse_stream: ch=%c (%d) m=%d quote=%d - %c\n",
2947                        ch >= ' ' ? ch : '.', ch, m,
2948                        dest->quote, ctx->stack == NULL ? '*' : '.');
2949
2950                if (m==0 || ((m==1 || m==2) && dest->quote)) {
2951                        b_addqchr(dest, ch, dest->quote);
2952                } else {
2953                        if (m==2) {  /* unquoted IFS */
2954                                if (done_word(dest, ctx)) {
2955                                        return 1;
2956                                }
2957                                /* If we aren't performing a substitution, treat a newline as a
2958                                 * command separator.  */
2959                                if (end_trigger != '\0' && ch=='\n')
2960                                        done_pipe(ctx,PIPE_SEQ);
2961                        }
2962                        if (ch == end_trigger && !dest->quote && ctx->w==RES_NONE) {
2963                                debug_printf("leaving parse_stream (triggered)\n");
2964                                return 0;
2965                        }
2966#if 0
2967                        if (ch=='\n') {
2968                                /* Yahoo!  Time to run with it! */
2969                                done_pipe(ctx,PIPE_SEQ);
2970                                run_list(ctx->list_head);
2971                                initialize_context(ctx);
2972                        }
2973#endif
2974                        if (m!=2) switch (ch) {
2975                case '#':
2976                        if (dest->length == 0 && !dest->quote) {
2977                                while(ch=b_peek(input),ch!=EOF && ch!='\n') { b_getch(input); }
2978                        } else {
2979                                b_addqchr(dest, ch, dest->quote);
2980                        }
2981                        break;
2982                case '\\':
2983                        if (next == EOF) {
2984                                syntax();
2985                                return 1;
2986                        }
2987                        b_addqchr(dest, '\\', dest->quote);
2988                        b_addqchr(dest, b_getch(input), dest->quote);
2989                        break;
2990                case '$':
2991                        if (handle_dollar(dest, ctx, input)!=0) return 1;
2992                        break;
2993                case '\'':
2994                        dest->nonnull = 1;
2995                        while(ch=b_getch(input),ch!=EOF && ch!='\'') {
2996#ifdef __U_BOOT__
2997                                if(input->__promptme == 0) return 1;
2998#endif
2999                                b_addchr(dest,ch);
3000                        }
3001                        if (ch==EOF) {
3002                                syntax();
3003                                return 1;
3004                        }
3005                        break;
3006                case '"':
3007                        dest->nonnull = 1;
3008                        dest->quote = !dest->quote;
3009                        break;
3010#ifndef __U_BOOT__
3011                case '`':
3012                        process_command_subs(dest, ctx, input, '`');
3013                        break;
3014                case '>':
3015                        redir_fd = redirect_opt_num(dest);
3016                        done_word(dest, ctx);
3017                        redir_style=REDIRECT_OVERWRITE;
3018                        if (next == '>') {
3019                                redir_style=REDIRECT_APPEND;
3020                                b_getch(input);
3021                        } else if (next == '(') {
3022                                syntax();   /* until we support >(list) Process Substitution */
3023                                return 1;
3024                        }
3025                        setup_redirect(ctx, redir_fd, redir_style, input);
3026                        break;
3027                case '<':
3028                        redir_fd = redirect_opt_num(dest);
3029                        done_word(dest, ctx);
3030                        redir_style=REDIRECT_INPUT;
3031                        if (next == '<') {
3032                                redir_style=REDIRECT_HEREIS;
3033                                b_getch(input);
3034                        } else if (next == '>') {
3035                                redir_style=REDIRECT_IO;
3036                                b_getch(input);
3037                        } else if (next == '(') {
3038                                syntax();   /* until we support <(list) Process Substitution */
3039                                return 1;
3040                        }
3041                        setup_redirect(ctx, redir_fd, redir_style, input);
3042                        break;
3043#endif
3044                case ';':
3045                        done_word(dest, ctx);
3046                        done_pipe(ctx,PIPE_SEQ);
3047                        break;
3048                case '&':
3049                        done_word(dest, ctx);
3050                        if (next=='&') {
3051                                b_getch(input);
3052                                done_pipe(ctx,PIPE_AND);
3053                        } else {
3054#ifndef __U_BOOT__
3055                                done_pipe(ctx,PIPE_BG);
3056#else
3057                                syntax_err();
3058                                return 1;
3059#endif
3060                        }
3061                        break;
3062                case '|':
3063                        done_word(dest, ctx);
3064                        if (next=='|') {
3065                                b_getch(input);
3066                                done_pipe(ctx,PIPE_OR);
3067                        } else {
3068                                /* we could pick up a file descriptor choice here
3069                                 * with redirect_opt_num(), but bash doesn't do it.
3070                                 * "echo foo 2| cat" yields "foo 2". */
3071#ifndef __U_BOOT__
3072                                done_command(ctx);
3073#else
3074                                syntax_err();
3075                                return 1;
3076#endif
3077                        }
3078                        break;
3079#ifndef __U_BOOT__
3080                case '(':
3081                case '{':
3082                        if (parse_group(dest, ctx, input, ch)!=0) return 1;
3083                        break;
3084                case ')':
3085                case '}':
3086                        syntax();   /* Proper use of this character caught by end_trigger */
3087                        return 1;
3088                        break;
3089#endif
3090                case SUBSTED_VAR_SYMBOL:
3091                        dest->nonnull = 1;
3092                        while (ch = b_getch(input), ch != EOF &&
3093                            ch != SUBSTED_VAR_SYMBOL) {
3094                                debug_printf("subst, pass=%d\n", ch);
3095                                if (input->__promptme == 0)
3096                                        return 1;
3097                                b_addchr(dest, ch);
3098                        }
3099                        debug_printf("subst, term=%d\n", ch);
3100                        if (ch == EOF) {
3101                                syntax();
3102                                return 1;
3103                        }
3104                        break;
3105                default:
3106                        syntax();   /* this is really an internal logic error */
3107                        return 1;
3108                        }
3109                }
3110        }
3111        /* complain if quote?  No, maybe we just finished a command substitution
3112         * that was quoted.  Example:
3113         * $ echo "`cat foo` plus more"
3114         * and we just got the EOF generated by the subshell that ran "cat foo"
3115         * The only real complaint is if we got an EOF when end_trigger != '\0',
3116         * that is, we were really supposed to get end_trigger, and never got
3117         * one before the EOF.  Can't use the standard "syntax error" return code,
3118         * so that parse_stream_outer can distinguish the EOF and exit smoothly. */
3119        debug_printf("leaving parse_stream (EOF)\n");
3120        if (end_trigger != '\0') return -1;
3121        return 0;
3122}
3123
3124static void mapset(const unsigned char *set, int code)
3125{
3126        const unsigned char *s;
3127        for (s=set; *s; s++) map[*s] = code;
3128}
3129
3130static void update_ifs_map(void)
3131{
3132        /* char *ifs and char map[256] are both globals. */
3133        ifs = (uchar *)getenv("IFS");
3134        if (ifs == NULL) ifs=(uchar *)" \t\n";
3135        /* Precompute a list of 'flow through' behavior so it can be treated
3136         * quickly up front.  Computation is necessary because of IFS.
3137         * Special case handling of IFS == " \t\n" is not implemented.
3138         * The map[] array only really needs two bits each, and on most machines
3139         * that would be faster because of the reduced L1 cache footprint.
3140         */
3141        memset(map,0,sizeof(map)); /* most characters flow through always */
3142#ifndef __U_BOOT__
3143        mapset((uchar *)"\\$'\"`", 3);      /* never flow through */
3144        mapset((uchar *)"<>;&|(){}#", 1);   /* flow through if quoted */
3145#else
3146        {
3147                uchar subst[2] = {SUBSTED_VAR_SYMBOL, 0};
3148                mapset(subst, 3);       /* never flow through */
3149        }
3150        mapset((uchar *)"\\$'\"", 3);       /* never flow through */
3151        mapset((uchar *)";&|#", 1);         /* flow through if quoted */
3152#endif
3153        mapset(ifs, 2);            /* also flow through if quoted */
3154}
3155
3156/* most recursion does not come through here, the exeception is
3157 * from builtin_source() */
3158static int parse_stream_outer(struct in_str *inp, int flag)
3159{
3160
3161        struct p_context ctx;
3162        o_string temp=NULL_O_STRING;
3163        int rcode;
3164#ifdef __U_BOOT__
3165        int code = 1;
3166#endif
3167        do {
3168                ctx.type = flag;
3169                initialize_context(&ctx);
3170                update_ifs_map();
3171                if (!(flag & FLAG_PARSE_SEMICOLON) || (flag & FLAG_REPARSING)) mapset((uchar *)";$&|", 0);
3172                inp->promptmode=1;
3173                rcode = parse_stream(&temp, &ctx, inp,
3174                                     flag & FLAG_CONT_ON_NEWLINE ? -1 : '\n');
3175#ifdef __U_BOOT__
3176                if (rcode == 1) flag_repeat = 0;
3177#endif
3178                if (rcode != 1 && ctx.old_flag != 0) {
3179                        syntax();
3180#ifdef __U_BOOT__
3181                        flag_repeat = 0;
3182#endif
3183                }
3184                if (rcode != 1 && ctx.old_flag == 0) {
3185                        done_word(&temp, &ctx);
3186                        done_pipe(&ctx,PIPE_SEQ);
3187#ifndef __U_BOOT__
3188                        run_list(ctx.list_head);
3189#else
3190                        code = run_list(ctx.list_head);
3191                        if (code == -2) {       /* exit */
3192                                b_free(&temp);
3193                                code = 0;
3194                                /* XXX hackish way to not allow exit from main loop */
3195                                if (inp->peek == file_peek) {
3196                                        printf("exit not allowed from main input shell.\n");
3197                                        continue;
3198                                }
3199                                break;
3200                        }
3201                        if (code == -1)
3202                            flag_repeat = 0;
3203#endif
3204                } else {
3205                        if (ctx.old_flag != 0) {
3206                                free(ctx.stack);
3207                                b_reset(&temp);
3208                        }
3209#ifdef __U_BOOT__
3210                        if (inp->__promptme == 0) printf("<INTERRUPT>\n");
3211                        inp->__promptme = 1;
3212#endif
3213                        temp.nonnull = 0;
3214                        temp.quote = 0;
3215                        inp->p = NULL;
3216                        free_pipe_list(ctx.list_head,0);
3217                }
3218                b_free(&temp);
3219        /* loop on syntax errors, return on EOF */
3220        } while (rcode != -1 && !(flag & FLAG_EXIT_FROM_LOOP) &&
3221                (inp->peek != static_peek || b_peek(inp)));
3222#ifndef __U_BOOT__
3223        return 0;
3224#else
3225        return (code != 0) ? 1 : 0;
3226#endif /* __U_BOOT__ */
3227}
3228
3229#ifndef __U_BOOT__
3230static int parse_string_outer(const char *s, int flag)
3231#else
3232int parse_string_outer(const char *s, int flag)
3233#endif  /* __U_BOOT__ */
3234{
3235        struct in_str input;
3236#ifdef __U_BOOT__
3237        char *p = NULL;
3238        int rcode;
3239        if (!s)
3240                return 1;
3241        if (!*s)
3242                return 0;
3243        if (!(p = strchr(s, '\n')) || *++p) {
3244                p = xmalloc(strlen(s) + 2);
3245                strcpy(p, s);
3246                strcat(p, "\n");
3247                setup_string_in_str(&input, p);
3248                rcode = parse_stream_outer(&input, flag);
3249                free(p);
3250                return rcode;
3251        } else {
3252#endif
3253        setup_string_in_str(&input, s);
3254        return parse_stream_outer(&input, flag);
3255#ifdef __U_BOOT__
3256        }
3257#endif
3258}
3259
3260#ifndef __U_BOOT__
3261static int parse_file_outer(FILE *f)
3262#else
3263int parse_file_outer(void)
3264#endif
3265{
3266        int rcode;
3267        struct in_str input;
3268#ifndef __U_BOOT__
3269        setup_file_in_str(&input, f);
3270#else
3271        setup_file_in_str(&input);
3272#endif
3273        rcode = parse_stream_outer(&input, FLAG_PARSE_SEMICOLON);
3274        return rcode;
3275}
3276
3277#ifdef __U_BOOT__
3278#ifdef CONFIG_NEEDS_MANUAL_RELOC
3279static void u_boot_hush_reloc(void)
3280{
3281        unsigned long addr;
3282        struct reserved_combo *r;
3283
3284        for (r=reserved_list; r<reserved_list+NRES; r++) {
3285                addr = (ulong) (r->literal) + gd->reloc_off;
3286                r->literal = (char *)addr;
3287        }
3288}
3289#endif
3290
3291int u_boot_hush_start(void)
3292{
3293        if (top_vars == NULL) {
3294                top_vars = malloc(sizeof(struct variables));
3295                top_vars->name = "HUSH_VERSION";
3296                top_vars->value = "0.01";
3297                top_vars->next = NULL;
3298                top_vars->flg_export = 0;
3299                top_vars->flg_read_only = 1;
3300#ifdef CONFIG_NEEDS_MANUAL_RELOC
3301                u_boot_hush_reloc();
3302#endif
3303        }
3304        return 0;
3305}
3306
3307static void *xmalloc(size_t size)
3308{
3309        void *p = NULL;
3310
3311        if (!(p = malloc(size))) {
3312            printf("ERROR : memory not allocated\n");
3313            for(;;);
3314        }
3315        return p;
3316}
3317
3318static void *xrealloc(void *ptr, size_t size)
3319{
3320        void *p = NULL;
3321
3322        if (!(p = realloc(ptr, size))) {
3323            printf("ERROR : memory not allocated\n");
3324            for(;;);
3325        }
3326        return p;
3327}
3328#endif /* __U_BOOT__ */
3329
3330#ifndef __U_BOOT__
3331/* Make sure we have a controlling tty.  If we get started under a job
3332 * aware app (like bash for example), make sure we are now in charge so
3333 * we don't fight over who gets the foreground */
3334static void setup_job_control(void)
3335{
3336        static pid_t shell_pgrp;
3337        /* Loop until we are in the foreground.  */
3338        while (tcgetpgrp (shell_terminal) != (shell_pgrp = getpgrp ()))
3339                kill (- shell_pgrp, SIGTTIN);
3340
3341        /* Ignore interactive and job-control signals.  */
3342        signal(SIGINT, SIG_IGN);
3343        signal(SIGQUIT, SIG_IGN);
3344        signal(SIGTERM, SIG_IGN);
3345        signal(SIGTSTP, SIG_IGN);
3346        signal(SIGTTIN, SIG_IGN);
3347        signal(SIGTTOU, SIG_IGN);
3348        signal(SIGCHLD, SIG_IGN);
3349
3350        /* Put ourselves in our own process group.  */
3351        setsid();
3352        shell_pgrp = getpid ();
3353        setpgid (shell_pgrp, shell_pgrp);
3354
3355        /* Grab control of the terminal.  */
3356        tcsetpgrp(shell_terminal, shell_pgrp);
3357}
3358
3359int hush_main(int argc, char * const *argv)
3360{
3361        int opt;
3362        FILE *input;
3363        char **e = environ;
3364
3365        /* XXX what should these be while sourcing /etc/profile? */
3366        global_argc = argc;
3367        global_argv = argv;
3368
3369        /* (re?) initialize globals.  Sometimes hush_main() ends up calling
3370         * hush_main(), therefore we cannot rely on the BSS to zero out this
3371         * stuff.  Reset these to 0 every time. */
3372        ifs = NULL;
3373        /* map[] is taken care of with call to update_ifs_map() */
3374        fake_mode = 0;
3375        interactive = 0;
3376        close_me_head = NULL;
3377        last_bg_pid = 0;
3378        job_list = NULL;
3379        last_jobid = 0;
3380
3381        /* Initialize some more globals to non-zero values */
3382        set_cwd();
3383#ifdef CONFIG_FEATURE_COMMAND_EDITING
3384        cmdedit_set_initial_prompt();
3385#else
3386        PS1 = NULL;
3387#endif
3388        PS2 = "> ";
3389
3390        /* initialize our shell local variables with the values
3391         * currently living in the environment */
3392        if (e) {
3393                for (; *e; e++)
3394                        set_local_var(*e, 2);   /* without call putenv() */
3395        }
3396
3397        last_return_code=EXIT_SUCCESS;
3398
3399
3400        if (argv[0] && argv[0][0] == '-') {
3401                debug_printf("\nsourcing /etc/profile\n");
3402                if ((input = fopen("/etc/profile", "r")) != NULL) {
3403                        mark_open(fileno(input));
3404                        parse_file_outer(input);
3405                        mark_closed(fileno(input));
3406                        fclose(input);
3407                }
3408        }
3409        input=stdin;
3410
3411        while ((opt = getopt(argc, argv, "c:xif")) > 0) {
3412                switch (opt) {
3413                        case 'c':
3414                                {
3415                                        global_argv = argv+optind;
3416                                        global_argc = argc-optind;
3417                                        opt = parse_string_outer(optarg, FLAG_PARSE_SEMICOLON);
3418                                        goto final_return;
3419                                }
3420                                break;
3421                        case 'i':
3422                                interactive++;
3423                                break;
3424                        case 'f':
3425                                fake_mode++;
3426                                break;
3427                        default:
3428#ifndef BB_VER
3429                                fprintf(stderr, "Usage: sh [FILE]...\n"
3430                                                "   or: sh -c command [args]...\n\n");
3431                                exit(EXIT_FAILURE);
3432#else
3433                                show_usage();
3434#endif
3435                }
3436        }
3437        /* A shell is interactive if the `-i' flag was given, or if all of
3438         * the following conditions are met:
3439         *        no -c command
3440         *    no arguments remaining or the -s flag given
3441         *    standard input is a terminal
3442         *    standard output is a terminal
3443         *    Refer to Posix.2, the description of the `sh' utility. */
3444        if (argv[optind]==NULL && input==stdin &&
3445                        isatty(fileno(stdin)) && isatty(fileno(stdout))) {
3446                interactive++;
3447        }
3448
3449        debug_printf("\ninteractive=%d\n", interactive);
3450        if (interactive) {
3451                /* Looks like they want an interactive shell */
3452#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
3453                printf( "\n\n" BB_BANNER " hush - the humble shell v0.01 (testing)\n");
3454                printf( "Enter 'help' for a list of built-in commands.\n\n");
3455#endif
3456                setup_job_control();
3457        }
3458
3459        if (argv[optind]==NULL) {
3460                opt=parse_file_outer(stdin);
3461                goto final_return;
3462        }
3463
3464        debug_printf("\nrunning script '%s'\n", argv[optind]);
3465        global_argv = argv+optind;
3466        global_argc = argc-optind;
3467        input = xfopen(argv[optind], "r");
3468        opt = parse_file_outer(input);
3469
3470#ifdef CONFIG_FEATURE_CLEAN_UP
3471        fclose(input);
3472        if (cwd && cwd != unknown)
3473                free((char*)cwd);
3474        {
3475                struct variables *cur, *tmp;
3476                for(cur = top_vars; cur; cur = tmp) {
3477                        tmp = cur->next;
3478                        if (!cur->flg_read_only) {
3479                                free(cur->name);
3480                                free(cur->value);
3481                                free(cur);
3482                        }
3483                }
3484        }
3485#endif
3486
3487final_return:
3488        return(opt?opt:last_return_code);
3489}
3490#endif
3491
3492static char *insert_var_value(char *inp)
3493{
3494        return insert_var_value_sub(inp, 0);
3495}
3496
3497static char *insert_var_value_sub(char *inp, int tag_subst)
3498{
3499        int res_str_len = 0;
3500        int len;
3501        int done = 0;
3502        char *p, *p1, *res_str = NULL;
3503
3504        while ((p = strchr(inp, SPECIAL_VAR_SYMBOL))) {
3505                /* check the beginning of the string for normal charachters */
3506                if (p != inp) {
3507                        /* copy any charachters to the result string */
3508                        len = p - inp;
3509                        res_str = xrealloc(res_str, (res_str_len + len));
3510                        strncpy((res_str + res_str_len), inp, len);
3511                        res_str_len += len;
3512                }
3513                inp = ++p;
3514                /* find the ending marker */
3515                p = strchr(inp, SPECIAL_VAR_SYMBOL);
3516                *p = '\0';
3517                /* look up the value to substitute */
3518                if ((p1 = lookup_param(inp))) {
3519                        if (tag_subst)
3520                                len = res_str_len + strlen(p1) + 2;
3521                        else
3522                                len = res_str_len + strlen(p1);
3523                        res_str = xrealloc(res_str, (1 + len));
3524                        if (tag_subst) {
3525                                /*
3526                                 * copy the variable value to the result
3527                                 * string
3528                                 */
3529                                strcpy((res_str + res_str_len + 1), p1);
3530
3531                                /*
3532                                 * mark the replaced text to be accepted as
3533                                 * is
3534                                 */
3535                                res_str[res_str_len] = SUBSTED_VAR_SYMBOL;
3536                                res_str[res_str_len + 1 + strlen(p1)] =
3537                                        SUBSTED_VAR_SYMBOL;
3538                        } else
3539                                /*
3540                                 * copy the variable value to the result
3541                                 * string
3542                                 */
3543                                strcpy((res_str + res_str_len), p1);
3544
3545                        res_str_len = len;
3546                }
3547                *p = SPECIAL_VAR_SYMBOL;
3548                inp = ++p;
3549                done = 1;
3550        }
3551        if (done) {
3552                res_str = xrealloc(res_str, (1 + res_str_len + strlen(inp)));
3553                strcpy((res_str + res_str_len), inp);
3554                while ((p = strchr(res_str, '\n'))) {
3555                        *p = ' ';
3556                }
3557        }
3558        return (res_str == NULL) ? inp : res_str;
3559}
3560
3561static char **make_list_in(char **inp, char *name)
3562{
3563        int len, i;
3564        int name_len = strlen(name);
3565        int n = 0;
3566        char **list;
3567        char *p1, *p2, *p3;
3568
3569        /* create list of variable values */
3570        list = xmalloc(sizeof(*list));
3571        for (i = 0; inp[i]; i++) {
3572                p3 = insert_var_value(inp[i]);
3573                p1 = p3;
3574                while (*p1) {
3575                        if (*p1 == ' ') {
3576                                p1++;
3577                                continue;
3578                        }
3579                        if ((p2 = strchr(p1, ' '))) {
3580                                len = p2 - p1;
3581                        } else {
3582                                len = strlen(p1);
3583                                p2 = p1 + len;
3584                        }
3585                        /* we use n + 2 in realloc for list,because we add
3586                         * new element and then we will add NULL element */
3587                        list = xrealloc(list, sizeof(*list) * (n + 2));
3588                        list[n] = xmalloc(2 + name_len + len);
3589                        strcpy(list[n], name);
3590                        strcat(list[n], "=");
3591                        strncat(list[n], p1, len);
3592                        list[n++][name_len + len + 1] = '\0';
3593                        p1 = p2;
3594                }
3595                if (p3 != inp[i]) free(p3);
3596        }
3597        list[n] = NULL;
3598        return list;
3599}
3600
3601/*
3602 * Make new string for parser
3603 * inp     - array of argument strings to flatten
3604 * nonnull - indicates argument was quoted when originally parsed
3605 */
3606static char *make_string(char **inp, int *nonnull)
3607{
3608        char *p;
3609        char *str = NULL;
3610        int n;
3611        int len = 2;
3612        char *noeval_str;
3613        int noeval = 0;
3614
3615        noeval_str = get_local_var("HUSH_NO_EVAL");
3616        if (noeval_str != NULL && *noeval_str != '0' && *noeval_str != '\0')
3617                noeval = 1;
3618        for (n = 0; inp[n]; n++) {
3619                p = insert_var_value_sub(inp[n], noeval);
3620                str = xrealloc(str, (len + strlen(p) + (2 * nonnull[n])));
3621                if (n) {
3622                        strcat(str, " ");
3623                } else {
3624                        *str = '\0';
3625                }
3626                if (nonnull[n])
3627                        strcat(str, "'");
3628                strcat(str, p);
3629                if (nonnull[n])
3630                        strcat(str, "'");
3631                len = strlen(str) + 3;
3632                if (p != inp[n]) free(p);
3633        }
3634        len = strlen(str);
3635        *(str + len) = '\n';
3636        *(str + len + 1) = '\0';
3637        return str;
3638}
3639
3640#ifdef __U_BOOT__
3641static int do_showvar(cmd_tbl_t *cmdtp, int flag, int argc,
3642                      char * const argv[])
3643{
3644        int i, k;
3645        int rcode = 0;
3646        struct variables *cur;
3647
3648        if (argc == 1) {                /* Print all env variables      */
3649                for (cur = top_vars; cur; cur = cur->next) {
3650                        printf ("%s=%s\n", cur->name, cur->value);
3651                        if (ctrlc ()) {
3652                                puts ("\n ** Abort\n");
3653                                return 1;
3654                        }
3655                }
3656                return 0;
3657        }
3658        for (i = 1; i < argc; ++i) {    /* print single env variables   */
3659                char *name = argv[i];
3660
3661                k = -1;
3662                for (cur = top_vars; cur; cur = cur->next) {
3663                        if(strcmp (cur->name, name) == 0) {
3664                                k = 0;
3665                                printf ("%s=%s\n", cur->name, cur->value);
3666                        }
3667                        if (ctrlc ()) {
3668                                puts ("\n ** Abort\n");
3669                                return 1;
3670                        }
3671                }
3672                if (k < 0) {
3673                        printf ("## Error: \"%s\" not defined\n", name);
3674                        rcode ++;
3675                }
3676        }
3677        return rcode;
3678}
3679
3680U_BOOT_CMD(
3681        showvar, CONFIG_SYS_MAXARGS, 1, do_showvar,
3682        "print local hushshell variables",
3683        "\n    - print values of all hushshell variables\n"
3684        "showvar name ...\n"
3685        "    - print value of hushshell variable 'name'"
3686);
3687
3688#endif
3689/****************************************************************************/
3690