Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/shell/hush.c


Ignore:
Timestamp:
Feb 25, 2011, 9:26:54 PM (13 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.9/mindi-busybox/shell/hush.c

    r1765 r2725  
    11/* vi: set sw=4 ts=4: */
    22/*
    3  * sh.c -- a prototype Bourne shell grammar parser
    4  *      Intended to follow the original Thompson and Ritchie
    5  *      "small and simple is beautiful" philosophy, which
    6  *      incidentally is a good match to today's BusyBox.
     3 * A prototype Bourne shell grammar parser.
     4 * Intended to follow the original Thompson and Ritchie
     5 * "small and simple is beautiful" philosophy, which
     6 * incidentally is a good match to today's BusyBox.
    77 *
    8  * Copyright (C) 2000,2001  Larry Doolittle  <larry@doolittle.boa.org>
     8 * Copyright (C) 2000,2001  Larry Doolittle <larry@doolittle.boa.org>
     9 * Copyright (C) 2008,2009  Denys Vlasenko <vda.linux@googlemail.com>
     10 *
     11 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    912 *
    1013 * Credits:
     
    2124 *
    2225 * Other credits:
    23  *      b_addchr() derived from similar w_addchar function in glibc-2.2
    24  *      setup_redirect(), redirect_opt_num(), and big chunks of main()
    25  *      and many builtins derived from contributions by Erik Andersen
    26  *      miscellaneous bugfixes from Matt Kraai
     26 *      o_addchr derived from similar w_addchar function in glibc-2.2.
     27 *      parse_redirect, redirect_opt_num, and big chunks of main
     28 *      and many builtins derived from contributions by Erik Andersen.
     29 *      Miscellaneous bugfixes from Matt Kraai.
    2730 *
    2831 * There are two big (and related) architecture differences between
     
    3740 * across continuation lines.
    3841 *
    39  * Bash grammar not implemented: (how many of these were in original sh?)
    40  *      $_
    41  *      ! negation operator for pipes
    42  *      &> and >& redirection of stdout+stderr
    43  *      Brace Expansion
    44  *      Tilde Expansion
    45  *      fancy forms of Parameter Expansion
     42 * TODOs:
     43 *      grep for "TODO" and fix (some of them are easy)
     44 *      special variables (done: PWD, PPID, RANDOM)
     45 *      tilde expansion
    4646 *      aliases
    47  *      Arithmetic Expansion
    48  *      <(list) and >(list) Process Substitution
    49  *      reserved words: case, esac, select, function
    50  *      Here Documents ( << word )
    51  *      Functions
    52  * Major bugs:
    53  *      job handling woefully incomplete and buggy (improved --vda)
    54  *      reserved word execution woefully incomplete and buggy
    55  * to-do:
    56  *      port selected bugfixes from post-0.49 busybox lash - done?
    57  *      finish implementing reserved words: for, while, until, do, done
    58  *      change { and } from special chars to reserved words
    59  *      builtins: break, continue, eval, return, set, trap, ulimit
    60  *      test magic exec
    61  *      handle children going into background
    62  *      clean up recognition of null pipes
    63  *      check setting of global_argc and global_argv
    64  *      control-C handling, probably with longjmp
    6547 *      follow IFS rules more precisely, including update semantics
    66  *      figure out what to do with backslash-newline
    67  *      explain why we use signal instead of sigaction
    68  *      propagate syntax errors, die on resource errors?
    69  *      continuation lines, both explicit and implicit - done?
    70  *      memory leak finding and plugging - done?
    71  *      more testing, especially quoting rules and redirection
    72  *      document how quoting rules not precisely followed for variable assignments
    73  *      maybe change charmap[] to use 2-bit entries
    74  *      (eventually) remove all the printf's
     48 *      builtins mandated by standards we don't support:
     49 *          [un]alias, command, fc, getopts, newgrp, readonly, times
     50 *      make complex ${var%...} constructs support optional
     51 *      make here documents optional
    7552 *
    76  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
     53 * Bash compat TODO:
     54 *      redirection of stdout+stderr: &> and >&
     55 *      reserved words: function select
     56 *      advanced test: [[ ]]
     57 *      process substitution: <(list) and >(list)
     58 *      =~: regex operator
     59 *      let EXPR [EXPR...]
     60 *          Each EXPR is an arithmetic expression (ARITHMETIC EVALUATION)
     61 *          If the last arg evaluates to 0, let returns 1; 0 otherwise.
     62 *          NB: let `echo 'a=a + 1'` - error (IOW: multi-word expansion is used)
     63 *      ((EXPR))
     64 *          The EXPR is evaluated according to ARITHMETIC EVALUATION.
     65 *          This is exactly equivalent to let "EXPR".
     66 *      $[EXPR]: synonym for $((EXPR))
     67 *
     68 * Won't do:
     69 *      In bash, export builtin is special, its arguments are assignments
     70 *          and therefore expansion of them should be "one-word" expansion:
     71 *              $ export i=`echo 'a  b'` # export has one arg: "i=a  b"
     72 *          compare with:
     73 *              $ ls i=`echo 'a  b'`     # ls has two args: "i=a" and "b"
     74 *              ls: cannot access i=a: No such file or directory
     75 *              ls: cannot access b: No such file or directory
     76 *          Note1: same applies to local builtin.
     77 *          Note2: bash 3.2.33(1) does this only if export word itself
     78 *          is not quoted:
     79 *              $ export i=`echo 'aaa  bbb'`; echo "$i"
     80 *              aaa  bbb
     81 *              $ "export" i=`echo 'aaa  bbb'`; echo "$i"
     82 *              aaa
    7783 */
    78 
    79 
    80 #include <glob.h>      /* glob, of course */
    81 #include <getopt.h>    /* should be pretty obvious */
     84#include "busybox.h"  /* for APPLET_IS_NOFORK/NOEXEC */
     85#include <malloc.h>   /* for malloc_trim */
     86#include <glob.h>
    8287/* #include <dmalloc.h> */
    83 
    84 extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */
    85 
    86 #include "busybox.h" /* for struct bb_applet */
    87 
     88#if ENABLE_HUSH_CASE
     89# include <fnmatch.h>
     90#endif
     91
     92#include "shell_common.h"
     93#include "math.h"
     94#include "match.h"
     95#if ENABLE_HUSH_RANDOM_SUPPORT
     96# include "random.h"
     97#else
     98# define CLEAR_RANDOM_T(rnd) ((void)0)
     99#endif
     100#ifndef PIPE_BUF
     101# define PIPE_BUF 4096  /* amount of buffering in a pipe */
     102#endif
     103
     104//applet:IF_HUSH(APPLET(hush, _BB_DIR_BIN, _BB_SUID_DROP))
     105//applet:IF_MSH(APPLET(msh, _BB_DIR_BIN, _BB_SUID_DROP))
     106//applet:IF_FEATURE_SH_IS_HUSH(APPLET_ODDNAME(sh, hush, _BB_DIR_BIN, _BB_SUID_DROP, sh))
     107//applet:IF_FEATURE_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, _BB_DIR_BIN, _BB_SUID_DROP, bash))
     108
     109//kbuild:lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o
     110//kbuild:lib-$(CONFIG_HUSH_RANDOM_SUPPORT) += random.o
     111
     112//config:config HUSH
     113//config:   bool "hush"
     114//config:   default y
     115//config:   help
     116//config:     hush is a small shell (25k). It handles the normal flow control
     117//config:     constructs such as if/then/elif/else/fi, for/in/do/done, while loops,
     118//config:     case/esac. Redirections, here documents, $((arithmetic))
     119//config:     and functions are supported.
     120//config:
     121//config:     It will compile and work on no-mmu systems.
     122//config:
     123//config:     It does not handle select, aliases, tilde expansion,
     124//config:     &>file and >&file redirection of stdout+stderr.
     125//config:
     126//config:config HUSH_BASH_COMPAT
     127//config:   bool "bash-compatible extensions"
     128//config:   default y
     129//config:   depends on HUSH
     130//config:   help
     131//config:     Enable bash-compatible extensions.
     132//config:
     133//config:config HUSH_BRACE_EXPANSION
     134//config:   bool "Brace expansion"
     135//config:   default y
     136//config:   depends on HUSH_BASH_COMPAT
     137//config:   help
     138//config:     Enable {abc,def} extension.
     139//config:
     140//config:config HUSH_HELP
     141//config:   bool "help builtin"
     142//config:   default y
     143//config:   depends on HUSH
     144//config:   help
     145//config:     Enable help builtin in hush. Code size + ~1 kbyte.
     146//config:
     147//config:config HUSH_INTERACTIVE
     148//config:   bool "Interactive mode"
     149//config:   default y
     150//config:   depends on HUSH
     151//config:   help
     152//config:     Enable interactive mode (prompt and command editing).
     153//config:     Without this, hush simply reads and executes commands
     154//config:     from stdin just like a shell script from a file.
     155//config:     No prompt, no PS1/PS2 magic shell variables.
     156//config:
     157//config:config HUSH_SAVEHISTORY
     158//config:   bool "Save command history to .hush_history"
     159//config:   default y
     160//config:   depends on HUSH_INTERACTIVE && FEATURE_EDITING_SAVEHISTORY
     161//config:   help
     162//config:     Enable history saving in hush.
     163//config:
     164//config:config HUSH_JOB
     165//config:   bool "Job control"
     166//config:   default y
     167//config:   depends on HUSH_INTERACTIVE
     168//config:   help
     169//config:     Enable job control: Ctrl-Z backgrounds, Ctrl-C interrupts current
     170//config:     command (not entire shell), fg/bg builtins work. Without this option,
     171//config:     "cmd &" still works by simply spawning a process and immediately
     172//config:     prompting for next command (or executing next command in a script),
     173//config:     but no separate process group is formed.
     174//config:
     175//config:config HUSH_TICK
     176//config:   bool "Process substitution"
     177//config:   default y
     178//config:   depends on HUSH
     179//config:   help
     180//config:     Enable process substitution `command` and $(command) in hush.
     181//config:
     182//config:config HUSH_IF
     183//config:   bool "Support if/then/elif/else/fi"
     184//config:   default y
     185//config:   depends on HUSH
     186//config:   help
     187//config:     Enable if/then/elif/else/fi in hush.
     188//config:
     189//config:config HUSH_LOOPS
     190//config:   bool "Support for, while and until loops"
     191//config:   default y
     192//config:   depends on HUSH
     193//config:   help
     194//config:     Enable for, while and until loops in hush.
     195//config:
     196//config:config HUSH_CASE
     197//config:   bool "Support case ... esac statement"
     198//config:   default y
     199//config:   depends on HUSH
     200//config:   help
     201//config:     Enable case ... esac statement in hush. +400 bytes.
     202//config:
     203//config:config HUSH_FUNCTIONS
     204//config:   bool "Support funcname() { commands; } syntax"
     205//config:   default y
     206//config:   depends on HUSH
     207//config:   help
     208//config:     Enable support for shell functions in hush. +800 bytes.
     209//config:
     210//config:config HUSH_LOCAL
     211//config:   bool "Support local builtin"
     212//config:   default y
     213//config:   depends on HUSH_FUNCTIONS
     214//config:   help
     215//config:     Enable support for local variables in functions.
     216//config:
     217//config:config HUSH_RANDOM_SUPPORT
     218//config:   bool "Pseudorandom generator and $RANDOM variable"
     219//config:   default y
     220//config:   depends on HUSH
     221//config:   help
     222//config:     Enable pseudorandom generator and dynamic variable "$RANDOM".
     223//config:     Each read of "$RANDOM" will generate a new pseudorandom value.
     224//config:
     225//config:config HUSH_EXPORT_N
     226//config:   bool "Support 'export -n' option"
     227//config:   default y
     228//config:   depends on HUSH
     229//config:   help
     230//config:     export -n unexports variables. It is a bash extension.
     231//config:
     232//config:config HUSH_MODE_X
     233//config:   bool "Support 'hush -x' option and 'set -x' command"
     234//config:   default y
     235//config:   depends on HUSH
     236//config:   help
     237//config:     This instructs hush to print commands before execution.
     238//config:     Adds ~300 bytes.
     239//config:
     240//config:config MSH
     241//config:   bool "msh (deprecated: aliased to hush)"
     242//config:   default n
     243//config:   select HUSH
     244//config:   help
     245//config:     msh is deprecated and will be removed, please migrate to hush.
     246//config:
     247
     248//usage:#define hush_trivial_usage NOUSAGE_STR
     249//usage:#define hush_full_usage ""
     250//usage:#define msh_trivial_usage NOUSAGE_STR
     251//usage:#define msh_full_usage ""
     252//usage:#define sh_trivial_usage NOUSAGE_STR
     253//usage:#define sh_full_usage ""
     254//usage:#define bash_trivial_usage NOUSAGE_STR
     255//usage:#define bash_full_usage ""
     256
     257
     258/* Build knobs */
     259#define LEAK_HUNTING 0
     260#define BUILD_AS_NOMMU 0
     261/* Enable/disable sanity checks. Ok to enable in production,
     262 * only adds a bit of bloat. Set to >1 to get non-production level verbosity.
     263 * Keeping 1 for now even in released versions.
     264 */
     265#define HUSH_DEBUG 1
     266/* Slightly bigger (+200 bytes), but faster hush.
     267 * So far it only enables a trick with counting SIGCHLDs and forks,
     268 * which allows us to do fewer waitpid's.
     269 * (we can detect a case where neither forks were done nor SIGCHLDs happened
     270 * and therefore waitpid will return the same result as last time)
     271 */
     272#define ENABLE_HUSH_FAST 0
     273/* TODO: implement simplified code for users which do not need ${var%...} ops
     274 * So far ${var%...} ops are always enabled:
     275 */
     276#define ENABLE_HUSH_DOLLAR_OPS 1
     277
     278
     279#if BUILD_AS_NOMMU
     280# undef BB_MMU
     281# undef USE_FOR_NOMMU
     282# undef USE_FOR_MMU
     283# define BB_MMU 0
     284# define USE_FOR_NOMMU(...) __VA_ARGS__
     285# define USE_FOR_MMU(...)
     286#endif
     287
     288#include "NUM_APPLETS.h"
     289#if NUM_APPLETS == 1
     290/* STANDALONE does not make sense, and won't compile */
     291# undef CONFIG_FEATURE_SH_STANDALONE
     292# undef ENABLE_FEATURE_SH_STANDALONE
     293# undef IF_FEATURE_SH_STANDALONE
     294# undef IF_NOT_FEATURE_SH_STANDALONE
     295# define ENABLE_FEATURE_SH_STANDALONE 0
     296# define IF_FEATURE_SH_STANDALONE(...)
     297# define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
     298#endif
     299
     300#if !ENABLE_HUSH_INTERACTIVE
     301# undef ENABLE_FEATURE_EDITING
     302# define ENABLE_FEATURE_EDITING 0
     303# undef ENABLE_FEATURE_EDITING_FANCY_PROMPT
     304# define ENABLE_FEATURE_EDITING_FANCY_PROMPT 0
     305#endif
     306
     307/* Do we support ANY keywords? */
     308#if ENABLE_HUSH_IF || ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
     309# define HAS_KEYWORDS 1
     310# define IF_HAS_KEYWORDS(...) __VA_ARGS__
     311# define IF_HAS_NO_KEYWORDS(...)
     312#else
     313# define HAS_KEYWORDS 0
     314# define IF_HAS_KEYWORDS(...)
     315# define IF_HAS_NO_KEYWORDS(...) __VA_ARGS__
     316#endif
    88317
    89318/* If you comment out one of these below, it will be #defined later
     
    94323#define debug_print_tree(a, b)   do {} while (0)
    95324#define debug_printf_exec(...)   do {} while (0)
     325#define debug_printf_env(...)    do {} while (0)
    96326#define debug_printf_jobs(...)   do {} while (0)
    97327#define debug_printf_expand(...) do {} while (0)
     328#define debug_printf_varexp(...) do {} while (0)
     329#define debug_printf_glob(...)   do {} while (0)
     330#define debug_printf_list(...)   do {} while (0)
     331#define debug_printf_subst(...)  do {} while (0)
    98332#define debug_printf_clean(...)  do {} while (0)
    99333
    100 #ifndef debug_printf
    101 #define debug_printf(...) fprintf(stderr, __VA_ARGS__)
    102 #endif
    103 
    104 #ifndef debug_printf_parse
    105 #define debug_printf_parse(...) fprintf(stderr, __VA_ARGS__)
    106 #endif
    107 
    108 #ifndef debug_printf_exec
    109 #define debug_printf_exec(...) fprintf(stderr, __VA_ARGS__)
    110 #endif
    111 
    112 #ifndef debug_printf_jobs
    113 #define debug_printf_jobs(...) fprintf(stderr, __VA_ARGS__)
    114 #define DEBUG_SHELL_JOBS 1
    115 #endif
    116 
    117 #ifndef debug_printf_expand
    118 #define debug_printf_expand(...) fprintf(stderr, __VA_ARGS__)
    119 #define DEBUG_EXPAND 1
    120 #endif
    121 
    122 /* Keep unconditionally on for now */
    123 #define ENABLE_HUSH_DEBUG 1
    124 
    125 #ifndef debug_printf_clean
    126 /* broken, of course, but OK for testing */
    127 static const char *indenter(int i)
    128 {
    129     static const char blanks[] ALIGN1 =
    130         "                                    ";
    131     return &blanks[sizeof(blanks) - i - 1];
    132 }
    133 #define debug_printf_clean(...) fprintf(stderr, __VA_ARGS__)
    134 #define DEBUG_CLEAN 1
    135 #endif
    136 
    137 
    138 #if !ENABLE_HUSH_INTERACTIVE
    139 #undef ENABLE_FEATURE_EDITING
    140 #define ENABLE_FEATURE_EDITING 0
    141 #undef ENABLE_FEATURE_EDITING_FANCY_PROMPT
    142 #define ENABLE_FEATURE_EDITING_FANCY_PROMPT 0
     334#define ERR_PTR ((void*)(long)1)
     335
     336#define JOB_STATUS_FORMAT    "[%d] %-22s %.40s\n"
     337
     338#define _SPECIAL_VARS_STR     "_*@$!?#"
     339#define SPECIAL_VARS_STR     ("_*@$!?#" + 1)
     340#define NUMERIC_SPECVARS_STR ("_*@$!?#" + 3)
     341#if ENABLE_HUSH_BASH_COMPAT
     342/* Support / and // replace ops */
     343/* Note that // is stored as \ in "encoded" string representation */
     344# define VAR_ENCODED_SUBST_OPS      "\\/%#:-=+?"
     345# define VAR_SUBST_OPS             ("\\/%#:-=+?" + 1)
     346# define MINUS_PLUS_EQUAL_QUESTION ("\\/%#:-=+?" + 5)
     347#else
     348# define VAR_ENCODED_SUBST_OPS      "%#:-=+?"
     349# define VAR_SUBST_OPS              "%#:-=+?"
     350# define MINUS_PLUS_EQUAL_QUESTION ("%#:-=+?" + 3)
    143351#endif
    144352
    145353#define SPECIAL_VAR_SYMBOL   3
    146354
    147 #define PARSEFLAG_EXIT_FROM_LOOP 1
    148 #define PARSEFLAG_SEMICOLON      (1 << 1)  /* symbol ';' is special for parser */
    149 #define PARSEFLAG_REPARSING      (1 << 2)  /* >= 2nd pass */
    150 
    151 typedef enum {
    152     REDIRECT_INPUT     = 1,
    153     REDIRECT_OVERWRITE = 2,
    154     REDIRECT_APPEND    = 3,
    155     REDIRECT_HEREIS    = 4,
    156     REDIRECT_IO        = 5
    157 } redir_type;
    158 
    159 /* The descrip member of this structure is only used to make debugging
    160  * output pretty */
     355struct variable;
     356
     357static const char hush_version_str[] ALIGN1 = "HUSH_VERSION="BB_VER;
     358
     359/* This supports saving pointers malloced in vfork child,
     360 * to be freed in the parent.
     361 */
     362#if !BB_MMU
     363typedef struct nommu_save_t {
     364    char **new_env;
     365    struct variable *old_vars;
     366    char **argv;
     367    char **argv_from_re_execing;
     368} nommu_save_t;
     369#endif
     370
     371enum {
     372    RES_NONE  = 0,
     373#if ENABLE_HUSH_IF
     374    RES_IF    ,
     375    RES_THEN  ,
     376    RES_ELIF  ,
     377    RES_ELSE  ,
     378    RES_FI    ,
     379#endif
     380#if ENABLE_HUSH_LOOPS
     381    RES_FOR   ,
     382    RES_WHILE ,
     383    RES_UNTIL ,
     384    RES_DO    ,
     385    RES_DONE  ,
     386#endif
     387#if ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
     388    RES_IN    ,
     389#endif
     390#if ENABLE_HUSH_CASE
     391    RES_CASE  ,
     392    /* three pseudo-keywords support contrived "case" syntax: */
     393    RES_CASE_IN,   /* "case ... IN", turns into RES_MATCH when IN is observed */
     394    RES_MATCH ,    /* "word)" */
     395    RES_CASE_BODY, /* "this command is inside CASE" */
     396    RES_ESAC  ,
     397#endif
     398    RES_XXXX  ,
     399    RES_SNTX
     400};
     401
     402typedef struct o_string {
     403    char *data;
     404    int length; /* position where data is appended */
     405    int maxlen;
     406    int o_expflags;
     407    /* At least some part of the string was inside '' or "",
     408     * possibly empty one: word"", wo''rd etc. */
     409    smallint has_quoted_part;
     410    smallint has_empty_slot;
     411    smallint o_assignment; /* 0:maybe, 1:yes, 2:no */
     412} o_string;
     413enum {
     414    EXP_FLAG_SINGLEWORD     = 0x80, /* must be 0x80 */
     415    EXP_FLAG_GLOB           = 0x2,
     416    /* Protect newly added chars against globbing
     417     * by prepending \ to *, ?, [, \ */
     418    EXP_FLAG_ESC_GLOB_CHARS = 0x1,
     419};
     420enum {
     421    MAYBE_ASSIGNMENT      = 0,
     422    DEFINITELY_ASSIGNMENT = 1,
     423    NOT_ASSIGNMENT        = 2,
     424    /* Not an assigment, but next word may be: "if v=xyz cmd;" */
     425    WORD_IS_KEYWORD       = 3,
     426};
     427/* Used for initialization: o_string foo = NULL_O_STRING; */
     428#define NULL_O_STRING { NULL }
     429
     430/* I can almost use ordinary FILE*.  Is open_memstream() universally
     431 * available?  Where is it documented? */
     432typedef struct in_str {
     433    const char *p;
     434    /* eof_flag=1: last char in ->p is really an EOF */
     435    char eof_flag; /* meaningless if ->p == NULL */
     436    char peek_buf[2];
     437#if ENABLE_HUSH_INTERACTIVE
     438    smallint promptme;
     439    smallint promptmode; /* 0: PS1, 1: PS2 */
     440#endif
     441    FILE *file;
     442    int (*get) (struct in_str *) FAST_FUNC;
     443    int (*peek) (struct in_str *) FAST_FUNC;
     444} in_str;
     445#define i_getch(input) ((input)->get(input))
     446#define i_peek(input) ((input)->peek(input))
     447
     448/* The descrip member of this structure is only used to make
     449 * debugging output pretty */
    161450static const struct {
    162451    int mode;
     
    164453    char descrip[3];
    165454} redir_table[] = {
    166     { 0,                         0, "()" },
    167455    { O_RDONLY,                  0, "<"  },
    168456    { O_CREAT|O_TRUNC|O_WRONLY,  1, ">"  },
    169457    { O_CREAT|O_APPEND|O_WRONLY, 1, ">>" },
    170     { O_RDONLY,                 -1, "<<" },
    171     { O_RDWR,                    1, "<>" }
     458    { O_CREAT|O_RDWR,            1, "<>" },
     459    { O_RDONLY,                  0, "<<" },
     460/* Should not be needed. Bogus default_fd helps in debugging */
     461/*  { O_RDONLY,                 77, "<<" }, */
    172462};
    173463
    174 typedef enum {
     464struct redir_struct {
     465    struct redir_struct *next;
     466    char *rd_filename;          /* filename */
     467    int rd_fd;                  /* fd to redirect */
     468    /* fd to redirect to, or -3 if rd_fd is to be closed (n>&-) */
     469    int rd_dup;
     470    smallint rd_type;           /* (enum redir_type) */
     471    /* note: for heredocs, rd_filename contains heredoc delimiter,
     472     * and subsequently heredoc itself; and rd_dup is a bitmask:
     473     * bit 0: do we need to trim leading tabs?
     474     * bit 1: is heredoc quoted (<<'delim' syntax) ?
     475     */
     476};
     477typedef enum redir_type {
     478    REDIRECT_INPUT     = 0,
     479    REDIRECT_OVERWRITE = 1,
     480    REDIRECT_APPEND    = 2,
     481    REDIRECT_IO        = 3,
     482    REDIRECT_HEREDOC   = 4,
     483    REDIRECT_HEREDOC2  = 5, /* REDIRECT_HEREDOC after heredoc is loaded */
     484
     485    REDIRFD_CLOSE      = -3,
     486    REDIRFD_SYNTAX_ERR = -2,
     487    REDIRFD_TO_FILE    = -1,
     488    /* otherwise, rd_fd is redirected to rd_dup */
     489
     490    HEREDOC_SKIPTABS = 1,
     491    HEREDOC_QUOTED   = 2,
     492} redir_type;
     493
     494
     495struct command {
     496    pid_t pid;                  /* 0 if exited */
     497    int assignment_cnt;         /* how many argv[i] are assignments? */
     498    smallint is_stopped;        /* is the command currently running? */
     499    smallint cmd_type;          /* CMD_xxx */
     500#define CMD_NORMAL   0
     501#define CMD_SUBSHELL 1
     502#if ENABLE_HUSH_BASH_COMPAT
     503/* used for "[[ EXPR ]]" */
     504# define CMD_SINGLEWORD_NOGLOB 2
     505#endif
     506#if ENABLE_HUSH_FUNCTIONS
     507# define CMD_FUNCDEF 3
     508#endif
     509
     510    smalluint cmd_exitcode;
     511    /* if non-NULL, this "command" is { list }, ( list ), or a compound statement */
     512    struct pipe *group;
     513#if !BB_MMU
     514    char *group_as_string;
     515#endif
     516#if ENABLE_HUSH_FUNCTIONS
     517    struct function *child_func;
     518/* This field is used to prevent a bug here:
     519 * while...do f1() {a;}; f1; f1() {b;}; f1; done
     520 * When we execute "f1() {a;}" cmd, we create new function and clear
     521 * cmd->group, cmd->group_as_string, cmd->argv[0].
     522 * When we execute "f1() {b;}", we notice that f1 exists,
     523 * and that its "parent cmd" struct is still "alive",
     524 * we put those fields back into cmd->xxx
     525 * (struct function has ->parent_cmd ptr to facilitate that).
     526 * When we loop back, we can execute "f1() {a;}" again and set f1 correctly.
     527 * Without this trick, loop would execute a;b;b;b;...
     528 * instead of correct sequence a;b;a;b;...
     529 * When command is freed, it severs the link
     530 * (sets ->child_func->parent_cmd to NULL).
     531 */
     532#endif
     533    char **argv;                /* command name and arguments */
     534/* argv vector may contain variable references (^Cvar^C, ^C0^C etc)
     535 * and on execution these are substituted with their values.
     536 * Substitution can make _several_ words out of one argv[n]!
     537 * Example: argv[0]=='.^C*^C.' here: echo .$*.
     538 * References of the form ^C`cmd arg^C are `cmd arg` substitutions.
     539 */
     540    struct redir_struct *redirects; /* I/O redirections */
     541};
     542/* Is there anything in this command at all? */
     543#define IS_NULL_CMD(cmd) \
     544    (!(cmd)->group && !(cmd)->argv && !(cmd)->redirects)
     545
     546struct pipe {
     547    struct pipe *next;
     548    int num_cmds;               /* total number of commands in pipe */
     549    int alive_cmds;             /* number of commands running (not exited) */
     550    int stopped_cmds;           /* number of commands alive, but stopped */
     551#if ENABLE_HUSH_JOB
     552    int jobid;                  /* job number */
     553    pid_t pgrp;                 /* process group ID for the job */
     554    char *cmdtext;              /* name of job */
     555#endif
     556    struct command *cmds;       /* array of commands in pipe */
     557    smallint followup;          /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */
     558    IF_HAS_KEYWORDS(smallint pi_inverted;) /* "! cmd | cmd" */
     559    IF_HAS_KEYWORDS(smallint res_word;) /* needed for if, for, while, until... */
     560};
     561typedef enum pipe_style {
    175562    PIPE_SEQ = 1,
    176563    PIPE_AND = 2,
     
    178565    PIPE_BG  = 4,
    179566} pipe_style;
    180 
    181 /* might eventually control execution */
    182 typedef enum {
    183     RES_NONE  = 0,
    184 #if ENABLE_HUSH_IF
    185     RES_IF    = 1,
    186     RES_THEN  = 2,
    187     RES_ELIF  = 3,
    188     RES_ELSE  = 4,
    189     RES_FI    = 5,
    190 #endif
    191 #if ENABLE_HUSH_LOOPS
    192     RES_FOR   = 6,
    193     RES_WHILE = 7,
    194     RES_UNTIL = 8,
    195     RES_DO    = 9,
    196     RES_DONE  = 10,
    197     RES_IN    = 11,
    198 #endif
    199     RES_XXXX  = 12,
    200     RES_SNTX  = 13
    201 } reserved_style;
    202 enum {
    203     FLAG_END   = (1 << RES_NONE ),
    204 #if ENABLE_HUSH_IF
    205     FLAG_IF    = (1 << RES_IF   ),
    206     FLAG_THEN  = (1 << RES_THEN ),
    207     FLAG_ELIF  = (1 << RES_ELIF ),
    208     FLAG_ELSE  = (1 << RES_ELSE ),
    209     FLAG_FI    = (1 << RES_FI   ),
    210 #endif
    211 #if ENABLE_HUSH_LOOPS
    212     FLAG_FOR   = (1 << RES_FOR  ),
    213     FLAG_WHILE = (1 << RES_WHILE),
    214     FLAG_UNTIL = (1 << RES_UNTIL),
    215     FLAG_DO    = (1 << RES_DO   ),
    216     FLAG_DONE  = (1 << RES_DONE ),
    217     FLAG_IN    = (1 << RES_IN   ),
    218 #endif
    219     FLAG_START = (1 << RES_XXXX ),
    220 };
     567/* Is there anything in this pipe at all? */
     568#define IS_NULL_PIPE(pi) \
     569    ((pi)->num_cmds == 0 IF_HAS_KEYWORDS( && (pi)->res_word == RES_NONE))
    221570
    222571/* This holds pointers to the various results of parsing */
    223 struct p_context {
    224     struct child_prog *child;
     572struct parse_context {
     573    /* linked list of pipes */
    225574    struct pipe *list_head;
     575    /* last pipe (being constructed right now) */
    226576    struct pipe *pipe;
     577    /* last command in pipe (being constructed right now) */
     578    struct command *command;
     579    /* last redirect in command->redirects list */
    227580    struct redir_struct *pending_redirect;
    228     smallint res_w;
    229     smallint parse_type;        /* bitmask of PARSEFLAG_xxx, defines type of parser : ";$" common or special symbol */
    230     int old_flag;               /* bitmask of FLAG_xxx, for figuring out valid reserved words */
    231     struct p_context *stack;
    232     /* How about quoting status? */
    233 };
    234 
    235 struct redir_struct {
    236     struct redir_struct *next;  /* pointer to the next redirect in the list */
    237     redir_type type;            /* type of redirection */
    238     int fd;                     /* file descriptor being redirected */
    239     int dup;                    /* -1, or file descriptor being duplicated */
    240     glob_t word;                /* *word.gl_pathv is the filename */
    241 };
    242 
    243 struct child_prog {
    244     pid_t pid;                  /* 0 if exited */
    245     char **argv;                /* program name and arguments */
    246     struct pipe *group;         /* if non-NULL, first in group or subshell */
    247     smallint subshell;          /* flag, non-zero if group must be forked */
    248     smallint is_stopped;        /* is the program currently running? */
    249     struct redir_struct *redirects; /* I/O redirections */
    250     glob_t glob_result;         /* result of parameter globbing */
    251     struct pipe *family;        /* pointer back to the child's parent pipe */
    252     //sp counting seems to be broken... so commented out, grep for '//sp:'
    253     //sp: int sp;               /* number of SPECIAL_VAR_SYMBOL */
    254     //seems to be unused, grep for '//pt:'
    255     //pt: int parse_type;
    256 };
    257 /* argv vector may contain variable references (^Cvar^C, ^C0^C etc)
    258  * and on execution these are substituted with their values.
    259  * Substitution can make _several_ words out of one argv[n]!
    260  * Example: argv[0]=='.^C*^C.' here: echo .$*.
    261  */
    262 
    263 struct pipe {
    264     struct pipe *next;
    265     int num_progs;              /* total number of programs in job */
    266     int running_progs;          /* number of programs running (not exited) */
    267     int stopped_progs;          /* number of programs alive, but stopped */
    268 #if ENABLE_HUSH_JOB
    269     int jobid;                  /* job number */
    270     pid_t pgrp;                 /* process group ID for the job */
    271     char *cmdtext;              /* name of job */
    272 #endif
    273     char *cmdbuf;               /* buffer various argv's point into */
    274     struct child_prog *progs;   /* array of commands in pipe */
    275     int job_context;            /* bitmask defining current context */
    276     smallint followup;          /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */
    277     smallint res_word;          /* needed for if, for, while, until... */
    278 };
    279 
    280 struct close_me {
    281     struct close_me *next;
    282     int fd;
     581#if !BB_MMU
     582    o_string as_string;
     583#endif
     584#if HAS_KEYWORDS
     585    smallint ctx_res_w;
     586    smallint ctx_inverted; /* "! cmd | cmd" */
     587#if ENABLE_HUSH_CASE
     588    smallint ctx_dsemicolon; /* ";;" seen */
     589#endif
     590    /* bitmask of FLAG_xxx, for figuring out valid reserved words */
     591    int old_flag;
     592    /* group we are enclosed in:
     593     * example: "if pipe1; pipe2; then pipe3; fi"
     594     * when we see "if" or "then", we malloc and copy current context,
     595     * and make ->stack point to it. then we parse pipeN.
     596     * when closing "then" / fi" / whatever is found,
     597     * we move list_head into ->stack->command->group,
     598     * copy ->stack into current context, and delete ->stack.
     599     * (parsing of { list } and ( list ) doesn't use this method)
     600     */
     601    struct parse_context *stack;
     602#endif
    283603};
    284604
     
    292612    struct variable *next;
    293613    char *varstr;        /* points to "name=" portion */
     614#if ENABLE_HUSH_LOCAL
     615    unsigned func_nest_level;
     616#endif
    294617    int max_len;         /* if > 0, name is part of initial env; else name is malloced */
    295618    smallint flg_export; /* putenv should be done on this var */
     
    297620};
    298621
    299 typedef struct {
    300     char *data;
    301     int length;
    302     int maxlen;
    303     int quote;
    304     int nonnull;
    305 } o_string;
    306 #define NULL_O_STRING {NULL,0,0,0,0}
    307 /* used for initialization: o_string foo = NULL_O_STRING; */
    308 
    309 /* I can almost use ordinary FILE *.  Is open_memstream() universally
    310  * available?  Where is it documented? */
    311 struct in_str {
    312     const char *p;
    313     /* eof_flag=1: last char in ->p is really an EOF */
    314     char eof_flag; /* meaningless if ->p == NULL */
    315     char peek_buf[2];
    316 #if ENABLE_HUSH_INTERACTIVE
    317     smallint promptme;
    318     smallint promptmode; /* 0: PS1, 1: PS2 */
    319 #endif
    320     FILE *file;
    321     int (*get) (struct in_str *);
    322     int (*peek) (struct in_str *);
     622enum {
     623    BC_BREAK = 1,
     624    BC_CONTINUE = 2,
    323625};
    324 #define b_getch(input) ((input)->get(input))
    325 #define b_peek(input) ((input)->peek(input))
    326 
     626
     627#if ENABLE_HUSH_FUNCTIONS
     628struct function {
     629    struct function *next;
     630    char *name;
     631    struct command *parent_cmd;
     632    struct pipe *body;
     633# if !BB_MMU
     634    char *body_as_string;
     635# endif
     636};
     637#endif
     638
     639
     640/* set -/+o OPT support. (TODO: make it optional)
     641 * bash supports the following opts:
     642 * allexport       off
     643 * braceexpand     on
     644 * emacs           on
     645 * errexit         off
     646 * errtrace        off
     647 * functrace       off
     648 * hashall         on
     649 * histexpand      off
     650 * history         on
     651 * ignoreeof       off
     652 * interactive-comments    on
     653 * keyword         off
     654 * monitor         on
     655 * noclobber       off
     656 * noexec          off
     657 * noglob          off
     658 * nolog           off
     659 * notify          off
     660 * nounset         off
     661 * onecmd          off
     662 * physical        off
     663 * pipefail        off
     664 * posix           off
     665 * privileged      off
     666 * verbose         off
     667 * vi              off
     668 * xtrace          off
     669 */
     670static const char o_opt_strings[] ALIGN1 = "pipefail\0";
    327671enum {
    328     CHAR_ORDINARY           = 0,
    329     CHAR_ORDINARY_IF_QUOTED = 1, /* example: *, # */
    330     CHAR_IFS                = 2, /* treated as ordinary if quoted */
    331     CHAR_SPECIAL            = 3, /* example: $ */
     672    OPT_O_PIPEFAIL,
     673    NUM_OPT_O
    332674};
    333675
    334 #define HUSH_VER_STR "0.02"
    335676
    336677/* "Globals" within this file */
    337 
    338678/* Sorted roughly by size (smaller offsets == smaller code) */
    339679struct globals {
     680    /* interactive_fd != 0 means we are an interactive shell.
     681     * If we are, then saved_tty_pgrp can also be != 0, meaning
     682     * that controlling tty is available. With saved_tty_pgrp == 0,
     683     * job control still works, but terminal signals
     684     * (^C, ^Z, ^Y, ^\) won't work at all, and background
     685     * process groups can only be created with "cmd &".
     686     * With saved_tty_pgrp != 0, hush will use tcsetpgrp()
     687     * to give tty to the foreground process group,
     688     * and will take it back when the group is stopped (^Z)
     689     * or killed (^C).
     690     */
    340691#if ENABLE_HUSH_INTERACTIVE
    341692    /* 'interactive_fd' is a fd# open to ctty, if we have one
     
    344695    const char *PS1;
    345696    const char *PS2;
     697# define G_interactive_fd (G.interactive_fd)
     698#else
     699# define G_interactive_fd 0
    346700#endif
    347701#if ENABLE_FEATURE_EDITING
    348702    line_input_t *line_input_state;
    349703#endif
     704    pid_t root_pid;
     705    pid_t root_ppid;
     706    pid_t last_bg_pid;
     707#if ENABLE_HUSH_RANDOM_SUPPORT
     708    random_t random_gen;
     709#endif
    350710#if ENABLE_HUSH_JOB
    351711    int run_list_level;
    352     pid_t saved_task_pgrp;
     712    int last_jobid;
    353713    pid_t saved_tty_pgrp;
    354     int last_jobid;
    355714    struct pipe *job_list;
    356     struct pipe *toplevel_list;
    357     smallint ctrl_z_flag;
    358 #endif
    359     smallint fake_mode;
    360     /* these three support $?, $#, and $1 */
     715# define G_saved_tty_pgrp (G.saved_tty_pgrp)
     716#else
     717# define G_saved_tty_pgrp 0
     718#endif
     719    char o_opt[NUM_OPT_O];
     720    smallint flag_SIGINT;
     721#if ENABLE_HUSH_LOOPS
     722    smallint flag_break_continue;
     723#endif
     724#if ENABLE_HUSH_FUNCTIONS
     725    /* 0: outside of a function (or sourced file)
     726     * -1: inside of a function, ok to use return builtin
     727     * 1: return is invoked, skip all till end of func
     728     */
     729    smallint flag_return_in_progress;
     730#endif
     731    smallint n_mode;
     732#if ENABLE_HUSH_MODE_X
     733    smallint x_mode;
     734# define G_x_mode (G.x_mode)
     735#else
     736# define G_x_mode 0
     737#endif
     738    smallint exiting; /* used to prevent EXIT trap recursion */
     739    /* These four support $?, $#, and $1 */
     740    smalluint last_exitcode;
     741    /* are global_argv and global_argv[1..n] malloced? (note: not [0]) */
     742    smalluint global_args_malloced;
     743    smalluint inherited_set_is_saved;
     744    /* how many non-NULL argv's we have. NB: $# + 1 */
     745    int global_argc;
    361746    char **global_argv;
    362     int global_argc;
    363     int last_return_code;
     747#if !BB_MMU
     748    char *argv0_for_re_execing;
     749#endif
     750#if ENABLE_HUSH_LOOPS
     751    unsigned depth_break_continue;
     752    unsigned depth_of_loop;
     753#endif
    364754    const char *ifs;
    365     struct close_me *close_me_head;
    366755    const char *cwd;
    367     unsigned last_bg_pid;
    368     struct variable *top_var; /* = &shell_ver (set in main()) */
    369     struct variable shell_ver;
    370 #if ENABLE_FEATURE_SH_STANDALONE
    371     struct nofork_save_area nofork_save;
    372 #endif
     756    struct variable *top_var;
     757    char **expanded_assignments;
     758#if ENABLE_HUSH_FUNCTIONS
     759    struct function *top_func;
     760# if ENABLE_HUSH_LOCAL
     761    struct variable **shadowed_vars_pp;
     762    unsigned func_nest_level;
     763# endif
     764#endif
     765    /* Signal and trap handling */
     766#if ENABLE_HUSH_FAST
     767    unsigned count_SIGCHLD;
     768    unsigned handled_SIGCHLD;
     769    smallint we_have_children;
     770#endif
     771    /* which signals have non-DFL handler (even with no traps set)? */
     772    unsigned non_DFL_mask;
     773    char **traps; /* char *traps[NSIG] */
     774    sigset_t blocked_set;
     775    sigset_t inherited_set;
     776#if HUSH_DEBUG
     777    unsigned long memleak_value;
     778    int debug_indent;
     779#endif
     780    char user_input_buf[ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 2];
     781};
     782#define G (*ptr_to_globals)
     783/* Not #defining name to G.name - this quickly gets unwieldy
     784 * (too many defines). Also, I actually prefer to see when a variable
     785 * is global, thus "G." prefix is a useful hint */
     786#define INIT_G() do { \
     787    SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
     788} while (0)
     789
     790
     791/* Function prototypes for builtins */
     792static int builtin_cd(char **argv) FAST_FUNC;
     793static int builtin_echo(char **argv) FAST_FUNC;
     794static int builtin_eval(char **argv) FAST_FUNC;
     795static int builtin_exec(char **argv) FAST_FUNC;
     796static int builtin_exit(char **argv) FAST_FUNC;
     797static int builtin_export(char **argv) FAST_FUNC;
    373798#if ENABLE_HUSH_JOB
    374     sigjmp_buf toplevel_jb;
    375 #endif
    376     unsigned char charmap[256];
    377     char user_input_buf[ENABLE_FEATURE_EDITING ? BUFSIZ : 2];
    378 };
    379 
    380 #define G (*ptr_to_globals)
    381 
    382 #if !ENABLE_HUSH_INTERACTIVE
    383 enum { interactive_fd = 0 };
    384 #endif
    385 #if !ENABLE_HUSH_JOB
    386 enum { run_list_level = 0 };
    387 #endif
    388 
    389 #if ENABLE_HUSH_INTERACTIVE
    390 #define interactive_fd   (G.interactive_fd  )
    391 #define PS1              (G.PS1             )
    392 #define PS2              (G.PS2             )
    393 #endif
    394 #if ENABLE_FEATURE_EDITING
    395 #define line_input_state (G.line_input_state)
    396 #endif
    397 #if ENABLE_HUSH_JOB
    398 #define run_list_level   (G.run_list_level  )
    399 #define saved_task_pgrp  (G.saved_task_pgrp )
    400 #define saved_tty_pgrp   (G.saved_tty_pgrp  )
    401 #define last_jobid       (G.last_jobid      )
    402 #define job_list         (G.job_list        )
    403 #define toplevel_list    (G.toplevel_list   )
    404 #define toplevel_jb      (G.toplevel_jb     )
    405 #define ctrl_z_flag      (G.ctrl_z_flag     )
    406 #endif /* JOB */
    407 #define global_argv      (G.global_argv     )
    408 #define global_argc      (G.global_argc     )
    409 #define last_return_code (G.last_return_code)
    410 #define ifs              (G.ifs             )
    411 #define fake_mode        (G.fake_mode       )
    412 #define close_me_head    (G.close_me_head   )
    413 #define cwd              (G.cwd             )
    414 #define last_bg_pid      (G.last_bg_pid     )
    415 #define top_var          (G.top_var         )
    416 #define shell_ver        (G.shell_ver       )
    417 #if ENABLE_FEATURE_SH_STANDALONE
    418 #define nofork_save      (G.nofork_save     )
    419 #endif
    420 #if ENABLE_HUSH_JOB
    421 #define toplevel_jb      (G.toplevel_jb     )
    422 #endif
    423 #define charmap          (G.charmap         )
    424 #define user_input_buf   (G.user_input_buf  )
    425 
    426 
    427 #define B_CHUNK  100
    428 #define B_NOSPAC 1
    429 #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
    430 
    431 #if 1
    432 /* Normal */
    433 static void syntax(const char *msg)
    434 {
    435     /* Was using fancy stuff:
    436      * (interactive_fd ? bb_error_msg : bb_error_msg_and_die)(...params...)
    437      * but it SEGVs. ?! Oh well... explicit temp ptr works around that */
    438     void (*fp)(const char *s, ...);
    439 
    440     fp = (interactive_fd ? bb_error_msg : bb_error_msg_and_die);
    441     fp(msg ? "%s: %s" : "syntax error", "syntax error", msg);
    442 }
    443 
    444 #else
    445 /* Debug */
    446 static void syntax_lineno(int line)
    447 {
    448     void (*fp)(const char *s, ...);
    449 
    450     fp = (interactive_fd ? bb_error_msg : bb_error_msg_and_die);
    451     fp("syntax error hush.c:%d", line);
    452 }
    453 #define syntax(str) syntax_lineno(__LINE__)
    454 #endif
    455 
    456 /* Index of subroutines: */
    457 /*   function prototypes for builtins */
    458 static int builtin_cd(char **argv);
    459 static int builtin_eval(char **argv);
    460 static int builtin_exec(char **argv);
    461 static int builtin_exit(char **argv);
    462 static int builtin_export(char **argv);
    463 #if ENABLE_HUSH_JOB
    464 static int builtin_fg_bg(char **argv);
    465 static int builtin_jobs(char **argv);
     799static int builtin_fg_bg(char **argv) FAST_FUNC;
     800static int builtin_jobs(char **argv) FAST_FUNC;
    466801#endif
    467802#if ENABLE_HUSH_HELP
    468 static int builtin_help(char **argv);
    469 #endif
    470 static int builtin_pwd(char **argv);
    471 static int builtin_read(char **argv);
    472 static int builtin_set(char **argv);
    473 static int builtin_shift(char **argv);
    474 static int builtin_source(char **argv);
    475 static int builtin_umask(char **argv);
    476 static int builtin_unset(char **argv);
    477 //static int builtin_not_written(char **argv);
    478 /*   o_string manipulation: */
    479 static int b_check_space(o_string *o, int len);
    480 static int b_addchr(o_string *o, int ch);
    481 static void b_reset(o_string *o);
    482 static int b_addqchr(o_string *o, int ch, int quote);
    483 /*  in_str manipulations: */
    484 static int static_get(struct in_str *i);
    485 static int static_peek(struct in_str *i);
    486 static int file_get(struct in_str *i);
    487 static int file_peek(struct in_str *i);
    488 static void setup_file_in_str(struct in_str *i, FILE *f);
    489 static void setup_string_in_str(struct in_str *i, const char *s);
    490 /*  close_me manipulations: */
    491 static void mark_open(int fd);
    492 static void mark_closed(int fd);
    493 static void close_all(void);
    494 /*  "run" the final data structures: */
    495 #if !defined(DEBUG_CLEAN)
    496 #define free_pipe_list(head, indent) free_pipe_list(head)
    497 #define free_pipe(pi, indent)        free_pipe(pi)
    498 #endif
    499 static int free_pipe_list(struct pipe *head, int indent);
    500 static int free_pipe(struct pipe *pi, int indent);
    501 /*  really run the final data structures: */
    502 static int setup_redirects(struct child_prog *prog, int squirrel[]);
    503 static int run_list_real(struct pipe *pi);
    504 static void pseudo_exec_argv(char **argv) ATTRIBUTE_NORETURN;
    505 static void pseudo_exec(struct child_prog *child) ATTRIBUTE_NORETURN;
    506 static int run_pipe_real(struct pipe *pi);
    507 /*   extended glob support: */
    508 static int globhack(const char *src, int flags, glob_t *pglob);
    509 static int glob_needed(const char *s);
    510 static int xglob(o_string *dest, int flags, glob_t *pglob);
    511 /*   variable assignment: */
    512 static int is_assignment(const char *s);
    513 /*   data structure manipulation: */
    514 static int setup_redirect(struct p_context *ctx, int fd, redir_type style, struct in_str *input);
    515 static void initialize_context(struct p_context *ctx);
    516 static int done_word(o_string *dest, struct p_context *ctx);
    517 static int done_command(struct p_context *ctx);
    518 static int done_pipe(struct p_context *ctx, pipe_style type);
    519 /*   primary string parsing: */
    520 static int redirect_dup_num(struct in_str *input);
    521 static int redirect_opt_num(o_string *o);
    522 #if ENABLE_HUSH_TICK
    523 static int process_command_subs(o_string *dest, struct p_context *ctx, struct in_str *input, const char *subst_end);
    524 #endif
    525 static int parse_group(o_string *dest, struct p_context *ctx, struct in_str *input, int ch);
    526 static const char *lookup_param(const char *src);
    527 static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input);
    528 static int parse_stream(o_string *dest, struct p_context *ctx, struct in_str *input0, const char *end_trigger);
    529 /*   setup: */
    530 static int parse_and_run_stream(struct in_str *inp, int parse_flag);
    531 static int parse_and_run_string(const char *s, int parse_flag);
    532 static int parse_and_run_file(FILE *f);
    533 /*   job management: */
    534 static int checkjobs(struct pipe* fg_pipe);
    535 #if ENABLE_HUSH_JOB
    536 static int checkjobs_and_fg_shell(struct pipe* fg_pipe);
    537 static void insert_bg_job(struct pipe *pi);
    538 static void remove_bg_job(struct pipe *pi);
    539 static void delete_finished_bg_job(struct pipe *pi);
    540 #else
    541 int checkjobs_and_fg_shell(struct pipe* fg_pipe); /* never called */
    542 #endif
    543 /*     local variable support */
    544 static char **expand_strvec_to_strvec(char **argv);
    545 /* used for eval */
    546 static char *expand_strvec_to_string(char **argv);
    547 /* used for expansion of right hand of assignments */
    548 static char *expand_string_to_string(const char *str);
    549 static struct variable *get_local_var(const char *name);
    550 static int set_local_var(char *str, int flg_export);
    551 static void unset_local_var(const char *name);
     803static int builtin_help(char **argv) FAST_FUNC;
     804#endif
     805#if ENABLE_HUSH_LOCAL
     806static int builtin_local(char **argv) FAST_FUNC;
     807#endif
     808#if HUSH_DEBUG
     809static int builtin_memleak(char **argv) FAST_FUNC;
     810#endif
     811#if ENABLE_PRINTF
     812static int builtin_printf(char **argv) FAST_FUNC;
     813#endif
     814static int builtin_pwd(char **argv) FAST_FUNC;
     815static int builtin_read(char **argv) FAST_FUNC;
     816static int builtin_set(char **argv) FAST_FUNC;
     817static int builtin_shift(char **argv) FAST_FUNC;
     818static int builtin_source(char **argv) FAST_FUNC;
     819static int builtin_test(char **argv) FAST_FUNC;
     820static int builtin_trap(char **argv) FAST_FUNC;
     821static int builtin_type(char **argv) FAST_FUNC;
     822static int builtin_true(char **argv) FAST_FUNC;
     823static int builtin_umask(char **argv) FAST_FUNC;
     824static int builtin_unset(char **argv) FAST_FUNC;
     825static int builtin_wait(char **argv) FAST_FUNC;
     826#if ENABLE_HUSH_LOOPS
     827static int builtin_break(char **argv) FAST_FUNC;
     828static int builtin_continue(char **argv) FAST_FUNC;
     829#endif
     830#if ENABLE_HUSH_FUNCTIONS
     831static int builtin_return(char **argv) FAST_FUNC;
     832#endif
    552833
    553834/* Table of built-in functions.  They can be forked or not, depending on
     
    558839 * still be set at the end. */
    559840struct built_in_command {
    560     const char *cmd;                /* name */
    561     int (*function) (char **argv);  /* function ptr */
     841    const char *b_cmd;
     842    int (*b_function)(char **argv) FAST_FUNC;
    562843#if ENABLE_HUSH_HELP
    563     const char *descr;              /* description */
    564 #define BLTIN(cmd, func, help) { cmd, func, help }
     844    const char *b_descr;
     845# define BLTIN(cmd, func, help) { cmd, func, help }
    565846#else
    566 #define BLTIN(cmd, func, help) { cmd, func }
     847# define BLTIN(cmd, func, help) { cmd, func }
    567848#endif
    568849};
    569850
    570 static const struct built_in_command bltins[] = {
     851static const struct built_in_command bltins1[] = {
     852    BLTIN("."        , builtin_source  , "Run commands in a file"),
     853    BLTIN(":"        , builtin_true    , NULL),
    571854#if ENABLE_HUSH_JOB
    572     BLTIN("bg"    , builtin_fg_bg, "Resume a job in the background"),
    573 #endif
    574 //  BLTIN("break" , builtin_not_written, "Exit for, while or until loop"),
    575     BLTIN("cd"    , builtin_cd, "Change working directory"),
    576 //  BLTIN("continue", builtin_not_written, "Continue for, while or until loop"),
    577     BLTIN("eval"  , builtin_eval, "Construct and run shell command"),
    578     BLTIN("exec"  , builtin_exec, "Exec command, replacing this shell with the exec'd process"),
    579     BLTIN("exit"  , builtin_exit, "Exit from shell"),
    580     BLTIN("export", builtin_export, "Set environment variable"),
     855    BLTIN("bg"       , builtin_fg_bg   , "Resume a job in the background"),
     856#endif
     857#if ENABLE_HUSH_LOOPS
     858    BLTIN("break"    , builtin_break   , "Exit from a loop"),
     859#endif
     860    BLTIN("cd"       , builtin_cd      , "Change directory"),
     861#if ENABLE_HUSH_LOOPS
     862    BLTIN("continue" , builtin_continue, "Start new loop iteration"),
     863#endif
     864    BLTIN("eval"     , builtin_eval    , "Construct and run shell command"),
     865    BLTIN("exec"     , builtin_exec    , "Execute command, don't return to shell"),
     866    BLTIN("exit"     , builtin_exit    , "Exit"),
     867    BLTIN("export"   , builtin_export  , "Set environment variables"),
    581868#if ENABLE_HUSH_JOB
    582     BLTIN("fg"    , builtin_fg_bg, "Bring job into the foreground"),
    583     BLTIN("jobs"  , builtin_jobs, "Lists the active jobs"),
    584 #endif
    585 // TODO: remove pwd? we have it as an applet...
    586     BLTIN("pwd"   , builtin_pwd, "Print current directory"),
    587     BLTIN("read"  , builtin_read, "Input environment variable"),
    588 //  BLTIN("return", builtin_not_written, "Return from a function"),
    589     BLTIN("set"   , builtin_set, "Set/unset shell local variables"),
    590     BLTIN("shift" , builtin_shift, "Shift positional parameters"),
    591 //  BLTIN("trap"  , builtin_not_written, "Trap signals"),
    592 //  BLTIN("ulimit", builtin_not_written, "Controls resource limits"),
    593     BLTIN("umask" , builtin_umask, "Sets file creation mask"),
    594     BLTIN("unset" , builtin_unset, "Unset environment variable"),
    595     BLTIN("."     , builtin_source, "Source-in and run commands in a file"),
     869    BLTIN("fg"       , builtin_fg_bg   , "Bring job into the foreground"),
     870#endif
    596871#if ENABLE_HUSH_HELP
    597     BLTIN("help"  , builtin_help, "List shell built-in commands"),
    598 #endif
    599     BLTIN(NULL, NULL, NULL)
     872    BLTIN("help"     , builtin_help    , NULL),
     873#endif
     874#if ENABLE_HUSH_JOB
     875    BLTIN("jobs"     , builtin_jobs    , "List jobs"),
     876#endif
     877#if ENABLE_HUSH_LOCAL
     878    BLTIN("local"    , builtin_local   , "Set local variables"),
     879#endif
     880#if HUSH_DEBUG
     881    BLTIN("memleak"  , builtin_memleak , NULL),
     882#endif
     883    BLTIN("read"     , builtin_read    , "Input into variable"),
     884#if ENABLE_HUSH_FUNCTIONS
     885    BLTIN("return"   , builtin_return  , "Return from a function"),
     886#endif
     887    BLTIN("set"      , builtin_set     , "Set/unset positional parameters"),
     888    BLTIN("shift"    , builtin_shift   , "Shift positional parameters"),
     889#if ENABLE_HUSH_BASH_COMPAT
     890    BLTIN("source"   , builtin_source  , "Run commands in a file"),
     891#endif
     892    BLTIN("trap"     , builtin_trap    , "Trap signals"),
     893    BLTIN("type"     , builtin_type    , "Show command type"),
     894    BLTIN("ulimit"   , shell_builtin_ulimit  , "Control resource limits"),
     895    BLTIN("umask"    , builtin_umask   , "Set file creation mask"),
     896    BLTIN("unset"    , builtin_unset   , "Unset variables"),
     897    BLTIN("wait"     , builtin_wait    , "Wait for process"),
    600898};
    601 
     899/* For now, echo and test are unconditionally enabled.
     900 * Maybe make it configurable? */
     901static const struct built_in_command bltins2[] = {
     902    BLTIN("["        , builtin_test    , NULL),
     903    BLTIN("echo"     , builtin_echo    , NULL),
     904#if ENABLE_PRINTF
     905    BLTIN("printf"   , builtin_printf  , NULL),
     906#endif
     907    BLTIN("pwd"      , builtin_pwd     , NULL),
     908    BLTIN("test"     , builtin_test    , NULL),
     909};
     910
     911
     912/* Debug printouts.
     913 */
     914#if HUSH_DEBUG
     915/* prevent disasters with G.debug_indent < 0 */
     916# define indent() fdprintf(2, "%*s", (G.debug_indent * 2) & 0xff, "")
     917# define debug_enter() (G.debug_indent++)
     918# define debug_leave() (G.debug_indent--)
     919#else
     920# define indent()      ((void)0)
     921# define debug_enter() ((void)0)
     922# define debug_leave() ((void)0)
     923#endif
     924
     925#ifndef debug_printf
     926# define debug_printf(...) (indent(), fdprintf(2, __VA_ARGS__))
     927#endif
     928
     929#ifndef debug_printf_parse
     930# define debug_printf_parse(...) (indent(), fdprintf(2, __VA_ARGS__))
     931#endif
     932
     933#ifndef debug_printf_exec
     934#define debug_printf_exec(...) (indent(), fdprintf(2, __VA_ARGS__))
     935#endif
     936
     937#ifndef debug_printf_env
     938# define debug_printf_env(...) (indent(), fdprintf(2, __VA_ARGS__))
     939#endif
     940
     941#ifndef debug_printf_jobs
     942# define debug_printf_jobs(...) (indent(), fdprintf(2, __VA_ARGS__))
     943# define DEBUG_JOBS 1
     944#else
     945# define DEBUG_JOBS 0
     946#endif
     947
     948#ifndef debug_printf_expand
     949# define debug_printf_expand(...) (indent(), fdprintf(2, __VA_ARGS__))
     950# define DEBUG_EXPAND 1
     951#else
     952# define DEBUG_EXPAND 0
     953#endif
     954
     955#ifndef debug_printf_varexp
     956# define debug_printf_varexp(...) (indent(), fdprintf(2, __VA_ARGS__))
     957#endif
     958
     959#ifndef debug_printf_glob
     960# define debug_printf_glob(...) (indent(), fdprintf(2, __VA_ARGS__))
     961# define DEBUG_GLOB 1
     962#else
     963# define DEBUG_GLOB 0
     964#endif
     965
     966#ifndef debug_printf_list
     967# define debug_printf_list(...) (indent(), fdprintf(2, __VA_ARGS__))
     968#endif
     969
     970#ifndef debug_printf_subst
     971# define debug_printf_subst(...) (indent(), fdprintf(2, __VA_ARGS__))
     972#endif
     973
     974#ifndef debug_printf_clean
     975# define debug_printf_clean(...) (indent(), fdprintf(2, __VA_ARGS__))
     976# define DEBUG_CLEAN 1
     977#else
     978# define DEBUG_CLEAN 0
     979#endif
     980
     981#if DEBUG_EXPAND
     982static void debug_print_strings(const char *prefix, char **vv)
     983{
     984    indent();
     985    fdprintf(2, "%s:\n", prefix);
     986    while (*vv)
     987        fdprintf(2, " '%s'\n", *vv++);
     988}
     989#else
     990# define debug_print_strings(prefix, vv) ((void)0)
     991#endif
     992
     993
     994/* Leak hunting. Use hush_leaktool.sh for post-processing.
     995 */
     996#if LEAK_HUNTING
     997static void *xxmalloc(int lineno, size_t size)
     998{
     999    void *ptr = xmalloc((size + 0xff) & ~0xff);
     1000    fdprintf(2, "line %d: malloc %p\n", lineno, ptr);
     1001    return ptr;
     1002}
     1003static void *xxrealloc(int lineno, void *ptr, size_t size)
     1004{
     1005    ptr = xrealloc(ptr, (size + 0xff) & ~0xff);
     1006    fdprintf(2, "line %d: realloc %p\n", lineno, ptr);
     1007    return ptr;
     1008}
     1009static char *xxstrdup(int lineno, const char *str)
     1010{
     1011    char *ptr = xstrdup(str);
     1012    fdprintf(2, "line %d: strdup %p\n", lineno, ptr);
     1013    return ptr;
     1014}
     1015static void xxfree(void *ptr)
     1016{
     1017    fdprintf(2, "free %p\n", ptr);
     1018    free(ptr);
     1019}
     1020# define xmalloc(s)     xxmalloc(__LINE__, s)
     1021# define xrealloc(p, s) xxrealloc(__LINE__, p, s)
     1022# define xstrdup(s)     xxstrdup(__LINE__, s)
     1023# define free(p)        xxfree(p)
     1024#endif
     1025
     1026
     1027/* Syntax and runtime errors. They always abort scripts.
     1028 * In interactive use they usually discard unparsed and/or unexecuted commands
     1029 * and return to the prompt.
     1030 * HUSH_DEBUG >= 2 prints line number in this file where it was detected.
     1031 */
     1032#if HUSH_DEBUG < 2
     1033# define die_if_script(lineno, ...)             die_if_script(__VA_ARGS__)
     1034# define syntax_error(lineno, msg)              syntax_error(msg)
     1035# define syntax_error_at(lineno, msg)           syntax_error_at(msg)
     1036# define syntax_error_unterm_ch(lineno, ch)     syntax_error_unterm_ch(ch)
     1037# define syntax_error_unterm_str(lineno, s)     syntax_error_unterm_str(s)
     1038# define syntax_error_unexpected_ch(lineno, ch) syntax_error_unexpected_ch(ch)
     1039#endif
     1040
     1041static void die_if_script(unsigned lineno, const char *fmt, ...)
     1042{
     1043    va_list p;
     1044
     1045#if HUSH_DEBUG >= 2
     1046    bb_error_msg("hush.c:%u", lineno);
     1047#endif
     1048    va_start(p, fmt);
     1049    bb_verror_msg(fmt, p, NULL);
     1050    va_end(p);
     1051    if (!G_interactive_fd)
     1052        xfunc_die();
     1053}
     1054
     1055static void syntax_error(unsigned lineno, const char *msg)
     1056{
     1057    if (msg)
     1058        die_if_script(lineno, "syntax error: %s", msg);
     1059    else
     1060        die_if_script(lineno, "syntax error", NULL);
     1061}
     1062
     1063static void syntax_error_at(unsigned lineno, const char *msg)
     1064{
     1065    die_if_script(lineno, "syntax error at '%s'", msg);
     1066}
     1067
     1068static void syntax_error_unterm_str(unsigned lineno, const char *s)
     1069{
     1070    die_if_script(lineno, "syntax error: unterminated %s", s);
     1071}
     1072
     1073/* It so happens that all such cases are totally fatal
     1074 * even if shell is interactive: EOF while looking for closing
     1075 * delimiter. There is nowhere to read stuff from after that,
     1076 * it's EOF! The only choice is to terminate.
     1077 */
     1078static void syntax_error_unterm_ch(unsigned lineno, char ch) NORETURN;
     1079static void syntax_error_unterm_ch(unsigned lineno, char ch)
     1080{
     1081    char msg[2] = { ch, '\0' };
     1082    syntax_error_unterm_str(lineno, msg);
     1083    xfunc_die();
     1084}
     1085
     1086static void syntax_error_unexpected_ch(unsigned lineno, int ch)
     1087{
     1088    char msg[2];
     1089    msg[0] = ch;
     1090    msg[1] = '\0';
     1091    die_if_script(lineno, "syntax error: unexpected %s", ch == EOF ? "EOF" : msg);
     1092}
     1093
     1094#if HUSH_DEBUG < 2
     1095# undef die_if_script
     1096# undef syntax_error
     1097# undef syntax_error_at
     1098# undef syntax_error_unterm_ch
     1099# undef syntax_error_unterm_str
     1100# undef syntax_error_unexpected_ch
     1101#else
     1102# define die_if_script(...)             die_if_script(__LINE__, __VA_ARGS__)
     1103# define syntax_error(msg)              syntax_error(__LINE__, msg)
     1104# define syntax_error_at(msg)           syntax_error_at(__LINE__, msg)
     1105# define syntax_error_unterm_ch(ch)     syntax_error_unterm_ch(__LINE__, ch)
     1106# define syntax_error_unterm_str(s)     syntax_error_unterm_str(__LINE__, s)
     1107# define syntax_error_unexpected_ch(ch) syntax_error_unexpected_ch(__LINE__, ch)
     1108#endif
     1109
     1110
     1111#if ENABLE_HUSH_INTERACTIVE
     1112static void cmdedit_update_prompt(void);
     1113#else
     1114# define cmdedit_update_prompt() ((void)0)
     1115#endif
     1116
     1117
     1118/* Utility functions
     1119 */
     1120/* Replace each \x with x in place, return ptr past NUL. */
     1121static char *unbackslash(char *src)
     1122{
     1123    char *dst = src = strchrnul(src, '\\');
     1124    while (1) {
     1125        if (*src == '\\')
     1126            src++;
     1127        if ((*dst++ = *src++) == '\0')
     1128            break;
     1129    }
     1130    return dst;
     1131}
     1132
     1133static char **add_strings_to_strings(char **strings, char **add, int need_to_dup)
     1134{
     1135    int i;
     1136    unsigned count1;
     1137    unsigned count2;
     1138    char **v;
     1139
     1140    v = strings;
     1141    count1 = 0;
     1142    if (v) {
     1143        while (*v) {
     1144            count1++;
     1145            v++;
     1146        }
     1147    }
     1148    count2 = 0;
     1149    v = add;
     1150    while (*v) {
     1151        count2++;
     1152        v++;
     1153    }
     1154    v = xrealloc(strings, (count1 + count2 + 1) * sizeof(char*));
     1155    v[count1 + count2] = NULL;
     1156    i = count2;
     1157    while (--i >= 0)
     1158        v[count1 + i] = (need_to_dup ? xstrdup(add[i]) : add[i]);
     1159    return v;
     1160}
     1161#if LEAK_HUNTING
     1162static char **xx_add_strings_to_strings(int lineno, char **strings, char **add, int need_to_dup)
     1163{
     1164    char **ptr = add_strings_to_strings(strings, add, need_to_dup);
     1165    fdprintf(2, "line %d: add_strings_to_strings %p\n", lineno, ptr);
     1166    return ptr;
     1167}
     1168#define add_strings_to_strings(strings, add, need_to_dup) \
     1169    xx_add_strings_to_strings(__LINE__, strings, add, need_to_dup)
     1170#endif
     1171
     1172/* Note: takes ownership of "add" ptr (it is not strdup'ed) */
     1173static char **add_string_to_strings(char **strings, char *add)
     1174{
     1175    char *v[2];
     1176    v[0] = add;
     1177    v[1] = NULL;
     1178    return add_strings_to_strings(strings, v, /*dup:*/ 0);
     1179}
     1180#if LEAK_HUNTING
     1181static char **xx_add_string_to_strings(int lineno, char **strings, char *add)
     1182{
     1183    char **ptr = add_string_to_strings(strings, add);
     1184    fdprintf(2, "line %d: add_string_to_strings %p\n", lineno, ptr);
     1185    return ptr;
     1186}
     1187#define add_string_to_strings(strings, add) \
     1188    xx_add_string_to_strings(__LINE__, strings, add)
     1189#endif
     1190
     1191static void free_strings(char **strings)
     1192{
     1193    char **v;
     1194
     1195    if (!strings)
     1196        return;
     1197    v = strings;
     1198    while (*v) {
     1199        free(*v);
     1200        v++;
     1201    }
     1202    free(strings);
     1203}
     1204
     1205
     1206/* Helpers for setting new $n and restoring them back
     1207 */
     1208typedef struct save_arg_t {
     1209    char *sv_argv0;
     1210    char **sv_g_argv;
     1211    int sv_g_argc;
     1212    smallint sv_g_malloced;
     1213} save_arg_t;
     1214
     1215static void save_and_replace_G_args(save_arg_t *sv, char **argv)
     1216{
     1217    int n;
     1218
     1219    sv->sv_argv0 = argv[0];
     1220    sv->sv_g_argv = G.global_argv;
     1221    sv->sv_g_argc = G.global_argc;
     1222    sv->sv_g_malloced = G.global_args_malloced;
     1223
     1224    argv[0] = G.global_argv[0]; /* retain $0 */
     1225    G.global_argv = argv;
     1226    G.global_args_malloced = 0;
     1227
     1228    n = 1;
     1229    while (*++argv)
     1230        n++;
     1231    G.global_argc = n;
     1232}
     1233
     1234static void restore_G_args(save_arg_t *sv, char **argv)
     1235{
     1236    char **pp;
     1237
     1238    if (G.global_args_malloced) {
     1239        /* someone ran "set -- arg1 arg2 ...", undo */
     1240        pp = G.global_argv;
     1241        while (*++pp) /* note: does not free $0 */
     1242            free(*pp);
     1243        free(G.global_argv);
     1244    }
     1245    argv[0] = sv->sv_argv0;
     1246    G.global_argv = sv->sv_g_argv;
     1247    G.global_argc = sv->sv_g_argc;
     1248    G.global_args_malloced = sv->sv_g_malloced;
     1249}
     1250
     1251
     1252/* Basic theory of signal handling in shell
     1253 * ========================================
     1254 * This does not describe what hush does, rather, it is current understanding
     1255 * what it _should_ do. If it doesn't, it's a bug.
     1256 * http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#trap
     1257 *
     1258 * Signals are handled only after each pipe ("cmd | cmd | cmd" thing)
     1259 * is finished or backgrounded. It is the same in interactive and
     1260 * non-interactive shells, and is the same regardless of whether
     1261 * a user trap handler is installed or a shell special one is in effect.
     1262 * ^C or ^Z from keyboard seems to execute "at once" because it usually
     1263 * backgrounds (i.e. stops) or kills all members of currently running
     1264 * pipe.
     1265 *
     1266 * Wait builtin in interruptible by signals for which user trap is set
     1267 * or by SIGINT in interactive shell.
     1268 *
     1269 * Trap handlers will execute even within trap handlers. (right?)
     1270 *
     1271 * User trap handlers are forgotten when subshell ("(cmd)") is entered,
     1272 * except for handlers set to '' (empty string).
     1273 *
     1274 * If job control is off, backgrounded commands ("cmd &")
     1275 * have SIGINT, SIGQUIT set to SIG_IGN.
     1276 *
     1277 * Commands which are run in command substitution ("`cmd`")
     1278 * have SIGTTIN, SIGTTOU, SIGTSTP set to SIG_IGN.
     1279 *
     1280 * Ordinary commands have signals set to SIG_IGN/DFL as inherited
     1281 * by the shell from its parent.
     1282 *
     1283 * Signals which differ from SIG_DFL action
     1284 * (note: child (i.e., [v]forked) shell is not an interactive shell):
     1285 *
     1286 * SIGQUIT: ignore
     1287 * SIGTERM (interactive): ignore
     1288 * SIGHUP (interactive):
     1289 *    send SIGCONT to stopped jobs, send SIGHUP to all jobs and exit
     1290 * SIGTTIN, SIGTTOU, SIGTSTP (if job control is on): ignore
     1291 *    Note that ^Z is handled not by trapping SIGTSTP, but by seeing
     1292 *    that all pipe members are stopped. Try this in bash:
     1293 *    while :; do :; done - ^Z does not background it
     1294 *    (while :; do :; done) - ^Z backgrounds it
     1295 * SIGINT (interactive): wait for last pipe, ignore the rest
     1296 *    of the command line, show prompt. NB: ^C does not send SIGINT
     1297 *    to interactive shell while shell is waiting for a pipe,
     1298 *    since shell is bg'ed (is not in foreground process group).
     1299 *    Example 1: this waits 5 sec, but does not execute ls:
     1300 *    "echo $$; sleep 5; ls -l" + "kill -INT <pid>"
     1301 *    Example 2: this does not wait and does not execute ls:
     1302 *    "echo $$; sleep 5 & wait; ls -l" + "kill -INT <pid>"
     1303 *    Example 3: this does not wait 5 sec, but executes ls:
     1304 *    "sleep 5; ls -l" + press ^C
     1305 *
     1306 * (What happens to signals which are IGN on shell start?)
     1307 * (What happens with signal mask on shell start?)
     1308 *
     1309 * Implementation in hush
     1310 * ======================
     1311 * We use in-kernel pending signal mask to determine which signals were sent.
     1312 * We block all signals which we don't want to take action immediately,
     1313 * i.e. we block all signals which need to have special handling as described
     1314 * above, and all signals which have traps set.
     1315 * After each pipe execution, we extract any pending signals via sigtimedwait()
     1316 * and act on them.
     1317 *
     1318 * unsigned non_DFL_mask: a mask of such "special" signals
     1319 * sigset_t blocked_set:  current blocked signal set
     1320 *
     1321 * "trap - SIGxxx":
     1322 *    clear bit in blocked_set unless it is also in non_DFL_mask
     1323 * "trap 'cmd' SIGxxx":
     1324 *    set bit in blocked_set (even if 'cmd' is '')
     1325 * after [v]fork, if we plan to be a shell:
     1326 *    unblock signals with special interactive handling
     1327 *    (child shell is not interactive),
     1328 *    unset all traps except '' (note: regardless of child shell's type - {}, (), etc)
     1329 * after [v]fork, if we plan to exec:
     1330 *    POSIX says fork clears pending signal mask in child - no need to clear it.
     1331 *    Restore blocked signal set to one inherited by shell just prior to exec.
     1332 *
     1333 * Note: as a result, we do not use signal handlers much. The only uses
     1334 * are to count SIGCHLDs
     1335 * and to restore tty pgrp on signal-induced exit.
     1336 *
     1337 * Note 2 (compat):
     1338 * Standard says "When a subshell is entered, traps that are not being ignored
     1339 * are set to the default actions". bash interprets it so that traps which
     1340 * are set to '' (ignore) are NOT reset to defaults. We do the same.
     1341 */
     1342enum {
     1343    SPECIAL_INTERACTIVE_SIGS = 0
     1344        | (1 << SIGTERM)
     1345        | (1 << SIGINT)
     1346        | (1 << SIGHUP)
     1347        ,
     1348    SPECIAL_JOB_SIGS = 0
    6021349#if ENABLE_HUSH_JOB
    603 
    604 /* move to libbb? */
    605 static void signal_SA_RESTART(int sig, void (*handler)(int))
    606 {
    607     struct sigaction sa;
    608     sa.sa_handler = handler;
    609     sa.sa_flags = SA_RESTART;
    610     sigemptyset(&sa.sa_mask);
    611     sigaction(sig, &sa, NULL);
    612 }
    613 
    614 /* Signals are grouped, we handle them in batches */
    615 static void set_fatal_sighandler(void (*handler)(int))
    616 {
    617     signal(SIGILL , handler);
    618     signal(SIGTRAP, handler);
    619     signal(SIGABRT, handler);
    620     signal(SIGFPE , handler);
    621     signal(SIGBUS , handler);
    622     signal(SIGSEGV, handler);
    623     /* bash 3.2 seems to handle these just like 'fatal' ones */
    624     signal(SIGHUP , handler);
    625     signal(SIGPIPE, handler);
    626     signal(SIGALRM, handler);
    627 }
    628 static void set_jobctrl_sighandler(void (*handler)(int))
    629 {
    630     signal(SIGTSTP, handler);
    631     signal(SIGTTIN, handler);
    632     signal(SIGTTOU, handler);
    633 }
    634 static void set_misc_sighandler(void (*handler)(int))
    635 {
    636     signal(SIGINT , handler);
    637     signal(SIGQUIT, handler);
    638     signal(SIGTERM, handler);
    639 }
    640 /* SIGCHLD is special and handled separately */
    641 
    642 static void set_every_sighandler(void (*handler)(int))
    643 {
    644     set_fatal_sighandler(handler);
    645     set_jobctrl_sighandler(handler);
    646     set_misc_sighandler(handler);
    647     signal(SIGCHLD, handler);
    648 }
    649 
    650 static void handler_ctrl_c(int sig)
    651 {
    652     debug_printf_jobs("got sig %d\n", sig);
    653 // as usual we can have all kinds of nasty problems with leaked malloc data here
    654     siglongjmp(toplevel_jb, 1);
    655 }
    656 
    657 static void handler_ctrl_z(int sig)
    658 {
    659     pid_t pid;
    660 
    661     debug_printf_jobs("got tty sig %d in pid %d\n", sig, getpid());
    662     pid = fork();
    663     if (pid < 0) /* can't fork. Pretend there was no ctrl-Z */
    664         return;
    665     ctrl_z_flag = 1;
    666     if (!pid) { /* child */
    667         setpgrp();
    668         debug_printf_jobs("set pgrp for child %d ok\n", getpid());
    669         set_every_sighandler(SIG_DFL);
    670         raise(SIGTSTP); /* resend TSTP so that child will be stopped */
    671         debug_printf_jobs("returning in child\n");
    672         /* return to nofork, it will eventually exit now,
    673          * not return back to shell */
    674         return;
    675     }
    676     /* parent */
    677     /* finish filling up pipe info */
    678     toplevel_list->pgrp = pid; /* child is in its own pgrp */
    679     toplevel_list->progs[0].pid = pid;
    680     /* parent needs to longjmp out of running nofork.
    681      * we will "return" exitcode 0, with child put in background */
    682 // as usual we can have all kinds of nasty problems with leaked malloc data here
    683     debug_printf_jobs("siglongjmp in parent\n");
    684     siglongjmp(toplevel_jb, 1);
    685 }
     1350        | (1 << SIGTTIN)
     1351        | (1 << SIGTTOU)
     1352        | (1 << SIGTSTP)
     1353#endif
     1354};
     1355
     1356#if ENABLE_HUSH_FAST
     1357static void SIGCHLD_handler(int sig UNUSED_PARAM)
     1358{
     1359    G.count_SIGCHLD++;
     1360//bb_error_msg("[%d] SIGCHLD_handler: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
     1361}
     1362#endif
     1363
     1364#if ENABLE_HUSH_JOB
     1365
     1366/* After [v]fork, in child: do not restore tty pgrp on xfunc death */
     1367# define disable_restore_tty_pgrp_on_exit() (die_sleep = 0)
     1368/* After [v]fork, in parent: restore tty pgrp on xfunc death */
     1369# define enable_restore_tty_pgrp_on_exit()  (die_sleep = -1)
    6861370
    6871371/* Restores tty foreground process group, and exits.
    6881372 * May be called as signal handler for fatal signal
    689  * (will faithfully resend signal to itself, producing correct exit state)
     1373 * (will resend signal to itself, producing correct exit state)
    6901374 * or called directly with -EXITCODE.
    6911375 * We also call it if xfunc is exiting. */
    692 static void sigexit(int sig) ATTRIBUTE_NORETURN;
     1376static void sigexit(int sig) NORETURN;
    6931377static void sigexit(int sig)
    6941378{
    695     sigset_t block_all;
    696 
    6971379    /* Disable all signals: job control, SIGPIPE, etc. */
    698     sigfillset(&block_all);
    699     sigprocmask(SIG_SETMASK, &block_all, NULL);
    700 
    701     if (interactive_fd)
    702         tcsetpgrp(interactive_fd, saved_tty_pgrp);
     1380    sigprocmask_allsigs(SIG_BLOCK);
     1381
     1382    /* Careful: we can end up here after [v]fork. Do not restore
     1383     * tty pgrp then, only top-level shell process does that */
     1384    if (G_saved_tty_pgrp && getpid() == G.root_pid)
     1385        tcsetpgrp(G_interactive_fd, G_saved_tty_pgrp);
    7031386
    7041387    /* Not a signal, just exit */
     
    7061389        _exit(- sig);
    7071390
    708     /* Enable only this sig and kill ourself with it */
    709     signal(sig, SIG_DFL);
    710     sigdelset(&block_all, sig);
    711     sigprocmask(SIG_SETMASK, &block_all, NULL);
    712     raise(sig);
    713     _exit(1); /* Should not reach it */
    714 }
     1391    kill_myself_with_sig(sig); /* does not return */
     1392}
     1393#else
     1394
     1395# define disable_restore_tty_pgrp_on_exit() ((void)0)
     1396# define enable_restore_tty_pgrp_on_exit()  ((void)0)
     1397
     1398#endif
    7151399
    7161400/* Restores tty foreground process group, and exits. */
    717 static void hush_exit(int exitcode) ATTRIBUTE_NORETURN;
     1401static void hush_exit(int exitcode) NORETURN;
    7181402static void hush_exit(int exitcode)
    7191403{
    720     fflush(NULL); /* flush all streams */
     1404    if (G.exiting <= 0 && G.traps && G.traps[0] && G.traps[0][0]) {
     1405        /* Prevent recursion:
     1406         * trap "echo Hi; exit" EXIT; exit
     1407         */
     1408        char *argv[3];
     1409        /* argv[0] is unused */
     1410        argv[1] = G.traps[0];
     1411        argv[2] = NULL;
     1412        G.exiting = 1; /* prevent EXIT trap recursion */
     1413        /* Note: G.traps[0] is not cleared!
     1414         * "trap" will still show it, if executed
     1415         * in the handler */
     1416        builtin_eval(argv);
     1417    }
     1418
     1419#if ENABLE_FEATURE_CLEAN_UP
     1420    {
     1421        struct variable *cur_var;
     1422        if (G.cwd != bb_msg_unknown)
     1423            free((char*)G.cwd);
     1424        cur_var = G.top_var;
     1425        while (cur_var) {
     1426            struct variable *tmp = cur_var;
     1427            if (!cur_var->max_len)
     1428                free(cur_var->varstr);
     1429            cur_var = cur_var->next;
     1430            free(tmp);
     1431        }
     1432    }
     1433#endif
     1434
     1435#if ENABLE_HUSH_JOB
     1436    fflush_all();
    7211437    sigexit(- (exitcode & 0xff));
    722 }
    723 
    724 #else /* !JOB */
    725 
    726 #define set_fatal_sighandler(handler)   ((void)0)
    727 #define set_jobctrl_sighandler(handler) ((void)0)
    728 #define set_misc_sighandler(handler)    ((void)0)
    729 #define hush_exit(e)                    exit(e)
    730 
    731 #endif /* JOB */
    732 
    733 
    734 static const char *set_cwd(void)
    735 {
    736     if (cwd == bb_msg_unknown)
    737         cwd = NULL;     /* xrealloc_getcwd_or_warn(arg) calls free(arg)! */
    738     cwd = xrealloc_getcwd_or_warn((char *)cwd);
    739     if (!cwd)
    740         cwd = bb_msg_unknown;
    741     return cwd;
    742 }
    743 
    744 /* built-in 'eval' handler */
    745 static int builtin_eval(char **argv)
    746 {
    747     int rcode = EXIT_SUCCESS;
    748 
    749     if (argv[1]) {
    750         char *str = expand_strvec_to_string(argv + 1);
    751         parse_and_run_string(str, PARSEFLAG_EXIT_FROM_LOOP |
    752                     PARSEFLAG_SEMICOLON);
     1438#else
     1439    exit(exitcode);
     1440#endif
     1441}
     1442
     1443
     1444static int check_and_run_traps(int sig)
     1445{
     1446    /* I want it in rodata, not in bss.
     1447     * gcc 4.2.1 puts it in rodata only if it has { 0, 0 }
     1448     * initializer. But other compilers may still use bss.
     1449     * TODO: find more portable solution.
     1450     */
     1451    static const struct timespec zero_timespec = { 0, 0 };
     1452    smalluint save_rcode;
     1453    int last_sig = 0;
     1454
     1455    if (sig)
     1456        goto jump_in;
     1457    while (1) {
     1458        sig = sigtimedwait(&G.blocked_set, NULL, &zero_timespec);
     1459        if (sig <= 0)
     1460            break;
     1461 jump_in:
     1462        last_sig = sig;
     1463        if (G.traps && G.traps[sig]) {
     1464            if (G.traps[sig][0]) {
     1465                /* We have user-defined handler */
     1466                char *argv[3];
     1467                /* argv[0] is unused */
     1468                argv[1] = G.traps[sig];
     1469                argv[2] = NULL;
     1470                save_rcode = G.last_exitcode;
     1471                builtin_eval(argv);
     1472                G.last_exitcode = save_rcode;
     1473            } /* else: "" trap, ignoring signal */
     1474            continue;
     1475        }
     1476        /* not a trap: special action */
     1477        switch (sig) {
     1478#if ENABLE_HUSH_FAST
     1479        case SIGCHLD:
     1480            G.count_SIGCHLD++;
     1481//bb_error_msg("[%d] check_and_run_traps: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
     1482            break;
     1483#endif
     1484        case SIGINT:
     1485            /* Builtin was ^C'ed, make it look prettier: */
     1486            bb_putchar('\n');
     1487            G.flag_SIGINT = 1;
     1488            break;
     1489#if ENABLE_HUSH_JOB
     1490        case SIGHUP: {
     1491            struct pipe *job;
     1492            /* bash is observed to signal whole process groups,
     1493             * not individual processes */
     1494            for (job = G.job_list; job; job = job->next) {
     1495                if (job->pgrp <= 0)
     1496                    continue;
     1497                debug_printf_exec("HUPing pgrp %d\n", job->pgrp);
     1498                if (kill(- job->pgrp, SIGHUP) == 0)
     1499                    kill(- job->pgrp, SIGCONT);
     1500            }
     1501            sigexit(SIGHUP);
     1502        }
     1503#endif
     1504        default: /* ignored: */
     1505            /* SIGTERM, SIGQUIT, SIGTTIN, SIGTTOU, SIGTSTP */
     1506            break;
     1507        }
     1508    }
     1509    return last_sig;
     1510}
     1511
     1512
     1513static const char *get_cwd(int force)
     1514{
     1515    if (force || G.cwd == NULL) {
     1516        /* xrealloc_getcwd_or_warn(arg) calls free(arg),
     1517         * we must not try to free(bb_msg_unknown) */
     1518        if (G.cwd == bb_msg_unknown)
     1519            G.cwd = NULL;
     1520        G.cwd = xrealloc_getcwd_or_warn((char *)G.cwd);
     1521        if (!G.cwd)
     1522            G.cwd = bb_msg_unknown;
     1523    }
     1524    return G.cwd;
     1525}
     1526
     1527
     1528/*
     1529 * Shell and environment variable support
     1530 */
     1531static struct variable **get_ptr_to_local_var(const char *name, unsigned len)
     1532{
     1533    struct variable **pp;
     1534    struct variable *cur;
     1535
     1536    pp = &G.top_var;
     1537    while ((cur = *pp) != NULL) {
     1538        if (strncmp(cur->varstr, name, len) == 0 && cur->varstr[len] == '=')
     1539            return pp;
     1540        pp = &cur->next;
     1541    }
     1542    return NULL;
     1543}
     1544
     1545static const char* FAST_FUNC get_local_var_value(const char *name)
     1546{
     1547    struct variable **vpp;
     1548    unsigned len = strlen(name);
     1549
     1550    if (G.expanded_assignments) {
     1551        char **cpp = G.expanded_assignments;
     1552        while (*cpp) {
     1553            char *cp = *cpp;
     1554            if (strncmp(cp, name, len) == 0 && cp[len] == '=')
     1555                return cp + len + 1;
     1556            cpp++;
     1557        }
     1558    }
     1559
     1560    vpp = get_ptr_to_local_var(name, len);
     1561    if (vpp)
     1562        return (*vpp)->varstr + len + 1;
     1563
     1564    if (strcmp(name, "PPID") == 0)
     1565        return utoa(G.root_ppid);
     1566    // bash compat: UID? EUID?
     1567#if ENABLE_HUSH_RANDOM_SUPPORT
     1568    if (strcmp(name, "RANDOM") == 0)
     1569        return utoa(next_random(&G.random_gen));
     1570#endif
     1571    return NULL;
     1572}
     1573
     1574/* str holds "NAME=VAL" and is expected to be malloced.
     1575 * We take ownership of it.
     1576 * flg_export:
     1577 *  0: do not change export flag
     1578 *     (if creating new variable, flag will be 0)
     1579 *  1: set export flag and putenv the variable
     1580 * -1: clear export flag and unsetenv the variable
     1581 * flg_read_only is set only when we handle -R var=val
     1582 */
     1583#if !BB_MMU && ENABLE_HUSH_LOCAL
     1584/* all params are used */
     1585#elif BB_MMU && ENABLE_HUSH_LOCAL
     1586#define set_local_var(str, flg_export, local_lvl, flg_read_only) \
     1587    set_local_var(str, flg_export, local_lvl)
     1588#elif BB_MMU && !ENABLE_HUSH_LOCAL
     1589#define set_local_var(str, flg_export, local_lvl, flg_read_only) \
     1590    set_local_var(str, flg_export)
     1591#elif !BB_MMU && !ENABLE_HUSH_LOCAL
     1592#define set_local_var(str, flg_export, local_lvl, flg_read_only) \
     1593    set_local_var(str, flg_export, flg_read_only)
     1594#endif
     1595static int set_local_var(char *str, int flg_export, int local_lvl, int flg_read_only)
     1596{
     1597    struct variable **var_pp;
     1598    struct variable *cur;
     1599    char *eq_sign;
     1600    int name_len;
     1601
     1602    eq_sign = strchr(str, '=');
     1603    if (!eq_sign) { /* not expected to ever happen? */
    7531604        free(str);
    754         rcode = last_return_code;
    755     }
    756     return rcode;
    757 }
    758 
    759 /* built-in 'cd <path>' handler */
    760 static int builtin_cd(char **argv)
    761 {
    762     const char *newdir;
    763     if (argv[1] == NULL)
    764         newdir = getenv("HOME") ? : "/";
    765     else
    766         newdir = argv[1];
    767     if (chdir(newdir)) {
    768         printf("cd: %s: %s\n", newdir, strerror(errno));
    769         return EXIT_FAILURE;
    770     }
    771     set_cwd();
     1605        return -1;
     1606    }
     1607
     1608    name_len = eq_sign - str + 1; /* including '=' */
     1609    var_pp = &G.top_var;
     1610    while ((cur = *var_pp) != NULL) {
     1611        if (strncmp(cur->varstr, str, name_len) != 0) {
     1612            var_pp = &cur->next;
     1613            continue;
     1614        }
     1615        /* We found an existing var with this name */
     1616        if (cur->flg_read_only) {
     1617#if !BB_MMU
     1618            if (!flg_read_only)
     1619#endif
     1620                bb_error_msg("%s: readonly variable", str);
     1621            free(str);
     1622            return -1;
     1623        }
     1624        if (flg_export == -1) { // "&& cur->flg_export" ?
     1625            debug_printf_env("%s: unsetenv '%s'\n", __func__, str);
     1626            *eq_sign = '\0';
     1627            unsetenv(str);
     1628            *eq_sign = '=';
     1629        }
     1630#if ENABLE_HUSH_LOCAL
     1631        if (cur->func_nest_level < local_lvl) {
     1632            /* New variable is declared as local,
     1633             * and existing one is global, or local
     1634             * from enclosing function.
     1635             * Remove and save old one: */
     1636            *var_pp = cur->next;
     1637            cur->next = *G.shadowed_vars_pp;
     1638            *G.shadowed_vars_pp = cur;
     1639            /* bash 3.2.33(1) and exported vars:
     1640             * # export z=z
     1641             * # f() { local z=a; env | grep ^z; }
     1642             * # f
     1643             * z=a
     1644             * # env | grep ^z
     1645             * z=z
     1646             */
     1647            if (cur->flg_export)
     1648                flg_export = 1;
     1649            break;
     1650        }
     1651#endif
     1652        if (strcmp(cur->varstr + name_len, eq_sign + 1) == 0) {
     1653 free_and_exp:
     1654            free(str);
     1655            goto exp;
     1656        }
     1657        if (cur->max_len != 0) {
     1658            if (cur->max_len >= strlen(str)) {
     1659                /* This one is from startup env, reuse space */
     1660                strcpy(cur->varstr, str);
     1661                goto free_and_exp;
     1662            }
     1663        } else {
     1664            /* max_len == 0 signifies "malloced" var, which we can
     1665             * (and has to) free */
     1666            free(cur->varstr);
     1667        }
     1668        cur->max_len = 0;
     1669        goto set_str_and_exp;
     1670    }
     1671
     1672    /* Not found - create new variable struct */
     1673    cur = xzalloc(sizeof(*cur));
     1674#if ENABLE_HUSH_LOCAL
     1675    cur->func_nest_level = local_lvl;
     1676#endif
     1677    cur->next = *var_pp;
     1678    *var_pp = cur;
     1679
     1680 set_str_and_exp:
     1681    cur->varstr = str;
     1682#if !BB_MMU
     1683    cur->flg_read_only = flg_read_only;
     1684#endif
     1685 exp:
     1686    if (flg_export == 1)
     1687        cur->flg_export = 1;
     1688    if (name_len == 4 && cur->varstr[0] == 'P' && cur->varstr[1] == 'S')
     1689        cmdedit_update_prompt();
     1690    if (cur->flg_export) {
     1691        if (flg_export == -1) {
     1692            cur->flg_export = 0;
     1693            /* unsetenv was already done */
     1694        } else {
     1695            debug_printf_env("%s: putenv '%s'\n", __func__, cur->varstr);
     1696            return putenv(cur->varstr);
     1697        }
     1698    }
     1699    return 0;
     1700}
     1701
     1702/* Used at startup and after each cd */
     1703static void set_pwd_var(int exp)
     1704{
     1705    set_local_var(xasprintf("PWD=%s", get_cwd(/*force:*/ 1)),
     1706        /*exp:*/ exp, /*lvl:*/ 0, /*ro:*/ 0);
     1707}
     1708
     1709static int unset_local_var_len(const char *name, int name_len)
     1710{
     1711    struct variable *cur;
     1712    struct variable **var_pp;
     1713
     1714    if (!name)
     1715        return EXIT_SUCCESS;
     1716    var_pp = &G.top_var;
     1717    while ((cur = *var_pp) != NULL) {
     1718        if (strncmp(cur->varstr, name, name_len) == 0 && cur->varstr[name_len] == '=') {
     1719            if (cur->flg_read_only) {
     1720                bb_error_msg("%s: readonly variable", name);
     1721                return EXIT_FAILURE;
     1722            }
     1723            *var_pp = cur->next;
     1724            debug_printf_env("%s: unsetenv '%s'\n", __func__, cur->varstr);
     1725            bb_unsetenv(cur->varstr);
     1726            if (name_len == 3 && cur->varstr[0] == 'P' && cur->varstr[1] == 'S')
     1727                cmdedit_update_prompt();
     1728            if (!cur->max_len)
     1729                free(cur->varstr);
     1730            free(cur);
     1731            return EXIT_SUCCESS;
     1732        }
     1733        var_pp = &cur->next;
     1734    }
    7721735    return EXIT_SUCCESS;
    7731736}
    7741737
    775 /* built-in 'exec' handler */
    776 static int builtin_exec(char **argv)
    777 {
    778     if (argv[1] == NULL)
    779         return EXIT_SUCCESS;   /* Really? */
    780     pseudo_exec_argv(argv + 1);
    781     /* never returns */
    782 }
    783 
    784 /* built-in 'exit' handler */
    785 static int builtin_exit(char **argv)
    786 {
    787 // TODO: bash does it ONLY on top-level sh exit (+interacive only?)
    788     //puts("exit"); /* bash does it */
    789 // TODO: warn if we have background jobs: "There are stopped jobs"
    790 // On second consecutive 'exit', exit anyway.
    791 
    792     if (argv[1] == NULL)
    793         hush_exit(last_return_code);
    794     /* mimic bash: exit 123abc == exit 255 + error msg */
    795     xfunc_error_retval = 255;
    796     /* bash: exit -2 == exit 254, no error msg */
    797     hush_exit(xatoi(argv[1]) & 0xff);
    798 }
    799 
    800 /* built-in 'export VAR=value' handler */
    801 static int builtin_export(char **argv)
    802 {
    803     const char *value;
    804     char *name = argv[1];
    805 
    806     if (name == NULL) {
    807         // TODO:
    808         // ash emits: export VAR='VAL'
    809         // bash: declare -x VAR="VAL"
    810         // (both also escape as needed (quotes, $, etc))
    811         char **e = environ;
    812         if (e)
    813             while (*e)
    814                 puts(*e++);
    815         return EXIT_SUCCESS;
    816     }
    817 
    818     value = strchr(name, '=');
    819     if (!value) {
    820         /* They are exporting something without a =VALUE */
    821         struct variable *var;
    822 
    823         var = get_local_var(name);
    824         if (var) {
    825             var->flg_export = 1;
     1738static int unset_local_var(const char *name)
     1739{
     1740    return unset_local_var_len(name, strlen(name));
     1741}
     1742
     1743static void unset_vars(char **strings)
     1744{
     1745    char **v;
     1746
     1747    if (!strings)
     1748        return;
     1749    v = strings;
     1750    while (*v) {
     1751        const char *eq = strchrnul(*v, '=');
     1752        unset_local_var_len(*v, (int)(eq - *v));
     1753        v++;
     1754    }
     1755    free(strings);
     1756}
     1757
     1758static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val)
     1759{
     1760    char *var = xasprintf("%s=%s", name, val);
     1761    set_local_var(var, /*flags:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
     1762}
     1763
     1764
     1765/*
     1766 * Helpers for "var1=val1 var2=val2 cmd" feature
     1767 */
     1768static void add_vars(struct variable *var)
     1769{
     1770    struct variable *next;
     1771
     1772    while (var) {
     1773        next = var->next;
     1774        var->next = G.top_var;
     1775        G.top_var = var;
     1776        if (var->flg_export) {
     1777            debug_printf_env("%s: restoring exported '%s'\n", __func__, var->varstr);
    8261778            putenv(var->varstr);
    827         }
    828         /* bash does not return an error when trying to export
    829          * an undefined variable.  Do likewise. */
    830         return EXIT_SUCCESS;
    831     }
    832 
    833     set_local_var(xstrdup(name), 1);
    834     return EXIT_SUCCESS;
    835 }
    836 
    837 #if ENABLE_HUSH_JOB
    838 /* built-in 'fg' and 'bg' handler */
    839 static int builtin_fg_bg(char **argv)
    840 {
    841     int i, jobnum;
    842     struct pipe *pi;
    843 
    844     if (!interactive_fd)
    845         return EXIT_FAILURE;
    846     /* If they gave us no args, assume they want the last backgrounded task */
    847     if (!argv[1]) {
    848         for (pi = job_list; pi; pi = pi->next) {
    849             if (pi->jobid == last_jobid) {
    850                 goto found;
    851             }
    852         }
    853         bb_error_msg("%s: no current job", argv[0]);
    854         return EXIT_FAILURE;
    855     }
    856     if (sscanf(argv[1], "%%%d", &jobnum) != 1) {
    857         bb_error_msg("%s: bad argument '%s'", argv[0], argv[1]);
    858         return EXIT_FAILURE;
    859     }
    860     for (pi = job_list; pi; pi = pi->next) {
    861         if (pi->jobid == jobnum) {
    862             goto found;
    863         }
    864     }
    865     bb_error_msg("%s: %d: no such job", argv[0], jobnum);
    866     return EXIT_FAILURE;
    867  found:
    868     // TODO: bash prints a string representation
    869     // of job being foregrounded (like "sleep 1 | cat")
    870     if (*argv[0] == 'f') {
    871         /* Put the job into the foreground.  */
    872         tcsetpgrp(interactive_fd, pi->pgrp);
    873     }
    874 
    875     /* Restart the processes in the job */
    876     debug_printf_jobs("reviving %d procs, pgrp %d\n", pi->num_progs, pi->pgrp);
    877     for (i = 0; i < pi->num_progs; i++) {
    878         debug_printf_jobs("reviving pid %d\n", pi->progs[i].pid);
    879         pi->progs[i].is_stopped = 0;
    880     }
    881     pi->stopped_progs = 0;
    882 
    883     i = kill(- pi->pgrp, SIGCONT);
    884     if (i < 0) {
    885         if (errno == ESRCH) {
    886             delete_finished_bg_job(pi);
    887             return EXIT_SUCCESS;
    8881779        } else {
    889             bb_perror_msg("kill (SIGCONT)");
    890         }
    891     }
    892 
    893     if (*argv[0] == 'f') {
    894         remove_bg_job(pi);
    895         return checkjobs_and_fg_shell(pi);
    896     }
    897     return EXIT_SUCCESS;
    898 }
    899 #endif
    900 
    901 /* built-in 'help' handler */
    902 #if ENABLE_HUSH_HELP
    903 static int builtin_help(char **argv ATTRIBUTE_UNUSED)
    904 {
    905     const struct built_in_command *x;
    906 
    907     printf("\nBuilt-in commands:\n");
    908     printf("-------------------\n");
    909     for (x = bltins; x->cmd; x++) {
    910         printf("%s\t%s\n", x->cmd, x->descr);
    911     }
    912     printf("\n\n");
    913     return EXIT_SUCCESS;
    914 }
    915 #endif
    916 
    917 #if ENABLE_HUSH_JOB
    918 /* built-in 'jobs' handler */
    919 static int builtin_jobs(char **argv ATTRIBUTE_UNUSED)
    920 {
    921     struct pipe *job;
    922     const char *status_string;
    923 
    924     for (job = job_list; job; job = job->next) {
    925         if (job->running_progs == job->stopped_progs)
    926             status_string = "Stopped";
    927         else
    928             status_string = "Running";
    929 
    930         printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->cmdtext);
    931     }
    932     return EXIT_SUCCESS;
    933 }
    934 #endif
    935 
    936 /* built-in 'pwd' handler */
    937 static int builtin_pwd(char **argv ATTRIBUTE_UNUSED)
    938 {
    939     puts(set_cwd());
    940     return EXIT_SUCCESS;
    941 }
    942 
    943 /* built-in 'read VAR' handler */
    944 static int builtin_read(char **argv)
    945 {
    946     char *string;
    947     const char *name = argv[1] ? argv[1] : "REPLY";
    948 
    949     string = xmalloc_reads(STDIN_FILENO, xasprintf("%s=", name));
    950     return set_local_var(string, 0);
    951 }
    952 
    953 /* built-in 'set [VAR=value]' handler */
    954 static int builtin_set(char **argv)
    955 {
    956     char *temp = argv[1];
    957     struct variable *e;
    958 
    959     if (temp == NULL)
    960         for (e = top_var; e; e = e->next)
    961             puts(e->varstr);
    962     else
    963         set_local_var(xstrdup(temp), 0);
    964 
    965     return EXIT_SUCCESS;
    966 }
    967 
    968 
    969 /* Built-in 'shift' handler */
    970 static int builtin_shift(char **argv)
    971 {
    972     int n = 1;
    973     if (argv[1]) {
    974         n = atoi(argv[1]);
    975     }
    976     if (n >= 0 && n < global_argc) {
    977         global_argv[n] = global_argv[0];
    978         global_argc -= n;
    979         global_argv += n;
    980         return EXIT_SUCCESS;
    981     }
    982     return EXIT_FAILURE;
    983 }
    984 
    985 /* Built-in '.' handler (read-in and execute commands from file) */
    986 static int builtin_source(char **argv)
    987 {
    988     FILE *input;
    989     int status;
    990 
    991     if (argv[1] == NULL)
    992         return EXIT_FAILURE;
    993 
    994     /* XXX search through $PATH is missing */
    995     input = fopen(argv[1], "r");
    996     if (!input) {
    997         bb_error_msg("cannot open '%s'", argv[1]);
    998         return EXIT_FAILURE;
    999     }
    1000 
    1001     /* Now run the file */
    1002     /* XXX argv and argc are broken; need to save old global_argv
    1003      * (pointer only is OK!) on this stack frame,
    1004      * set global_argv=argv+1, recurse, and restore. */
    1005     mark_open(fileno(input));
    1006     status = parse_and_run_file(input);
    1007     mark_closed(fileno(input));
    1008     fclose(input);
    1009     return status;
    1010 }
    1011 
    1012 static int builtin_umask(char **argv)
    1013 {
    1014     mode_t new_umask;
    1015     const char *arg = argv[1];
    1016     char *end;
    1017     if (arg) {
    1018         new_umask = strtoul(arg, &end, 8);
    1019         if (*end != '\0' || end == arg) {
    1020             return EXIT_FAILURE;
    1021         }
     1780            debug_printf_env("%s: restoring variable '%s'\n", __func__, var->varstr);
     1781        }
     1782        var = next;
     1783    }
     1784}
     1785
     1786static struct variable *set_vars_and_save_old(char **strings)
     1787{
     1788    char **s;
     1789    struct variable *old = NULL;
     1790
     1791    if (!strings)
     1792        return old;
     1793    s = strings;
     1794    while (*s) {
     1795        struct variable *var_p;
     1796        struct variable **var_pp;
     1797        char *eq;
     1798
     1799        eq = strchr(*s, '=');
     1800        if (eq) {
     1801            var_pp = get_ptr_to_local_var(*s, eq - *s);
     1802            if (var_pp) {
     1803                /* Remove variable from global linked list */
     1804                var_p = *var_pp;
     1805                debug_printf_env("%s: removing '%s'\n", __func__, var_p->varstr);
     1806                *var_pp = var_p->next;
     1807                /* Add it to returned list */
     1808                var_p->next = old;
     1809                old = var_p;
     1810            }
     1811            set_local_var(*s, /*exp:*/ 1, /*lvl:*/ 0, /*ro:*/ 0);
     1812        }
     1813        s++;
     1814    }
     1815    return old;
     1816}
     1817
     1818
     1819/*
     1820 * in_str support
     1821 */
     1822static int FAST_FUNC static_get(struct in_str *i)
     1823{
     1824    int ch = *i->p;
     1825    if (ch != '\0') {
     1826        i->p++;
     1827        return ch;
     1828    }
     1829    return EOF;
     1830}
     1831
     1832static int FAST_FUNC static_peek(struct in_str *i)
     1833{
     1834    return *i->p;
     1835}
     1836
     1837#if ENABLE_HUSH_INTERACTIVE
     1838
     1839static void cmdedit_update_prompt(void)
     1840{
     1841    if (ENABLE_FEATURE_EDITING_FANCY_PROMPT) {
     1842        G.PS1 = get_local_var_value("PS1");
     1843        if (G.PS1 == NULL)
     1844            G.PS1 = "\\w \\$ ";
     1845        G.PS2 = get_local_var_value("PS2");
    10221846    } else {
    1023         new_umask = umask(0);
    1024         printf("%.3o\n", (unsigned) new_umask);
    1025     }
    1026     umask(new_umask);
    1027     return EXIT_SUCCESS;
    1028 }
    1029 
    1030 /* built-in 'unset VAR' handler */
    1031 static int builtin_unset(char **argv)
    1032 {
    1033     /* bash always returns true */
    1034     unset_local_var(argv[1]);
    1035     return EXIT_SUCCESS;
    1036 }
    1037 
    1038 //static int builtin_not_written(char **argv)
    1039 //{
    1040 //  printf("builtin_%s not written\n", argv[0]);
    1041 //  return EXIT_FAILURE;
    1042 //}
    1043 
    1044 static int b_check_space(o_string *o, int len)
    1045 {
    1046     /* It would be easy to drop a more restrictive policy
    1047      * in here, such as setting a maximum string length */
    1048     if (o->length + len > o->maxlen) {
    1049         /* assert(data == NULL || o->maxlen != 0); */
    1050         o->maxlen += (2*len > B_CHUNK ? 2*len : B_CHUNK);
    1051         o->data = xrealloc(o->data, 1 + o->maxlen);
    1052     }
    1053     return o->data == NULL;
    1054 }
    1055 
    1056 static int b_addchr(o_string *o, int ch)
    1057 {
    1058     debug_printf("b_addchr: '%c' o->length=%d o=%p\n", ch, o->length, o);
    1059     if (b_check_space(o, 1))
    1060         return B_NOSPAC;
    1061     o->data[o->length] = ch;
    1062     o->length++;
    1063     o->data[o->length] = '\0';
    1064     return 0;
    1065 }
    1066 
    1067 static void b_reset(o_string *o)
    1068 {
    1069     o->length = 0;
    1070     o->nonnull = 0;
    1071     if (o->data != NULL)
    1072         *o->data = '\0';
    1073 }
    1074 
    1075 static void b_free(o_string *o)
    1076 {
    1077     b_reset(o);
    1078     free(o->data);
    1079     o->data = NULL;
    1080     o->maxlen = 0;
    1081 }
    1082 
    1083 /* My analysis of quoting semantics tells me that state information
    1084  * is associated with a destination, not a source.
    1085  */
    1086 static int b_addqchr(o_string *o, int ch, int quote)
    1087 {
    1088     if (quote && strchr("*?[\\", ch)) {
    1089         int rc;
    1090         rc = b_addchr(o, '\\');
    1091         if (rc)
    1092             return rc;
    1093     }
    1094     return b_addchr(o, ch);
    1095 }
    1096 
    1097 static int static_get(struct in_str *i)
    1098 {
    1099     int ch = *i->p++;
    1100     if (ch == '\0') return EOF;
    1101     return ch;
    1102 }
    1103 
    1104 static int static_peek(struct in_str *i)
    1105 {
    1106     return *i->p;
    1107 }
    1108 
    1109 #if ENABLE_HUSH_INTERACTIVE
    1110 #if ENABLE_FEATURE_EDITING
    1111 static void cmdedit_set_initial_prompt(void)
    1112 {
    1113 #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT
    1114     PS1 = NULL;
    1115 #else
    1116     PS1 = getenv("PS1");
    1117     if (PS1 == NULL)
    1118         PS1 = "\\w \\$ ";
    1119 #endif
    1120 }
    1121 #endif /* EDITING */
    1122 
    1123 static const char* setup_prompt_string(int promptmode)
     1847        G.PS1 = NULL;
     1848    }
     1849    if (G.PS2 == NULL)
     1850        G.PS2 = "> ";
     1851}
     1852
     1853static const char *setup_prompt_string(int promptmode)
    11241854{
    11251855    const char *prompt_str;
    11261856    debug_printf("setup_prompt_string %d ", promptmode);
    1127 #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT
    1128     /* Set up the prompt */
    1129     if (promptmode == 0) { /* PS1 */
    1130         free((char*)PS1);
    1131         PS1 = xasprintf("%s %c ", cwd, (geteuid() != 0) ? '$' : '#');
    1132         prompt_str = PS1;
    1133     } else {
    1134         prompt_str = PS2;
    1135     }
    1136 #else
    1137     prompt_str = (promptmode == 0) ? PS1 : PS2;
    1138 #endif
     1857    if (!ENABLE_FEATURE_EDITING_FANCY_PROMPT) {
     1858        /* Set up the prompt */
     1859        if (promptmode == 0) { /* PS1 */
     1860            free((char*)G.PS1);
     1861            /* bash uses $PWD value, even if it is set by user.
     1862             * It uses current dir only if PWD is unset.
     1863             * We always use current dir. */
     1864            G.PS1 = xasprintf("%s %c ", get_cwd(0), (geteuid() != 0) ? '$' : '#');
     1865            prompt_str = G.PS1;
     1866        } else
     1867            prompt_str = G.PS2;
     1868    } else
     1869        prompt_str = (promptmode == 0) ? G.PS1 : G.PS2;
    11391870    debug_printf("result '%s'\n", prompt_str);
    11401871    return prompt_str;
     
    11471878
    11481879    prompt_str = setup_prompt_string(i->promptmode);
    1149 #if ENABLE_FEATURE_EDITING
     1880# if ENABLE_FEATURE_EDITING
    11501881    /* Enable command line editing only while a command line
    1151      * is actually being read; otherwise, we'll end up bequeathing
    1152      * atexit() handlers and other unwanted stuff to our
    1153      * child processes (rob@sysgo.de) */
    1154     r = read_line_input(prompt_str, user_input_buf, BUFSIZ-1, line_input_state);
     1882     * is actually being read */
     1883    do {
     1884        G.flag_SIGINT = 0;
     1885        /* buglet: SIGINT will not make new prompt to appear _at once_,
     1886         * only after <Enter>. (^C will work) */
     1887        r = read_line_input(prompt_str, G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1, G.line_input_state);
     1888        /* catch *SIGINT* etc (^C is handled by read_line_input) */
     1889        check_and_run_traps(0);
     1890    } while (r == 0 || G.flag_SIGINT); /* repeat if ^C or SIGINT */
    11551891    i->eof_flag = (r < 0);
    11561892    if (i->eof_flag) { /* EOF/error detected */
    1157         user_input_buf[0] = EOF; /* yes, it will be truncated, it's ok */
    1158         user_input_buf[1] = '\0';
    1159     }
    1160 #else
    1161     fputs(prompt_str, stdout);
    1162     fflush(stdout);
    1163     user_input_buf[0] = r = fgetc(i->file);
    1164     /*user_input_buf[1] = '\0'; - already is and never changed */
     1893        G.user_input_buf[0] = EOF; /* yes, it will be truncated, it's ok */
     1894        G.user_input_buf[1] = '\0';
     1895    }
     1896# else
     1897    do {
     1898        G.flag_SIGINT = 0;
     1899        fputs(prompt_str, stdout);
     1900        fflush_all();
     1901        G.user_input_buf[0] = r = fgetc(i->file);
     1902        /*G.user_input_buf[1] = '\0'; - already is and never changed */
     1903//do we need check_and_run_traps(0)? (maybe only if stdin)
     1904    } while (G.flag_SIGINT);
    11651905    i->eof_flag = (r == EOF);
    1166 #endif
    1167     i->p = user_input_buf;
    1168 }
     1906# endif
     1907    i->p = G.user_input_buf;
     1908}
     1909
    11691910#endif  /* INTERACTIVE */
    11701911
    11711912/* This is the magic location that prints prompts
    11721913 * and gets data back from the user */
    1173 static int file_get(struct in_str *i)
     1914static int FAST_FUNC file_get(struct in_str *i)
    11741915{
    11751916    int ch;
     
    11831924        if (i->eof_flag && !*i->p)
    11841925            ch = EOF;
     1926        /* note: ch is never NUL */
    11851927    } else {
    11861928        /* need to double check i->file because we might be doing something
    11871929         * more complicated by now, like sourcing or substituting. */
    11881930#if ENABLE_HUSH_INTERACTIVE
    1189         if (interactive_fd && i->promptme && i->file == stdin) {
     1931        if (G_interactive_fd && i->promptme && i->file == stdin) {
    11901932            do {
    11911933                get_user_input(i);
     
    11961938        }
    11971939#endif
    1198         ch = fgetc(i->file);
    1199     }
    1200     debug_printf("file_get: got a '%c' %d\n", ch, ch);
     1940        do ch = fgetc(i->file); while (ch == '\0');
     1941    }
     1942    debug_printf("file_get: got '%c' %d\n", ch, ch);
    12011943#if ENABLE_HUSH_INTERACTIVE
    12021944    if (ch == '\n')
     
    12061948}
    12071949
    1208 /* All the callers guarantee this routine will never be
    1209  * used right after a newline, so prompting is not needed.
     1950/* All callers guarantee this routine will never
     1951 * be used right after a newline, so prompting is not needed.
    12101952 */
    1211 static int file_peek(struct in_str *i)
     1953static int FAST_FUNC file_peek(struct in_str *i)
    12121954{
    12131955    int ch;
     
    12161958            return EOF;
    12171959        return *i->p;
    1218     }
    1219     ch = fgetc(i->file);
     1960        /* note: ch is never NUL */
     1961    }
     1962    do ch = fgetc(i->file); while (ch == '\0');
    12201963    i->eof_flag = (ch == EOF);
    12211964    i->peek_buf[0] = ch;
    12221965    i->peek_buf[1] = '\0';
    12231966    i->p = i->peek_buf;
    1224     debug_printf("file_peek: got a '%c' %d\n", *i->p, *i->p);
     1967    debug_printf("file_peek: got '%c' %d\n", ch, ch);
    12251968    return ch;
    12261969}
     
    12501993}
    12511994
    1252 static void mark_open(int fd)
    1253 {
    1254     struct close_me *new = xmalloc(sizeof(struct close_me));
    1255     new->fd = fd;
    1256     new->next = close_me_head;
    1257     close_me_head = new;
    1258 }
    1259 
    1260 static void mark_closed(int fd)
    1261 {
    1262     struct close_me *tmp;
    1263     if (close_me_head == NULL || close_me_head->fd != fd)
    1264         bb_error_msg_and_die("corrupt close_me");
    1265     tmp = close_me_head;
    1266     close_me_head = close_me_head->next;
    1267     free(tmp);
    1268 }
    1269 
    1270 static void close_all(void)
    1271 {
    1272     struct close_me *c;
    1273     for (c = close_me_head; c; c = c->next) {
    1274         close(c->fd);
    1275     }
    1276     close_me_head = NULL;
     1995
     1996/*
     1997 * o_string support
     1998 */
     1999#define B_CHUNK  (32 * sizeof(char*))
     2000
     2001static void o_reset_to_empty_unquoted(o_string *o)
     2002{
     2003    o->length = 0;
     2004    o->has_quoted_part = 0;
     2005    if (o->data)
     2006        o->data[0] = '\0';
     2007}
     2008
     2009static void o_free(o_string *o)
     2010{
     2011    free(o->data);
     2012    memset(o, 0, sizeof(*o));
     2013}
     2014
     2015static ALWAYS_INLINE void o_free_unsafe(o_string *o)
     2016{
     2017    free(o->data);
     2018}
     2019
     2020static void o_grow_by(o_string *o, int len)
     2021{
     2022    if (o->length + len > o->maxlen) {
     2023        o->maxlen += (2*len > B_CHUNK ? 2*len : B_CHUNK);
     2024        o->data = xrealloc(o->data, 1 + o->maxlen);
     2025    }
     2026}
     2027
     2028static void o_addchr(o_string *o, int ch)
     2029{
     2030    debug_printf("o_addchr: '%c' o->length=%d o=%p\n", ch, o->length, o);
     2031    o_grow_by(o, 1);
     2032    o->data[o->length] = ch;
     2033    o->length++;
     2034    o->data[o->length] = '\0';
     2035}
     2036
     2037static void o_addblock(o_string *o, const char *str, int len)
     2038{
     2039    o_grow_by(o, len);
     2040    memcpy(&o->data[o->length], str, len);
     2041    o->length += len;
     2042    o->data[o->length] = '\0';
     2043}
     2044
     2045static void o_addstr(o_string *o, const char *str)
     2046{
     2047    o_addblock(o, str, strlen(str));
     2048}
     2049
     2050#if !BB_MMU
     2051static void nommu_addchr(o_string *o, int ch)
     2052{
     2053    if (o)
     2054        o_addchr(o, ch);
     2055}
     2056#else
     2057# define nommu_addchr(o, str) ((void)0)
     2058#endif
     2059
     2060static void o_addstr_with_NUL(o_string *o, const char *str)
     2061{
     2062    o_addblock(o, str, strlen(str) + 1);
     2063}
     2064
     2065/*
     2066 * HUSH_BRACE_EXPANSION code needs corresponding quoting on variable expansion side.
     2067 * Currently, "v='{q,w}'; echo $v" erroneously expands braces in $v.
     2068 * Apparently, on unquoted $v bash still does globbing
     2069 * ("v='*.txt'; echo $v" prints all .txt files),
     2070 * but NOT brace expansion! Thus, there should be TWO independent
     2071 * quoting mechanisms on $v expansion side: one protects
     2072 * $v from brace expansion, and other additionally protects "$v" against globbing.
     2073 * We have only second one.
     2074 */
     2075
     2076#if ENABLE_HUSH_BRACE_EXPANSION
     2077# define MAYBE_BRACES "{}"
     2078#else
     2079# define MAYBE_BRACES ""
     2080#endif
     2081
     2082/* My analysis of quoting semantics tells me that state information
     2083 * is associated with a destination, not a source.
     2084 */
     2085static void o_addqchr(o_string *o, int ch)
     2086{
     2087    int sz = 1;
     2088    char *found = strchr("*?[\\" MAYBE_BRACES, ch);
     2089    if (found)
     2090        sz++;
     2091    o_grow_by(o, sz);
     2092    if (found) {
     2093        o->data[o->length] = '\\';
     2094        o->length++;
     2095    }
     2096    o->data[o->length] = ch;
     2097    o->length++;
     2098    o->data[o->length] = '\0';
     2099}
     2100
     2101static void o_addQchr(o_string *o, int ch)
     2102{
     2103    int sz = 1;
     2104    if ((o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)
     2105     && strchr("*?[\\" MAYBE_BRACES, ch)
     2106    ) {
     2107        sz++;
     2108        o->data[o->length] = '\\';
     2109        o->length++;
     2110    }
     2111    o_grow_by(o, sz);
     2112    o->data[o->length] = ch;
     2113    o->length++;
     2114    o->data[o->length] = '\0';
     2115}
     2116
     2117static void o_addqblock(o_string *o, const char *str, int len)
     2118{
     2119    while (len) {
     2120        char ch;
     2121        int sz;
     2122        int ordinary_cnt = strcspn(str, "*?[\\" MAYBE_BRACES);
     2123        if (ordinary_cnt > len) /* paranoia */
     2124            ordinary_cnt = len;
     2125        o_addblock(o, str, ordinary_cnt);
     2126        if (ordinary_cnt == len)
     2127            return;
     2128        str += ordinary_cnt;
     2129        len -= ordinary_cnt + 1; /* we are processing + 1 char below */
     2130
     2131        ch = *str++;
     2132        sz = 1;
     2133        if (ch) { /* it is necessarily one of "*?[\\" MAYBE_BRACES */
     2134            sz++;
     2135            o->data[o->length] = '\\';
     2136            o->length++;
     2137        }
     2138        o_grow_by(o, sz);
     2139        o->data[o->length] = ch;
     2140        o->length++;
     2141        o->data[o->length] = '\0';
     2142    }
     2143}
     2144
     2145static void o_addQblock(o_string *o, const char *str, int len)
     2146{
     2147    if (!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)) {
     2148        o_addblock(o, str, len);
     2149        return;
     2150    }
     2151    o_addqblock(o, str, len);
     2152}
     2153
     2154static void o_addQstr(o_string *o, const char *str)
     2155{
     2156    o_addQblock(o, str, strlen(str));
     2157}
     2158
     2159/* A special kind of o_string for $VAR and `cmd` expansion.
     2160 * It contains char* list[] at the beginning, which is grown in 16 element
     2161 * increments. Actual string data starts at the next multiple of 16 * (char*).
     2162 * list[i] contains an INDEX (int!) into this string data.
     2163 * It means that if list[] needs to grow, data needs to be moved higher up
     2164 * but list[i]'s need not be modified.
     2165 * NB: remembering how many list[i]'s you have there is crucial.
     2166 * o_finalize_list() operation post-processes this structure - calculates
     2167 * and stores actual char* ptrs in list[]. Oh, it NULL terminates it as well.
     2168 */
     2169#if DEBUG_EXPAND || DEBUG_GLOB
     2170static void debug_print_list(const char *prefix, o_string *o, int n)
     2171{
     2172    char **list = (char**)o->data;
     2173    int string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
     2174    int i = 0;
     2175
     2176    indent();
     2177    fdprintf(2, "%s: list:%p n:%d string_start:%d length:%d maxlen:%d glob:%d quoted:%d escape:%d\n",
     2178            prefix, list, n, string_start, o->length, o->maxlen,
     2179            !!(o->o_expflags & EXP_FLAG_GLOB),
     2180            o->has_quoted_part,
     2181            !!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
     2182    while (i < n) {
     2183        indent();
     2184        fdprintf(2, " list[%d]=%d '%s' %p\n", i, (int)(uintptr_t)list[i],
     2185                o->data + (int)(uintptr_t)list[i] + string_start,
     2186                o->data + (int)(uintptr_t)list[i] + string_start);
     2187        i++;
     2188    }
     2189    if (n) {
     2190        const char *p = o->data + (int)(uintptr_t)list[n - 1] + string_start;
     2191        indent();
     2192        fdprintf(2, " total_sz:%ld\n", (long)((p + strlen(p) + 1) - o->data));
     2193    }
     2194}
     2195#else
     2196# define debug_print_list(prefix, o, n) ((void)0)
     2197#endif
     2198
     2199/* n = o_save_ptr_helper(str, n) "starts new string" by storing an index value
     2200 * in list[n] so that it points past last stored byte so far.
     2201 * It returns n+1. */
     2202static int o_save_ptr_helper(o_string *o, int n)
     2203{
     2204    char **list = (char**)o->data;
     2205    int string_start;
     2206    int string_len;
     2207
     2208    if (!o->has_empty_slot) {
     2209        string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
     2210        string_len = o->length - string_start;
     2211        if (!(n & 0xf)) { /* 0, 0x10, 0x20...? */
     2212            debug_printf_list("list[%d]=%d string_start=%d (growing)\n", n, string_len, string_start);
     2213            /* list[n] points to string_start, make space for 16 more pointers */
     2214            o->maxlen += 0x10 * sizeof(list[0]);
     2215            o->data = xrealloc(o->data, o->maxlen + 1);
     2216            list = (char**)o->data;
     2217            memmove(list + n + 0x10, list + n, string_len);
     2218            o->length += 0x10 * sizeof(list[0]);
     2219        } else {
     2220            debug_printf_list("list[%d]=%d string_start=%d\n",
     2221                    n, string_len, string_start);
     2222        }
     2223    } else {
     2224        /* We have empty slot at list[n], reuse without growth */
     2225        string_start = ((n+1 + 0xf) & ~0xf) * sizeof(list[0]); /* NB: n+1! */
     2226        string_len = o->length - string_start;
     2227        debug_printf_list("list[%d]=%d string_start=%d (empty slot)\n",
     2228                n, string_len, string_start);
     2229        o->has_empty_slot = 0;
     2230    }
     2231    list[n] = (char*)(uintptr_t)string_len;
     2232    return n + 1;
     2233}
     2234
     2235/* "What was our last o_save_ptr'ed position (byte offset relative o->data)?" */
     2236static int o_get_last_ptr(o_string *o, int n)
     2237{
     2238    char **list = (char**)o->data;
     2239    int string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
     2240
     2241    return ((int)(uintptr_t)list[n-1]) + string_start;
     2242}
     2243
     2244#if ENABLE_HUSH_BRACE_EXPANSION
     2245/* There in a GNU extension, GLOB_BRACE, but it is not usable:
     2246 * first, it processes even {a} (no commas), second,
     2247 * I didn't manage to make it return strings when they don't match
     2248 * existing files. Need to re-implement it.
     2249 */
     2250
     2251/* Helper */
     2252static int glob_needed(const char *s)
     2253{
     2254    while (*s) {
     2255        if (*s == '\\') {
     2256            if (!s[1])
     2257                return 0;
     2258            s += 2;
     2259            continue;
     2260        }
     2261        if (*s == '*' || *s == '[' || *s == '?' || *s == '{')
     2262            return 1;
     2263        s++;
     2264    }
     2265    return 0;
     2266}
     2267/* Return pointer to next closing brace or to comma */
     2268static const char *next_brace_sub(const char *cp)
     2269{
     2270    unsigned depth = 0;
     2271    cp++;
     2272    while (*cp != '\0') {
     2273        if (*cp == '\\') {
     2274            if (*++cp == '\0')
     2275                break;
     2276            cp++;
     2277            continue;
     2278        }
     2279        if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0))
     2280            break;
     2281        if (*cp++ == '{')
     2282            depth++;
     2283    }
     2284
     2285    return *cp != '\0' ? cp : NULL;
     2286}
     2287/* Recursive brace globber. Note: may garble pattern[]. */
     2288static int glob_brace(char *pattern, o_string *o, int n)
     2289{
     2290    char *new_pattern_buf;
     2291    const char *begin;
     2292    const char *next;
     2293    const char *rest;
     2294    const char *p;
     2295    size_t rest_len;
     2296
     2297    debug_printf_glob("glob_brace('%s')\n", pattern);
     2298
     2299    begin = pattern;
     2300    while (1) {
     2301        if (*begin == '\0')
     2302            goto simple_glob;
     2303        if (*begin == '{') {
     2304            /* Find the first sub-pattern and at the same time
     2305             * find the rest after the closing brace */
     2306            next = next_brace_sub(begin);
     2307            if (next == NULL) {
     2308                /* An illegal expression */
     2309                goto simple_glob;
     2310            }
     2311            if (*next == '}') {
     2312                /* "{abc}" with no commas - illegal
     2313                 * brace expr, disregard and skip it */
     2314                begin = next + 1;
     2315                continue;
     2316            }
     2317            break;
     2318        }
     2319        if (*begin == '\\' && begin[1] != '\0')
     2320            begin++;
     2321        begin++;
     2322    }
     2323    debug_printf_glob("begin:%s\n", begin);
     2324    debug_printf_glob("next:%s\n", next);
     2325
     2326    /* Now find the end of the whole brace expression */
     2327    rest = next;
     2328    while (*rest != '}') {
     2329        rest = next_brace_sub(rest);
     2330        if (rest == NULL) {
     2331            /* An illegal expression */
     2332            goto simple_glob;
     2333        }
     2334        debug_printf_glob("rest:%s\n", rest);
     2335    }
     2336    rest_len = strlen(++rest) + 1;
     2337
     2338    /* We are sure the brace expression is well-formed */
     2339
     2340    /* Allocate working buffer large enough for our work */
     2341    new_pattern_buf = xmalloc(strlen(pattern));
     2342
     2343    /* We have a brace expression.  BEGIN points to the opening {,
     2344     * NEXT points past the terminator of the first element, and REST
     2345     * points past the final }.  We will accumulate result names from
     2346     * recursive runs for each brace alternative in the buffer using
     2347     * GLOB_APPEND.  */
     2348
     2349    p = begin + 1;
     2350    while (1) {
     2351        /* Construct the new glob expression */
     2352        memcpy(
     2353            mempcpy(
     2354                mempcpy(new_pattern_buf,
     2355                    /* We know the prefix for all sub-patterns */
     2356                    pattern, begin - pattern),
     2357                p, next - p),
     2358            rest, rest_len);
     2359
     2360        /* Note: glob_brace() may garble new_pattern_buf[].
     2361         * That's why we re-copy prefix every time (1st memcpy above).
     2362         */
     2363        n = glob_brace(new_pattern_buf, o, n);
     2364        if (*next == '}') {
     2365            /* We saw the last entry */
     2366            break;
     2367        }
     2368        p = next + 1;
     2369        next = next_brace_sub(next);
     2370    }
     2371    free(new_pattern_buf);
     2372    return n;
     2373
     2374 simple_glob:
     2375    {
     2376        int gr;
     2377        glob_t globdata;
     2378
     2379        memset(&globdata, 0, sizeof(globdata));
     2380        gr = glob(pattern, 0, NULL, &globdata);
     2381        debug_printf_glob("glob('%s'):%d\n", pattern, gr);
     2382        if (gr != 0) {
     2383            if (gr == GLOB_NOMATCH) {
     2384                globfree(&globdata);
     2385                /* NB: garbles parameter */
     2386                unbackslash(pattern);
     2387                o_addstr_with_NUL(o, pattern);
     2388                debug_printf_glob("glob pattern '%s' is literal\n", pattern);
     2389                return o_save_ptr_helper(o, n);
     2390            }
     2391            if (gr == GLOB_NOSPACE)
     2392                bb_error_msg_and_die(bb_msg_memory_exhausted);
     2393            /* GLOB_ABORTED? Only happens with GLOB_ERR flag,
     2394             * but we didn't specify it. Paranoia again. */
     2395            bb_error_msg_and_die("glob error %d on '%s'", gr, pattern);
     2396        }
     2397        if (globdata.gl_pathv && globdata.gl_pathv[0]) {
     2398            char **argv = globdata.gl_pathv;
     2399            while (1) {
     2400                o_addstr_with_NUL(o, *argv);
     2401                n = o_save_ptr_helper(o, n);
     2402                argv++;
     2403                if (!*argv)
     2404                    break;
     2405            }
     2406        }
     2407        globfree(&globdata);
     2408    }
     2409    return n;
     2410}
     2411/* Performs globbing on last list[],
     2412 * saving each result as a new list[].
     2413 */
     2414static int perform_glob(o_string *o, int n)
     2415{
     2416    char *pattern, *copy;
     2417
     2418    debug_printf_glob("start perform_glob: n:%d o->data:%p\n", n, o->data);
     2419    if (!o->data)
     2420        return o_save_ptr_helper(o, n);
     2421    pattern = o->data + o_get_last_ptr(o, n);
     2422    debug_printf_glob("glob pattern '%s'\n", pattern);
     2423    if (!glob_needed(pattern)) {
     2424        /* unbackslash last string in o in place, fix length */
     2425        o->length = unbackslash(pattern) - o->data;
     2426        debug_printf_glob("glob pattern '%s' is literal\n", pattern);
     2427        return o_save_ptr_helper(o, n);
     2428    }
     2429
     2430    copy = xstrdup(pattern);
     2431    /* "forget" pattern in o */
     2432    o->length = pattern - o->data;
     2433    n = glob_brace(copy, o, n);
     2434    free(copy);
     2435    if (DEBUG_GLOB)
     2436        debug_print_list("perform_glob returning", o, n);
     2437    return n;
     2438}
     2439
     2440#else /* !HUSH_BRACE_EXPANSION */
     2441
     2442/* Helper */
     2443static int glob_needed(const char *s)
     2444{
     2445    while (*s) {
     2446        if (*s == '\\') {
     2447            if (!s[1])
     2448                return 0;
     2449            s += 2;
     2450            continue;
     2451        }
     2452        if (*s == '*' || *s == '[' || *s == '?')
     2453            return 1;
     2454        s++;
     2455    }
     2456    return 0;
     2457}
     2458/* Performs globbing on last list[],
     2459 * saving each result as a new list[].
     2460 */
     2461static int perform_glob(o_string *o, int n)
     2462{
     2463    glob_t globdata;
     2464    int gr;
     2465    char *pattern;
     2466
     2467    debug_printf_glob("start perform_glob: n:%d o->data:%p\n", n, o->data);
     2468    if (!o->data)
     2469        return o_save_ptr_helper(o, n);
     2470    pattern = o->data + o_get_last_ptr(o, n);
     2471    debug_printf_glob("glob pattern '%s'\n", pattern);
     2472    if (!glob_needed(pattern)) {
     2473 literal:
     2474        /* unbackslash last string in o in place, fix length */
     2475        o->length = unbackslash(pattern) - o->data;
     2476        debug_printf_glob("glob pattern '%s' is literal\n", pattern);
     2477        return o_save_ptr_helper(o, n);
     2478    }
     2479
     2480    memset(&globdata, 0, sizeof(globdata));
     2481    /* Can't use GLOB_NOCHECK: it does not unescape the string.
     2482     * If we glob "*.\*" and don't find anything, we need
     2483     * to fall back to using literal "*.*", but GLOB_NOCHECK
     2484     * will return "*.\*"!
     2485     */
     2486    gr = glob(pattern, 0, NULL, &globdata);
     2487    debug_printf_glob("glob('%s'):%d\n", pattern, gr);
     2488    if (gr != 0) {
     2489        if (gr == GLOB_NOMATCH) {
     2490            globfree(&globdata);
     2491            goto literal;
     2492        }
     2493        if (gr == GLOB_NOSPACE)
     2494            bb_error_msg_and_die(bb_msg_memory_exhausted);
     2495        /* GLOB_ABORTED? Only happens with GLOB_ERR flag,
     2496         * but we didn't specify it. Paranoia again. */
     2497        bb_error_msg_and_die("glob error %d on '%s'", gr, pattern);
     2498    }
     2499    if (globdata.gl_pathv && globdata.gl_pathv[0]) {
     2500        char **argv = globdata.gl_pathv;
     2501        /* "forget" pattern in o */
     2502        o->length = pattern - o->data;
     2503        while (1) {
     2504            o_addstr_with_NUL(o, *argv);
     2505            n = o_save_ptr_helper(o, n);
     2506            argv++;
     2507            if (!*argv)
     2508                break;
     2509        }
     2510    }
     2511    globfree(&globdata);
     2512    if (DEBUG_GLOB)
     2513        debug_print_list("perform_glob returning", o, n);
     2514    return n;
     2515}
     2516
     2517#endif /* !HUSH_BRACE_EXPANSION */
     2518
     2519/* If o->o_expflags & EXP_FLAG_GLOB, glob the string so far remembered.
     2520 * Otherwise, just finish current list[] and start new */
     2521static int o_save_ptr(o_string *o, int n)
     2522{
     2523    if (o->o_expflags & EXP_FLAG_GLOB) {
     2524        /* If o->has_empty_slot, list[n] was already globbed
     2525         * (if it was requested back then when it was filled)
     2526         * so don't do that again! */
     2527        if (!o->has_empty_slot)
     2528            return perform_glob(o, n); /* o_save_ptr_helper is inside */
     2529    }
     2530    return o_save_ptr_helper(o, n);
     2531}
     2532
     2533/* "Please convert list[n] to real char* ptrs, and NULL terminate it." */
     2534static char **o_finalize_list(o_string *o, int n)
     2535{
     2536    char **list;
     2537    int string_start;
     2538
     2539    n = o_save_ptr(o, n); /* force growth for list[n] if necessary */
     2540    if (DEBUG_EXPAND)
     2541        debug_print_list("finalized", o, n);
     2542    debug_printf_expand("finalized n:%d\n", n);
     2543    list = (char**)o->data;
     2544    string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
     2545    list[--n] = NULL;
     2546    while (n) {
     2547        n--;
     2548        list[n] = o->data + (int)(uintptr_t)list[n] + string_start;
     2549    }
     2550    return list;
     2551}
     2552
     2553static void free_pipe_list(struct pipe *pi);
     2554
     2555/* Returns pi->next - next pipe in the list */
     2556static struct pipe *free_pipe(struct pipe *pi)
     2557{
     2558    struct pipe *next;
     2559    int i;
     2560
     2561    debug_printf_clean("free_pipe (pid %d)\n", getpid());
     2562    for (i = 0; i < pi->num_cmds; i++) {
     2563        struct command *command;
     2564        struct redir_struct *r, *rnext;
     2565
     2566        command = &pi->cmds[i];
     2567        debug_printf_clean("  command %d:\n", i);
     2568        if (command->argv) {
     2569            if (DEBUG_CLEAN) {
     2570                int a;
     2571                char **p;
     2572                for (a = 0, p = command->argv; *p; a++, p++) {
     2573                    debug_printf_clean("   argv[%d] = %s\n", a, *p);
     2574                }
     2575            }
     2576            free_strings(command->argv);
     2577            //command->argv = NULL;
     2578        }
     2579        /* not "else if": on syntax error, we may have both! */
     2580        if (command->group) {
     2581            debug_printf_clean("   begin group (cmd_type:%d)\n",
     2582                    command->cmd_type);
     2583            free_pipe_list(command->group);
     2584            debug_printf_clean("   end group\n");
     2585            //command->group = NULL;
     2586        }
     2587        /* else is crucial here.
     2588         * If group != NULL, child_func is meaningless */
     2589#if ENABLE_HUSH_FUNCTIONS
     2590        else if (command->child_func) {
     2591            debug_printf_exec("cmd %p releases child func at %p\n", command, command->child_func);
     2592            command->child_func->parent_cmd = NULL;
     2593        }
     2594#endif
     2595#if !BB_MMU
     2596        free(command->group_as_string);
     2597        //command->group_as_string = NULL;
     2598#endif
     2599        for (r = command->redirects; r; r = rnext) {
     2600            debug_printf_clean("   redirect %d%s",
     2601                    r->rd_fd, redir_table[r->rd_type].descrip);
     2602            /* guard against the case >$FOO, where foo is unset or blank */
     2603            if (r->rd_filename) {
     2604                debug_printf_clean(" fname:'%s'\n", r->rd_filename);
     2605                free(r->rd_filename);
     2606                //r->rd_filename = NULL;
     2607            }
     2608            debug_printf_clean(" rd_dup:%d\n", r->rd_dup);
     2609            rnext = r->next;
     2610            free(r);
     2611        }
     2612        //command->redirects = NULL;
     2613    }
     2614    free(pi->cmds);   /* children are an array, they get freed all at once */
     2615    //pi->cmds = NULL;
     2616#if ENABLE_HUSH_JOB
     2617    free(pi->cmdtext);
     2618    //pi->cmdtext = NULL;
     2619#endif
     2620
     2621    next = pi->next;
     2622    free(pi);
     2623    return next;
     2624}
     2625
     2626static void free_pipe_list(struct pipe *pi)
     2627{
     2628    while (pi) {
     2629#if HAS_KEYWORDS
     2630        debug_printf_clean("pipe reserved word %d\n", pi->res_word);
     2631#endif
     2632        debug_printf_clean("pipe followup code %d\n", pi->followup);
     2633        pi = free_pipe(pi);
     2634    }
     2635}
     2636
     2637
     2638/*** Parsing routines ***/
     2639
     2640#ifndef debug_print_tree
     2641static void debug_print_tree(struct pipe *pi, int lvl)
     2642{
     2643    static const char *const PIPE[] = {
     2644        [PIPE_SEQ] = "SEQ",
     2645        [PIPE_AND] = "AND",
     2646        [PIPE_OR ] = "OR" ,
     2647        [PIPE_BG ] = "BG" ,
     2648    };
     2649    static const char *RES[] = {
     2650        [RES_NONE ] = "NONE" ,
     2651# if ENABLE_HUSH_IF
     2652        [RES_IF   ] = "IF"   ,
     2653        [RES_THEN ] = "THEN" ,
     2654        [RES_ELIF ] = "ELIF" ,
     2655        [RES_ELSE ] = "ELSE" ,
     2656        [RES_FI   ] = "FI"   ,
     2657# endif
     2658# if ENABLE_HUSH_LOOPS
     2659        [RES_FOR  ] = "FOR"  ,
     2660        [RES_WHILE] = "WHILE",
     2661        [RES_UNTIL] = "UNTIL",
     2662        [RES_DO   ] = "DO"   ,
     2663        [RES_DONE ] = "DONE" ,
     2664# endif
     2665# if ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
     2666        [RES_IN   ] = "IN"   ,
     2667# endif
     2668# if ENABLE_HUSH_CASE
     2669        [RES_CASE ] = "CASE" ,
     2670        [RES_CASE_IN ] = "CASE_IN" ,
     2671        [RES_MATCH] = "MATCH",
     2672        [RES_CASE_BODY] = "CASE_BODY",
     2673        [RES_ESAC ] = "ESAC" ,
     2674# endif
     2675        [RES_XXXX ] = "XXXX" ,
     2676        [RES_SNTX ] = "SNTX" ,
     2677    };
     2678    static const char *const CMDTYPE[] = {
     2679        "{}",
     2680        "()",
     2681        "[noglob]",
     2682# if ENABLE_HUSH_FUNCTIONS
     2683        "func()",
     2684# endif
     2685    };
     2686
     2687    int pin, prn;
     2688
     2689    pin = 0;
     2690    while (pi) {
     2691        fdprintf(2, "%*spipe %d res_word=%s followup=%d %s\n", lvl*2, "",
     2692                pin, RES[pi->res_word], pi->followup, PIPE[pi->followup]);
     2693        prn = 0;
     2694        while (prn < pi->num_cmds) {
     2695            struct command *command = &pi->cmds[prn];
     2696            char **argv = command->argv;
     2697
     2698            fdprintf(2, "%*s cmd %d assignment_cnt:%d",
     2699                    lvl*2, "", prn,
     2700                    command->assignment_cnt);
     2701            if (command->group) {
     2702                fdprintf(2, " group %s: (argv=%p)%s%s\n",
     2703                        CMDTYPE[command->cmd_type],
     2704                        argv
     2705# if !BB_MMU
     2706                        , " group_as_string:", command->group_as_string
     2707# else
     2708                        , "", ""
     2709# endif
     2710                );
     2711                debug_print_tree(command->group, lvl+1);
     2712                prn++;
     2713                continue;
     2714            }
     2715            if (argv) while (*argv) {
     2716                fdprintf(2, " '%s'", *argv);
     2717                argv++;
     2718            }
     2719            fdprintf(2, "\n");
     2720            prn++;
     2721        }
     2722        pi = pi->next;
     2723        pin++;
     2724    }
     2725}
     2726#endif /* debug_print_tree */
     2727
     2728static struct pipe *new_pipe(void)
     2729{
     2730    struct pipe *pi;
     2731    pi = xzalloc(sizeof(struct pipe));
     2732    /*pi->followup = 0; - deliberately invalid value */
     2733    /*pi->res_word = RES_NONE; - RES_NONE is 0 anyway */
     2734    return pi;
     2735}
     2736
     2737/* Command (member of a pipe) is complete, or we start a new pipe
     2738 * if ctx->command is NULL.
     2739 * No errors possible here.
     2740 */
     2741static int done_command(struct parse_context *ctx)
     2742{
     2743    /* The command is really already in the pipe structure, so
     2744     * advance the pipe counter and make a new, null command. */
     2745    struct pipe *pi = ctx->pipe;
     2746    struct command *command = ctx->command;
     2747
     2748    if (command) {
     2749        if (IS_NULL_CMD(command)) {
     2750            debug_printf_parse("done_command: skipping null cmd, num_cmds=%d\n", pi->num_cmds);
     2751            goto clear_and_ret;
     2752        }
     2753        pi->num_cmds++;
     2754        debug_printf_parse("done_command: ++num_cmds=%d\n", pi->num_cmds);
     2755        //debug_print_tree(ctx->list_head, 20);
     2756    } else {
     2757        debug_printf_parse("done_command: initializing, num_cmds=%d\n", pi->num_cmds);
     2758    }
     2759
     2760    /* Only real trickiness here is that the uncommitted
     2761     * command structure is not counted in pi->num_cmds. */
     2762    pi->cmds = xrealloc(pi->cmds, sizeof(*pi->cmds) * (pi->num_cmds+1));
     2763    ctx->command = command = &pi->cmds[pi->num_cmds];
     2764 clear_and_ret:
     2765    memset(command, 0, sizeof(*command));
     2766    return pi->num_cmds; /* used only for 0/nonzero check */
     2767}
     2768
     2769static void done_pipe(struct parse_context *ctx, pipe_style type)
     2770{
     2771    int not_null;
     2772
     2773    debug_printf_parse("done_pipe entered, followup %d\n", type);
     2774    /* Close previous command */
     2775    not_null = done_command(ctx);
     2776    ctx->pipe->followup = type;
     2777#if HAS_KEYWORDS
     2778    ctx->pipe->pi_inverted = ctx->ctx_inverted;
     2779    ctx->ctx_inverted = 0;
     2780    ctx->pipe->res_word = ctx->ctx_res_w;
     2781#endif
     2782
     2783    /* Without this check, even just <enter> on command line generates
     2784     * tree of three NOPs (!). Which is harmless but annoying.
     2785     * IOW: it is safe to do it unconditionally. */
     2786    if (not_null
     2787#if ENABLE_HUSH_IF
     2788     || ctx->ctx_res_w == RES_FI
     2789#endif
     2790#if ENABLE_HUSH_LOOPS
     2791     || ctx->ctx_res_w == RES_DONE
     2792     || ctx->ctx_res_w == RES_FOR
     2793     || ctx->ctx_res_w == RES_IN
     2794#endif
     2795#if ENABLE_HUSH_CASE
     2796     || ctx->ctx_res_w == RES_ESAC
     2797#endif
     2798    ) {
     2799        struct pipe *new_p;
     2800        debug_printf_parse("done_pipe: adding new pipe: "
     2801                "not_null:%d ctx->ctx_res_w:%d\n",
     2802                not_null, ctx->ctx_res_w);
     2803        new_p = new_pipe();
     2804        ctx->pipe->next = new_p;
     2805        ctx->pipe = new_p;
     2806        /* RES_THEN, RES_DO etc are "sticky" -
     2807         * they remain set for pipes inside if/while.
     2808         * This is used to control execution.
     2809         * RES_FOR and RES_IN are NOT sticky (needed to support
     2810         * cases where variable or value happens to match a keyword):
     2811         */
     2812#if ENABLE_HUSH_LOOPS
     2813        if (ctx->ctx_res_w == RES_FOR
     2814         || ctx->ctx_res_w == RES_IN)
     2815            ctx->ctx_res_w = RES_NONE;
     2816#endif
     2817#if ENABLE_HUSH_CASE
     2818        if (ctx->ctx_res_w == RES_MATCH)
     2819            ctx->ctx_res_w = RES_CASE_BODY;
     2820        if (ctx->ctx_res_w == RES_CASE)
     2821            ctx->ctx_res_w = RES_CASE_IN;
     2822#endif
     2823        ctx->command = NULL; /* trick done_command below */
     2824        /* Create the memory for command, roughly:
     2825         * ctx->pipe->cmds = new struct command;
     2826         * ctx->command = &ctx->pipe->cmds[0];
     2827         */
     2828        done_command(ctx);
     2829        //debug_print_tree(ctx->list_head, 10);
     2830    }
     2831    debug_printf_parse("done_pipe return\n");
     2832}
     2833
     2834static void initialize_context(struct parse_context *ctx)
     2835{
     2836    memset(ctx, 0, sizeof(*ctx));
     2837    ctx->pipe = ctx->list_head = new_pipe();
     2838    /* Create the memory for command, roughly:
     2839     * ctx->pipe->cmds = new struct command;
     2840     * ctx->command = &ctx->pipe->cmds[0];
     2841     */
     2842    done_command(ctx);
     2843}
     2844
     2845/* If a reserved word is found and processed, parse context is modified
     2846 * and 1 is returned.
     2847 */
     2848#if HAS_KEYWORDS
     2849struct reserved_combo {
     2850    char literal[6];
     2851    unsigned char res;
     2852    unsigned char assignment_flag;
     2853    int flag;
     2854};
     2855enum {
     2856    FLAG_END   = (1 << RES_NONE ),
     2857# if ENABLE_HUSH_IF
     2858    FLAG_IF    = (1 << RES_IF   ),
     2859    FLAG_THEN  = (1 << RES_THEN ),
     2860    FLAG_ELIF  = (1 << RES_ELIF ),
     2861    FLAG_ELSE  = (1 << RES_ELSE ),
     2862    FLAG_FI    = (1 << RES_FI   ),
     2863# endif
     2864# if ENABLE_HUSH_LOOPS
     2865    FLAG_FOR   = (1 << RES_FOR  ),
     2866    FLAG_WHILE = (1 << RES_WHILE),
     2867    FLAG_UNTIL = (1 << RES_UNTIL),
     2868    FLAG_DO    = (1 << RES_DO   ),
     2869    FLAG_DONE  = (1 << RES_DONE ),
     2870    FLAG_IN    = (1 << RES_IN   ),
     2871# endif
     2872# if ENABLE_HUSH_CASE
     2873    FLAG_MATCH = (1 << RES_MATCH),
     2874    FLAG_ESAC  = (1 << RES_ESAC ),
     2875# endif
     2876    FLAG_START = (1 << RES_XXXX ),
     2877};
     2878
     2879static const struct reserved_combo* match_reserved_word(o_string *word)
     2880{
     2881    /* Mostly a list of accepted follow-up reserved words.
     2882     * FLAG_END means we are done with the sequence, and are ready
     2883     * to turn the compound list into a command.
     2884     * FLAG_START means the word must start a new compound list.
     2885     */
     2886    static const struct reserved_combo reserved_list[] = {
     2887# if ENABLE_HUSH_IF
     2888        { "!",     RES_NONE,  NOT_ASSIGNMENT , 0 },
     2889        { "if",    RES_IF,    WORD_IS_KEYWORD, FLAG_THEN | FLAG_START },
     2890        { "then",  RES_THEN,  WORD_IS_KEYWORD, FLAG_ELIF | FLAG_ELSE | FLAG_FI },
     2891        { "elif",  RES_ELIF,  WORD_IS_KEYWORD, FLAG_THEN },
     2892        { "else",  RES_ELSE,  WORD_IS_KEYWORD, FLAG_FI   },
     2893        { "fi",    RES_FI,    NOT_ASSIGNMENT , FLAG_END  },
     2894# endif
     2895# if ENABLE_HUSH_LOOPS
     2896        { "for",   RES_FOR,   NOT_ASSIGNMENT , FLAG_IN | FLAG_DO | FLAG_START },
     2897        { "while", RES_WHILE, WORD_IS_KEYWORD, FLAG_DO | FLAG_START },
     2898        { "until", RES_UNTIL, WORD_IS_KEYWORD, FLAG_DO | FLAG_START },
     2899        { "in",    RES_IN,    NOT_ASSIGNMENT , FLAG_DO   },
     2900        { "do",    RES_DO,    WORD_IS_KEYWORD, FLAG_DONE },
     2901        { "done",  RES_DONE,  NOT_ASSIGNMENT , FLAG_END  },
     2902# endif
     2903# if ENABLE_HUSH_CASE
     2904        { "case",  RES_CASE,  NOT_ASSIGNMENT , FLAG_MATCH | FLAG_START },
     2905        { "esac",  RES_ESAC,  NOT_ASSIGNMENT , FLAG_END  },
     2906# endif
     2907    };
     2908    const struct reserved_combo *r;
     2909
     2910    for (r = reserved_list; r < reserved_list + ARRAY_SIZE(reserved_list); r++) {
     2911        if (strcmp(word->data, r->literal) == 0)
     2912            return r;
     2913    }
     2914    return NULL;
     2915}
     2916/* Return 0: not a keyword, 1: keyword
     2917 */
     2918static int reserved_word(o_string *word, struct parse_context *ctx)
     2919{
     2920# if ENABLE_HUSH_CASE
     2921    static const struct reserved_combo reserved_match = {
     2922        "",        RES_MATCH, NOT_ASSIGNMENT , FLAG_MATCH | FLAG_ESAC
     2923    };
     2924# endif
     2925    const struct reserved_combo *r;
     2926
     2927    if (word->has_quoted_part)
     2928        return 0;
     2929    r = match_reserved_word(word);
     2930    if (!r)
     2931        return 0;
     2932
     2933    debug_printf("found reserved word %s, res %d\n", r->literal, r->res);
     2934# if ENABLE_HUSH_CASE
     2935    if (r->res == RES_IN && ctx->ctx_res_w == RES_CASE_IN) {
     2936        /* "case word IN ..." - IN part starts first MATCH part */
     2937        r = &reserved_match;
     2938    } else
     2939# endif
     2940    if (r->flag == 0) { /* '!' */
     2941        if (ctx->ctx_inverted) { /* bash doesn't accept '! ! true' */
     2942            syntax_error("! ! command");
     2943            ctx->ctx_res_w = RES_SNTX;
     2944        }
     2945        ctx->ctx_inverted = 1;
     2946        return 1;
     2947    }
     2948    if (r->flag & FLAG_START) {
     2949        struct parse_context *old;
     2950
     2951        old = xmalloc(sizeof(*old));
     2952        debug_printf_parse("push stack %p\n", old);
     2953        *old = *ctx;   /* physical copy */
     2954        initialize_context(ctx);
     2955        ctx->stack = old;
     2956    } else if (/*ctx->ctx_res_w == RES_NONE ||*/ !(ctx->old_flag & (1 << r->res))) {
     2957        syntax_error_at(word->data);
     2958        ctx->ctx_res_w = RES_SNTX;
     2959        return 1;
     2960    } else {
     2961        /* "{...} fi" is ok. "{...} if" is not
     2962         * Example:
     2963         * if { echo foo; } then { echo bar; } fi */
     2964        if (ctx->command->group)
     2965            done_pipe(ctx, PIPE_SEQ);
     2966    }
     2967
     2968    ctx->ctx_res_w = r->res;
     2969    ctx->old_flag = r->flag;
     2970    word->o_assignment = r->assignment_flag;
     2971
     2972    if (ctx->old_flag & FLAG_END) {
     2973        struct parse_context *old;
     2974
     2975        done_pipe(ctx, PIPE_SEQ);
     2976        debug_printf_parse("pop stack %p\n", ctx->stack);
     2977        old = ctx->stack;
     2978        old->command->group = ctx->list_head;
     2979        old->command->cmd_type = CMD_NORMAL;
     2980# if !BB_MMU
     2981        o_addstr(&old->as_string, ctx->as_string.data);
     2982        o_free_unsafe(&ctx->as_string);
     2983        old->command->group_as_string = xstrdup(old->as_string.data);
     2984        debug_printf_parse("pop, remembering as:'%s'\n",
     2985                old->command->group_as_string);
     2986# endif
     2987        *ctx = *old;   /* physical copy */
     2988        free(old);
     2989    }
     2990    return 1;
     2991}
     2992#endif /* HAS_KEYWORDS */
     2993
     2994/* Word is complete, look at it and update parsing context.
     2995 * Normal return is 0. Syntax errors return 1.
     2996 * Note: on return, word is reset, but not o_free'd!
     2997 */
     2998static int done_word(o_string *word, struct parse_context *ctx)
     2999{
     3000    struct command *command = ctx->command;
     3001
     3002    debug_printf_parse("done_word entered: '%s' %p\n", word->data, command);
     3003    if (word->length == 0 && !word->has_quoted_part) {
     3004        debug_printf_parse("done_word return 0: true null, ignored\n");
     3005        return 0;
     3006    }
     3007
     3008    if (ctx->pending_redirect) {
     3009        /* We do not glob in e.g. >*.tmp case. bash seems to glob here
     3010         * only if run as "bash", not "sh" */
     3011        /* http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
     3012         * "2.7 Redirection
     3013         * ...the word that follows the redirection operator
     3014         * shall be subjected to tilde expansion, parameter expansion,
     3015         * command substitution, arithmetic expansion, and quote
     3016         * removal. Pathname expansion shall not be performed
     3017         * on the word by a non-interactive shell; an interactive
     3018         * shell may perform it, but shall do so only when
     3019         * the expansion would result in one word."
     3020         */
     3021        ctx->pending_redirect->rd_filename = xstrdup(word->data);
     3022        /* Cater for >\file case:
     3023         * >\a creates file a; >\\a, >"\a", >"\\a" create file \a
     3024         * Same with heredocs:
     3025         * for <<\H delim is H; <<\\H, <<"\H", <<"\\H" - \H
     3026         */
     3027        if (ctx->pending_redirect->rd_type == REDIRECT_HEREDOC) {
     3028            unbackslash(ctx->pending_redirect->rd_filename);
     3029            /* Is it <<"HEREDOC"? */
     3030            if (word->has_quoted_part) {
     3031                ctx->pending_redirect->rd_dup |= HEREDOC_QUOTED;
     3032            }
     3033        }
     3034        debug_printf_parse("word stored in rd_filename: '%s'\n", word->data);
     3035        ctx->pending_redirect = NULL;
     3036    } else {
     3037        /* If this word wasn't an assignment, next ones definitely
     3038         * can't be assignments. Even if they look like ones. */
     3039        if (word->o_assignment != DEFINITELY_ASSIGNMENT
     3040         && word->o_assignment != WORD_IS_KEYWORD
     3041        ) {
     3042            word->o_assignment = NOT_ASSIGNMENT;
     3043        } else {
     3044            if (word->o_assignment == DEFINITELY_ASSIGNMENT)
     3045                command->assignment_cnt++;
     3046            word->o_assignment = MAYBE_ASSIGNMENT;
     3047        }
     3048
     3049#if HAS_KEYWORDS
     3050# if ENABLE_HUSH_CASE
     3051        if (ctx->ctx_dsemicolon
     3052         && strcmp(word->data, "esac") != 0 /* not "... pattern) cmd;; esac" */
     3053        ) {
     3054            /* already done when ctx_dsemicolon was set to 1: */
     3055            /* ctx->ctx_res_w = RES_MATCH; */
     3056            ctx->ctx_dsemicolon = 0;
     3057        } else
     3058# endif
     3059        if (!command->argv /* if it's the first word... */
     3060# if ENABLE_HUSH_LOOPS
     3061         && ctx->ctx_res_w != RES_FOR /* ...not after FOR or IN */
     3062         && ctx->ctx_res_w != RES_IN
     3063# endif
     3064# if ENABLE_HUSH_CASE
     3065         && ctx->ctx_res_w != RES_CASE
     3066# endif
     3067        ) {
     3068            debug_printf_parse("checking '%s' for reserved-ness\n", word->data);
     3069            if (reserved_word(word, ctx)) {
     3070                o_reset_to_empty_unquoted(word);
     3071                debug_printf_parse("done_word return %d\n",
     3072                        (ctx->ctx_res_w == RES_SNTX));
     3073                return (ctx->ctx_res_w == RES_SNTX);
     3074            }
     3075# if ENABLE_HUSH_BASH_COMPAT
     3076            if (strcmp(word->data, "[[") == 0) {
     3077                command->cmd_type = CMD_SINGLEWORD_NOGLOB;
     3078            }
     3079            /* fall through */
     3080# endif
     3081        }
     3082#endif
     3083        if (command->group) {
     3084            /* "{ echo foo; } echo bar" - bad */
     3085            syntax_error_at(word->data);
     3086            debug_printf_parse("done_word return 1: syntax error, "
     3087                    "groups and arglists don't mix\n");
     3088            return 1;
     3089        }
     3090        if (word->has_quoted_part
     3091         /* optimization: and if it's ("" or '') or ($v... or `cmd`...): */
     3092         && (word->data[0] == '\0' || word->data[0] == SPECIAL_VAR_SYMBOL)
     3093         /* (otherwise it's known to be not empty and is already safe) */
     3094        ) {
     3095            /* exclude "$@" - it can expand to no word despite "" */
     3096            char *p = word->data;
     3097            while (p[0] == SPECIAL_VAR_SYMBOL
     3098                && (p[1] & 0x7f) == '@'
     3099                && p[2] == SPECIAL_VAR_SYMBOL
     3100            ) {
     3101                p += 3;
     3102            }
     3103            if (p == word->data || p[0] != '\0') {
     3104                /* saw no "$@", or not only "$@" but some
     3105                 * real text is there too */
     3106                /* insert "empty variable" reference, this makes
     3107                 * e.g. "", $empty"" etc to not disappear */
     3108                o_addchr(word, SPECIAL_VAR_SYMBOL);
     3109                o_addchr(word, SPECIAL_VAR_SYMBOL);
     3110            }
     3111        }
     3112        command->argv = add_string_to_strings(command->argv, xstrdup(word->data));
     3113        debug_print_strings("word appended to argv", command->argv);
     3114    }
     3115
     3116#if ENABLE_HUSH_LOOPS
     3117    if (ctx->ctx_res_w == RES_FOR) {
     3118        if (word->has_quoted_part
     3119         || !is_well_formed_var_name(command->argv[0], '\0')
     3120        ) {
     3121            /* bash says just "not a valid identifier" */
     3122            syntax_error("not a valid identifier in for");
     3123            return 1;
     3124        }
     3125        /* Force FOR to have just one word (variable name) */
     3126        /* NB: basically, this makes hush see "for v in ..."
     3127         * syntax as if it is "for v; in ...". FOR and IN become
     3128         * two pipe structs in parse tree. */
     3129        done_pipe(ctx, PIPE_SEQ);
     3130    }
     3131#endif
     3132#if ENABLE_HUSH_CASE
     3133    /* Force CASE to have just one word */
     3134    if (ctx->ctx_res_w == RES_CASE) {
     3135        done_pipe(ctx, PIPE_SEQ);
     3136    }
     3137#endif
     3138
     3139    o_reset_to_empty_unquoted(word);
     3140
     3141    debug_printf_parse("done_word return 0\n");
     3142    return 0;
     3143}
     3144
     3145
     3146/* Peek ahead in the input to find out if we have a "&n" construct,
     3147 * as in "2>&1", that represents duplicating a file descriptor.
     3148 * Return:
     3149 * REDIRFD_CLOSE if >&- "close fd" construct is seen,
     3150 * REDIRFD_SYNTAX_ERR if syntax error,
     3151 * REDIRFD_TO_FILE if no & was seen,
     3152 * or the number found.
     3153 */
     3154#if BB_MMU
     3155#define parse_redir_right_fd(as_string, input) \
     3156    parse_redir_right_fd(input)
     3157#endif
     3158static int parse_redir_right_fd(o_string *as_string, struct in_str *input)
     3159{
     3160    int ch, d, ok;
     3161
     3162    ch = i_peek(input);
     3163    if (ch != '&')
     3164        return REDIRFD_TO_FILE;
     3165
     3166    ch = i_getch(input);  /* get the & */
     3167    nommu_addchr(as_string, ch);
     3168    ch = i_peek(input);
     3169    if (ch == '-') {
     3170        ch = i_getch(input);
     3171        nommu_addchr(as_string, ch);
     3172        return REDIRFD_CLOSE;
     3173    }
     3174    d = 0;
     3175    ok = 0;
     3176    while (ch != EOF && isdigit(ch)) {
     3177        d = d*10 + (ch-'0');
     3178        ok = 1;
     3179        ch = i_getch(input);
     3180        nommu_addchr(as_string, ch);
     3181        ch = i_peek(input);
     3182    }
     3183    if (ok) return d;
     3184
     3185//TODO: this is the place to catch ">&file" bashism (redirect both fd 1 and 2)
     3186
     3187    bb_error_msg("ambiguous redirect");
     3188    return REDIRFD_SYNTAX_ERR;
     3189}
     3190
     3191/* Return code is 0 normal, 1 if a syntax error is detected
     3192 */
     3193static int parse_redirect(struct parse_context *ctx,
     3194        int fd,
     3195        redir_type style,
     3196        struct in_str *input)
     3197{
     3198    struct command *command = ctx->command;
     3199    struct redir_struct *redir;
     3200    struct redir_struct **redirp;
     3201    int dup_num;
     3202
     3203    dup_num = REDIRFD_TO_FILE;
     3204    if (style != REDIRECT_HEREDOC) {
     3205        /* Check for a '>&1' type redirect */
     3206        dup_num = parse_redir_right_fd(&ctx->as_string, input);
     3207        if (dup_num == REDIRFD_SYNTAX_ERR)
     3208            return 1;
     3209    } else {
     3210        int ch = i_peek(input);
     3211        dup_num = (ch == '-'); /* HEREDOC_SKIPTABS bit is 1 */
     3212        if (dup_num) { /* <<-... */
     3213            ch = i_getch(input);
     3214            nommu_addchr(&ctx->as_string, ch);
     3215            ch = i_peek(input);
     3216        }
     3217    }
     3218
     3219    if (style == REDIRECT_OVERWRITE && dup_num == REDIRFD_TO_FILE) {
     3220        int ch = i_peek(input);
     3221        if (ch == '|') {
     3222            /* >|FILE redirect ("clobbering" >).
     3223             * Since we do not support "set -o noclobber" yet,
     3224             * >| and > are the same for now. Just eat |.
     3225             */
     3226            ch = i_getch(input);
     3227            nommu_addchr(&ctx->as_string, ch);
     3228        }
     3229    }
     3230
     3231    /* Create a new redir_struct and append it to the linked list */
     3232    redirp = &command->redirects;
     3233    while ((redir = *redirp) != NULL) {
     3234        redirp = &(redir->next);
     3235    }
     3236    *redirp = redir = xzalloc(sizeof(*redir));
     3237    /* redir->next = NULL; */
     3238    /* redir->rd_filename = NULL; */
     3239    redir->rd_type = style;
     3240    redir->rd_fd = (fd == -1) ? redir_table[style].default_fd : fd;
     3241
     3242    debug_printf_parse("redirect type %d %s\n", redir->rd_fd,
     3243                redir_table[style].descrip);
     3244
     3245    redir->rd_dup = dup_num;
     3246    if (style != REDIRECT_HEREDOC && dup_num != REDIRFD_TO_FILE) {
     3247        /* Erik had a check here that the file descriptor in question
     3248         * is legit; I postpone that to "run time"
     3249         * A "-" representation of "close me" shows up as a -3 here */
     3250        debug_printf_parse("duplicating redirect '%d>&%d'\n",
     3251                redir->rd_fd, redir->rd_dup);
     3252    } else {
     3253        /* Set ctx->pending_redirect, so we know what to do at the
     3254         * end of the next parsed word. */
     3255        ctx->pending_redirect = redir;
     3256    }
     3257    return 0;
     3258}
     3259
     3260/* If a redirect is immediately preceded by a number, that number is
     3261 * supposed to tell which file descriptor to redirect.  This routine
     3262 * looks for such preceding numbers.  In an ideal world this routine
     3263 * needs to handle all the following classes of redirects...
     3264 *     echo 2>foo     # redirects fd  2 to file "foo", nothing passed to echo
     3265 *     echo 49>foo    # redirects fd 49 to file "foo", nothing passed to echo
     3266 *     echo -2>foo    # redirects fd  1 to file "foo",    "-2" passed to echo
     3267 *     echo 49x>foo   # redirects fd  1 to file "foo",   "49x" passed to echo
     3268 *
     3269 * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
     3270 * "2.7 Redirection
     3271 * ... If n is quoted, the number shall not be recognized as part of
     3272 * the redirection expression. For example:
     3273 * echo \2>a
     3274 * writes the character 2 into file a"
     3275 * We are getting it right by setting ->has_quoted_part on any \<char>
     3276 *
     3277 * A -1 return means no valid number was found,
     3278 * the caller should use the appropriate default for this redirection.
     3279 */
     3280static int redirect_opt_num(o_string *o)
     3281{
     3282    int num;
     3283
     3284    if (o->data == NULL)
     3285        return -1;
     3286    num = bb_strtou(o->data, NULL, 10);
     3287    if (errno || num < 0)
     3288        return -1;
     3289    o_reset_to_empty_unquoted(o);
     3290    return num;
     3291}
     3292
     3293#if BB_MMU
     3294#define fetch_till_str(as_string, input, word, skip_tabs) \
     3295    fetch_till_str(input, word, skip_tabs)
     3296#endif
     3297static char *fetch_till_str(o_string *as_string,
     3298        struct in_str *input,
     3299        const char *word,
     3300        int heredoc_flags)
     3301{
     3302    o_string heredoc = NULL_O_STRING;
     3303    unsigned past_EOL;
     3304    int prev = 0; /* not \ */
     3305    int ch;
     3306
     3307    goto jump_in;
     3308    while (1) {
     3309        ch = i_getch(input);
     3310        if (ch != EOF)
     3311            nommu_addchr(as_string, ch);
     3312        if ((ch == '\n' || ch == EOF)
     3313         && ((heredoc_flags & HEREDOC_QUOTED) || prev != '\\')
     3314        ) {
     3315            if (strcmp(heredoc.data + past_EOL, word) == 0) {
     3316                heredoc.data[past_EOL] = '\0';
     3317                debug_printf_parse("parsed heredoc '%s'\n", heredoc.data);
     3318                return heredoc.data;
     3319            }
     3320            while (ch == '\n') {
     3321                o_addchr(&heredoc, ch);
     3322                prev = ch;
     3323 jump_in:
     3324                past_EOL = heredoc.length;
     3325                do {
     3326                    ch = i_getch(input);
     3327                    if (ch != EOF)
     3328                        nommu_addchr(as_string, ch);
     3329                } while ((heredoc_flags & HEREDOC_SKIPTABS) && ch == '\t');
     3330            }
     3331        }
     3332        if (ch == EOF) {
     3333            o_free_unsafe(&heredoc);
     3334            return NULL;
     3335        }
     3336        o_addchr(&heredoc, ch);
     3337        nommu_addchr(as_string, ch);
     3338        if (prev == '\\' && ch == '\\')
     3339            /* Correctly handle foo\\<eol> (not a line cont.) */
     3340            prev = 0; /* not \ */
     3341        else
     3342            prev = ch;
     3343    }
     3344}
     3345
     3346/* Look at entire parse tree for not-yet-loaded REDIRECT_HEREDOCs
     3347 * and load them all. There should be exactly heredoc_cnt of them.
     3348 */
     3349static int fetch_heredocs(int heredoc_cnt, struct parse_context *ctx, struct in_str *input)
     3350{
     3351    struct pipe *pi = ctx->list_head;
     3352
     3353    while (pi && heredoc_cnt) {
     3354        int i;
     3355        struct command *cmd = pi->cmds;
     3356
     3357        debug_printf_parse("fetch_heredocs: num_cmds:%d cmd argv0:'%s'\n",
     3358                pi->num_cmds,
     3359                cmd->argv ? cmd->argv[0] : "NONE");
     3360        for (i = 0; i < pi->num_cmds; i++) {
     3361            struct redir_struct *redir = cmd->redirects;
     3362
     3363            debug_printf_parse("fetch_heredocs: %d cmd argv0:'%s'\n",
     3364                    i, cmd->argv ? cmd->argv[0] : "NONE");
     3365            while (redir) {
     3366                if (redir->rd_type == REDIRECT_HEREDOC) {
     3367                    char *p;
     3368
     3369                    redir->rd_type = REDIRECT_HEREDOC2;
     3370                    /* redir->rd_dup is (ab)used to indicate <<- */
     3371                    p = fetch_till_str(&ctx->as_string, input,
     3372                            redir->rd_filename, redir->rd_dup);
     3373                    if (!p) {
     3374                        syntax_error("unexpected EOF in here document");
     3375                        return 1;
     3376                    }
     3377                    free(redir->rd_filename);
     3378                    redir->rd_filename = p;
     3379                    heredoc_cnt--;
     3380                }
     3381                redir = redir->next;
     3382            }
     3383            cmd++;
     3384        }
     3385        pi = pi->next;
     3386    }
     3387#if 0
     3388    /* Should be 0. If it isn't, it's a parse error */
     3389    if (heredoc_cnt)
     3390        bb_error_msg_and_die("heredoc BUG 2");
     3391#endif
     3392    return 0;
     3393}
     3394
     3395
     3396static int run_list(struct pipe *pi);
     3397#if BB_MMU
     3398#define parse_stream(pstring, input, end_trigger) \
     3399    parse_stream(input, end_trigger)
     3400#endif
     3401static struct pipe *parse_stream(char **pstring,
     3402        struct in_str *input,
     3403        int end_trigger);
     3404
     3405
     3406#if !ENABLE_HUSH_FUNCTIONS
     3407#define parse_group(dest, ctx, input, ch) \
     3408    parse_group(ctx, input, ch)
     3409#endif
     3410static int parse_group(o_string *dest, struct parse_context *ctx,
     3411    struct in_str *input, int ch)
     3412{
     3413    /* dest contains characters seen prior to ( or {.
     3414     * Typically it's empty, but for function defs,
     3415     * it contains function name (without '()'). */
     3416    struct pipe *pipe_list;
     3417    int endch;
     3418    struct command *command = ctx->command;
     3419
     3420    debug_printf_parse("parse_group entered\n");
     3421#if ENABLE_HUSH_FUNCTIONS
     3422    if (ch == '(' && !dest->has_quoted_part) {
     3423        if (dest->length)
     3424            if (done_word(dest, ctx))
     3425                return 1;
     3426        if (!command->argv)
     3427            goto skip; /* (... */
     3428        if (command->argv[1]) { /* word word ... (... */
     3429            syntax_error_unexpected_ch('(');
     3430            return 1;
     3431        }
     3432        /* it is "word(..." or "word (..." */
     3433        do
     3434            ch = i_getch(input);
     3435        while (ch == ' ' || ch == '\t');
     3436        if (ch != ')') {
     3437            syntax_error_unexpected_ch(ch);
     3438            return 1;
     3439        }
     3440        nommu_addchr(&ctx->as_string, ch);
     3441        do
     3442            ch = i_getch(input);
     3443        while (ch == ' ' || ch == '\t' || ch == '\n');
     3444        if (ch != '{') {
     3445            syntax_error_unexpected_ch(ch);
     3446            return 1;
     3447        }
     3448        nommu_addchr(&ctx->as_string, ch);
     3449        command->cmd_type = CMD_FUNCDEF;
     3450        goto skip;
     3451    }
     3452#endif
     3453
     3454#if 0 /* Prevented by caller */
     3455    if (command->argv /* word [word]{... */
     3456     || dest->length /* word{... */
     3457     || dest->has_quoted_part /* ""{... */
     3458    ) {
     3459        syntax_error(NULL);
     3460        debug_printf_parse("parse_group return 1: "
     3461            "syntax error, groups and arglists don't mix\n");
     3462        return 1;
     3463    }
     3464#endif
     3465
     3466#if ENABLE_HUSH_FUNCTIONS
     3467 skip:
     3468#endif
     3469    endch = '}';
     3470    if (ch == '(') {
     3471        endch = ')';
     3472        command->cmd_type = CMD_SUBSHELL;
     3473    } else {
     3474        /* bash does not allow "{echo...", requires whitespace */
     3475        ch = i_getch(input);
     3476        if (ch != ' ' && ch != '\t' && ch != '\n') {
     3477            syntax_error_unexpected_ch(ch);
     3478            return 1;
     3479        }
     3480        nommu_addchr(&ctx->as_string, ch);
     3481    }
     3482
     3483    {
     3484#if BB_MMU
     3485# define as_string NULL
     3486#else
     3487        char *as_string = NULL;
     3488#endif
     3489        pipe_list = parse_stream(&as_string, input, endch);
     3490#if !BB_MMU
     3491        if (as_string)
     3492            o_addstr(&ctx->as_string, as_string);
     3493#endif
     3494        /* empty ()/{} or parse error? */
     3495        if (!pipe_list || pipe_list == ERR_PTR) {
     3496            /* parse_stream already emitted error msg */
     3497            if (!BB_MMU)
     3498                free(as_string);
     3499            debug_printf_parse("parse_group return 1: "
     3500                "parse_stream returned %p\n", pipe_list);
     3501            return 1;
     3502        }
     3503        command->group = pipe_list;
     3504#if !BB_MMU
     3505        as_string[strlen(as_string) - 1] = '\0'; /* plink ')' or '}' */
     3506        command->group_as_string = as_string;
     3507        debug_printf_parse("end of group, remembering as:'%s'\n",
     3508                command->group_as_string);
     3509#endif
     3510#undef as_string
     3511    }
     3512    debug_printf_parse("parse_group return 0\n");
     3513    return 0;
     3514    /* command remains "open", available for possible redirects */
     3515}
     3516
     3517#if ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_DOLLAR_OPS
     3518/* Subroutines for copying $(...) and `...` things */
     3519static void add_till_backquote(o_string *dest, struct in_str *input, int in_dquote);
     3520/* '...' */
     3521static void add_till_single_quote(o_string *dest, struct in_str *input)
     3522{
     3523    while (1) {
     3524        int ch = i_getch(input);
     3525        if (ch == EOF) {
     3526            syntax_error_unterm_ch('\'');
     3527            /*xfunc_die(); - redundant */
     3528        }
     3529        if (ch == '\'')
     3530            return;
     3531        o_addchr(dest, ch);
     3532    }
     3533}
     3534/* "...\"...`..`...." - do we need to handle "...$(..)..." too? */
     3535static void add_till_double_quote(o_string *dest, struct in_str *input)
     3536{
     3537    while (1) {
     3538        int ch = i_getch(input);
     3539        if (ch == EOF) {
     3540            syntax_error_unterm_ch('"');
     3541            /*xfunc_die(); - redundant */
     3542        }
     3543        if (ch == '"')
     3544            return;
     3545        if (ch == '\\') {  /* \x. Copy both chars. */
     3546            o_addchr(dest, ch);
     3547            ch = i_getch(input);
     3548        }
     3549        o_addchr(dest, ch);
     3550        if (ch == '`') {
     3551            add_till_backquote(dest, input, /*in_dquote:*/ 1);
     3552            o_addchr(dest, ch);
     3553            continue;
     3554        }
     3555        //if (ch == '$') ...
     3556    }
     3557}
     3558/* Process `cmd` - copy contents until "`" is seen. Complicated by
     3559 * \` quoting.
     3560 * "Within the backquoted style of command substitution, backslash
     3561 * shall retain its literal meaning, except when followed by: '$', '`', or '\'.
     3562 * The search for the matching backquote shall be satisfied by the first
     3563 * backquote found without a preceding backslash; during this search,
     3564 * if a non-escaped backquote is encountered within a shell comment,
     3565 * a here-document, an embedded command substitution of the $(command)
     3566 * form, or a quoted string, undefined results occur. A single-quoted
     3567 * or double-quoted string that begins, but does not end, within the
     3568 * "`...`" sequence produces undefined results."
     3569 * Example                               Output
     3570 * echo `echo '\'TEST\`echo ZZ\`BEST`    \TESTZZBEST
     3571 */
     3572static void add_till_backquote(o_string *dest, struct in_str *input, int in_dquote)
     3573{
     3574    while (1) {
     3575        int ch = i_getch(input);
     3576        if (ch == '`')
     3577            return;
     3578        if (ch == '\\') {
     3579            /* \x. Copy both unless it is \`, \$, \\ and maybe \" */
     3580            ch = i_getch(input);
     3581            if (ch != '`'
     3582             && ch != '$'
     3583             && ch != '\\'
     3584             && (!in_dquote || ch != '"')
     3585            ) {
     3586                o_addchr(dest, '\\');
     3587            }
     3588        }
     3589        if (ch == EOF) {
     3590            syntax_error_unterm_ch('`');
     3591            /*xfunc_die(); - redundant */
     3592        }
     3593        o_addchr(dest, ch);
     3594    }
     3595}
     3596/* Process $(cmd) - copy contents until ")" is seen. Complicated by
     3597 * quoting and nested ()s.
     3598 * "With the $(command) style of command substitution, all characters
     3599 * following the open parenthesis to the matching closing parenthesis
     3600 * constitute the command. Any valid shell script can be used for command,
     3601 * except a script consisting solely of redirections which produces
     3602 * unspecified results."
     3603 * Example                              Output
     3604 * echo $(echo '(TEST)' BEST)           (TEST) BEST
     3605 * echo $(echo 'TEST)' BEST)            TEST) BEST
     3606 * echo $(echo \(\(TEST\) BEST)         ((TEST) BEST
     3607 *
     3608 * Also adapted to eat ${var%...} and $((...)) constructs, since ... part
     3609 * can contain arbitrary constructs, just like $(cmd).
     3610 * In bash compat mode, it needs to also be able to stop on ':' or '/'
     3611 * for ${var:N[:M]} and ${var/P[/R]} parsing.
     3612 */
     3613#define DOUBLE_CLOSE_CHAR_FLAG 0x80
     3614static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsigned end_ch)
     3615{
     3616    int ch;
     3617    char dbl = end_ch & DOUBLE_CLOSE_CHAR_FLAG;
     3618# if ENABLE_HUSH_BASH_COMPAT
     3619    char end_char2 = end_ch >> 8;
     3620# endif
     3621    end_ch &= (DOUBLE_CLOSE_CHAR_FLAG - 1);
     3622
     3623    while (1) {
     3624        ch = i_getch(input);
     3625        if (ch == EOF) {
     3626            syntax_error_unterm_ch(end_ch);
     3627            /*xfunc_die(); - redundant */
     3628        }
     3629        if (ch == end_ch  IF_HUSH_BASH_COMPAT( || ch == end_char2)) {
     3630            if (!dbl)
     3631                break;
     3632            /* we look for closing )) of $((EXPR)) */
     3633            if (i_peek(input) == end_ch) {
     3634                i_getch(input); /* eat second ')' */
     3635                break;
     3636            }
     3637        }
     3638        o_addchr(dest, ch);
     3639        if (ch == '(' || ch == '{') {
     3640            ch = (ch == '(' ? ')' : '}');
     3641            add_till_closing_bracket(dest, input, ch);
     3642            o_addchr(dest, ch);
     3643            continue;
     3644        }
     3645        if (ch == '\'') {
     3646            add_till_single_quote(dest, input);
     3647            o_addchr(dest, ch);
     3648            continue;
     3649        }
     3650        if (ch == '"') {
     3651            add_till_double_quote(dest, input);
     3652            o_addchr(dest, ch);
     3653            continue;
     3654        }
     3655        if (ch == '`') {
     3656            add_till_backquote(dest, input, /*in_dquote:*/ 0);
     3657            o_addchr(dest, ch);
     3658            continue;
     3659        }
     3660        if (ch == '\\') {
     3661            /* \x. Copy verbatim. Important for  \(, \) */
     3662            ch = i_getch(input);
     3663            if (ch == EOF) {
     3664                syntax_error_unterm_ch(')');
     3665                /*xfunc_die(); - redundant */
     3666            }
     3667            o_addchr(dest, ch);
     3668            continue;
     3669        }
     3670    }
     3671    return ch;
     3672}
     3673#endif /* ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_DOLLAR_OPS */
     3674
     3675/* Return code: 0 for OK, 1 for syntax error */
     3676#if BB_MMU
     3677#define parse_dollar(as_string, dest, input, quote_mask) \
     3678    parse_dollar(dest, input, quote_mask)
     3679#define as_string NULL
     3680#endif
     3681static int parse_dollar(o_string *as_string,
     3682        o_string *dest,
     3683        struct in_str *input, unsigned char quote_mask)
     3684{
     3685    int ch = i_peek(input);  /* first character after the $ */
     3686
     3687    debug_printf_parse("parse_dollar entered: ch='%c'\n", ch);
     3688    if (isalpha(ch)) {
     3689        ch = i_getch(input);
     3690        nommu_addchr(as_string, ch);
     3691 make_var:
     3692        o_addchr(dest, SPECIAL_VAR_SYMBOL);
     3693        while (1) {
     3694            debug_printf_parse(": '%c'\n", ch);
     3695            o_addchr(dest, ch | quote_mask);
     3696            quote_mask = 0;
     3697            ch = i_peek(input);
     3698            if (!isalnum(ch) && ch != '_')
     3699                break;
     3700            ch = i_getch(input);
     3701            nommu_addchr(as_string, ch);
     3702        }
     3703        o_addchr(dest, SPECIAL_VAR_SYMBOL);
     3704    } else if (isdigit(ch)) {
     3705 make_one_char_var:
     3706        ch = i_getch(input);
     3707        nommu_addchr(as_string, ch);
     3708        o_addchr(dest, SPECIAL_VAR_SYMBOL);
     3709        debug_printf_parse(": '%c'\n", ch);
     3710        o_addchr(dest, ch | quote_mask);
     3711        o_addchr(dest, SPECIAL_VAR_SYMBOL);
     3712    } else switch (ch) {
     3713    case '$': /* pid */
     3714    case '!': /* last bg pid */
     3715    case '?': /* last exit code */
     3716    case '#': /* number of args */
     3717    case '*': /* args */
     3718    case '@': /* args */
     3719        goto make_one_char_var;
     3720    case '{': {
     3721        o_addchr(dest, SPECIAL_VAR_SYMBOL);
     3722
     3723        ch = i_getch(input); /* eat '{' */
     3724        nommu_addchr(as_string, ch);
     3725
     3726        ch = i_getch(input); /* first char after '{' */
     3727        /* It should be ${?}, or ${#var},
     3728         * or even ${?+subst} - operator acting on a special variable,
     3729         * or the beginning of variable name.
     3730         */
     3731        if (ch == EOF
     3732         || (!strchr(_SPECIAL_VARS_STR, ch) && !isalnum(ch)) /* not one of those */
     3733        ) {
     3734 bad_dollar_syntax:
     3735            syntax_error_unterm_str("${name}");
     3736            debug_printf_parse("parse_dollar return 1: unterminated ${name}\n");
     3737            return 1;
     3738        }
     3739        nommu_addchr(as_string, ch);
     3740        ch |= quote_mask;
     3741
     3742        /* It's possible to just call add_till_closing_bracket() at this point.
     3743         * However, this regresses some of our testsuite cases
     3744         * which check invalid constructs like ${%}.
     3745         * Oh well... let's check that the var name part is fine... */
     3746
     3747        while (1) {
     3748            unsigned pos;
     3749
     3750            o_addchr(dest, ch);
     3751            debug_printf_parse(": '%c'\n", ch);
     3752
     3753            ch = i_getch(input);
     3754            nommu_addchr(as_string, ch);
     3755            if (ch == '}')
     3756                break;
     3757
     3758            if (!isalnum(ch) && ch != '_') {
     3759                unsigned end_ch;
     3760                unsigned char last_ch;
     3761                /* handle parameter expansions
     3762                 * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02
     3763                 */
     3764                if (!strchr(VAR_SUBST_OPS, ch)) /* ${var<bad_char>... */
     3765                    goto bad_dollar_syntax;
     3766
     3767                /* Eat everything until closing '}' (or ':') */
     3768                end_ch = '}';
     3769                if (ENABLE_HUSH_BASH_COMPAT
     3770                 && ch == ':'
     3771                 && !strchr(MINUS_PLUS_EQUAL_QUESTION, i_peek(input))
     3772                ) {
     3773                    /* It's ${var:N[:M]} thing */
     3774                    end_ch = '}' * 0x100 + ':';
     3775                }
     3776                if (ENABLE_HUSH_BASH_COMPAT
     3777                 && ch == '/'
     3778                ) {
     3779                    /* It's ${var/[/]pattern[/repl]} thing */
     3780                    if (i_peek(input) == '/') { /* ${var//pattern[/repl]}? */
     3781                        i_getch(input);
     3782                        nommu_addchr(as_string, '/');
     3783                        ch = '\\';
     3784                    }
     3785                    end_ch = '}' * 0x100 + '/';
     3786                }
     3787                o_addchr(dest, ch);
     3788 again:
     3789                if (!BB_MMU)
     3790                    pos = dest->length;
     3791#if ENABLE_HUSH_DOLLAR_OPS
     3792                last_ch = add_till_closing_bracket(dest, input, end_ch);
     3793#else
     3794#error Simple code to only allow ${var} is not implemented
     3795#endif
     3796                if (as_string) {
     3797                    o_addstr(as_string, dest->data + pos);
     3798                    o_addchr(as_string, last_ch);
     3799                }
     3800
     3801                if (ENABLE_HUSH_BASH_COMPAT && (end_ch & 0xff00)) {
     3802                    /* close the first block: */
     3803                    o_addchr(dest, SPECIAL_VAR_SYMBOL);
     3804                    /* while parsing N from ${var:N[:M]}
     3805                     * or pattern from ${var/[/]pattern[/repl]} */
     3806                    if ((end_ch & 0xff) == last_ch) {
     3807                        /* got ':' or '/'- parse the rest */
     3808                        end_ch = '}';
     3809                        goto again;
     3810                    }
     3811                    /* got '}' */
     3812                    if (end_ch == '}' * 0x100 + ':') {
     3813                        /* it's ${var:N} - emulate :999999999 */
     3814                        o_addstr(dest, "999999999");
     3815                    } /* else: it's ${var/[/]pattern} */
     3816                }
     3817                break;
     3818            }
     3819        }
     3820        o_addchr(dest, SPECIAL_VAR_SYMBOL);
     3821        break;
     3822    }
     3823#if ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_TICK
     3824    case '(': {
     3825        unsigned pos;
     3826
     3827        ch = i_getch(input);
     3828        nommu_addchr(as_string, ch);
     3829# if ENABLE_SH_MATH_SUPPORT
     3830        if (i_peek(input) == '(') {
     3831            ch = i_getch(input);
     3832            nommu_addchr(as_string, ch);
     3833            o_addchr(dest, SPECIAL_VAR_SYMBOL);
     3834            o_addchr(dest, /*quote_mask |*/ '+');
     3835            if (!BB_MMU)
     3836                pos = dest->length;
     3837            add_till_closing_bracket(dest, input, ')' | DOUBLE_CLOSE_CHAR_FLAG);
     3838            if (as_string) {
     3839                o_addstr(as_string, dest->data + pos);
     3840                o_addchr(as_string, ')');
     3841                o_addchr(as_string, ')');
     3842            }
     3843            o_addchr(dest, SPECIAL_VAR_SYMBOL);
     3844            break;
     3845        }
     3846# endif
     3847# if ENABLE_HUSH_TICK
     3848        o_addchr(dest, SPECIAL_VAR_SYMBOL);
     3849        o_addchr(dest, quote_mask | '`');
     3850        if (!BB_MMU)
     3851            pos = dest->length;
     3852        add_till_closing_bracket(dest, input, ')');
     3853        if (as_string) {
     3854            o_addstr(as_string, dest->data + pos);
     3855            o_addchr(as_string, ')');
     3856        }
     3857        o_addchr(dest, SPECIAL_VAR_SYMBOL);
     3858# endif
     3859        break;
     3860    }
     3861#endif
     3862    case '_':
     3863        ch = i_getch(input);
     3864        nommu_addchr(as_string, ch);
     3865        ch = i_peek(input);
     3866        if (isalnum(ch)) { /* it's $_name or $_123 */
     3867            ch = '_';
     3868            goto make_var;
     3869        }
     3870        /* else: it's $_ */
     3871    /* TODO: $_ and $-: */
     3872    /* $_ Shell or shell script name; or last argument of last command
     3873     * (if last command wasn't a pipe; if it was, bash sets $_ to "");
     3874     * but in command's env, set to full pathname used to invoke it */
     3875    /* $- Option flags set by set builtin or shell options (-i etc) */
     3876    default:
     3877        o_addQchr(dest, '$');
     3878    }
     3879    debug_printf_parse("parse_dollar return 0\n");
     3880    return 0;
     3881#undef as_string
     3882}
     3883
     3884#if BB_MMU
     3885# if ENABLE_HUSH_BASH_COMPAT
     3886#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \
     3887    encode_string(dest, input, dquote_end, process_bkslash)
     3888# else
     3889/* only ${var/pattern/repl} (its pattern part) needs additional mode */
     3890#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \
     3891    encode_string(dest, input, dquote_end)
     3892# endif
     3893#define as_string NULL
     3894
     3895#else /* !MMU */
     3896
     3897# if ENABLE_HUSH_BASH_COMPAT
     3898/* all parameters are needed, no macro tricks */
     3899# else
     3900#define encode_string(as_string, dest, input, dquote_end, process_bkslash) \
     3901    encode_string(as_string, dest, input, dquote_end)
     3902# endif
     3903#endif
     3904static int encode_string(o_string *as_string,
     3905        o_string *dest,
     3906        struct in_str *input,
     3907        int dquote_end,
     3908        int process_bkslash)
     3909{
     3910#if !ENABLE_HUSH_BASH_COMPAT
     3911    const int process_bkslash = 1;
     3912#endif
     3913    int ch;
     3914    int next;
     3915
     3916 again:
     3917    ch = i_getch(input);
     3918    if (ch != EOF)
     3919        nommu_addchr(as_string, ch);
     3920    if (ch == dquote_end) { /* may be only '"' or EOF */
     3921        debug_printf_parse("encode_string return 0\n");
     3922        return 0;
     3923    }
     3924    /* note: can't move it above ch == dquote_end check! */
     3925    if (ch == EOF) {
     3926        syntax_error_unterm_ch('"');
     3927        /*xfunc_die(); - redundant */
     3928    }
     3929    next = '\0';
     3930    if (ch != '\n') {
     3931        next = i_peek(input);
     3932    }
     3933    debug_printf_parse("\" ch=%c (%d) escape=%d\n",
     3934            ch, ch, !!(dest->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
     3935    if (process_bkslash && ch == '\\') {
     3936        if (next == EOF) {
     3937            syntax_error("\\<eof>");
     3938            xfunc_die();
     3939        }
     3940        /* bash:
     3941         * "The backslash retains its special meaning [in "..."]
     3942         * only when followed by one of the following characters:
     3943         * $, `, ", \, or <newline>.  A double quote may be quoted
     3944         * within double quotes by preceding it with a backslash."
     3945         * NB: in (unquoted) heredoc, above does not apply to ",
     3946         * therefore we check for it by "next == dquote_end" cond.
     3947         */
     3948        if (next == dquote_end || strchr("$`\\\n", next)) {
     3949            ch = i_getch(input); /* eat next */
     3950            if (ch == '\n')
     3951                goto again; /* skip \<newline> */
     3952        } /* else: ch remains == '\\', and we double it below: */
     3953        o_addqchr(dest, ch); /* \c if c is a glob char, else just c */
     3954        nommu_addchr(as_string, ch);
     3955        goto again;
     3956    }
     3957    if (ch == '$') {
     3958        if (parse_dollar(as_string, dest, input, /*quote_mask:*/ 0x80) != 0) {
     3959            debug_printf_parse("encode_string return 1: "
     3960                    "parse_dollar returned non-0\n");
     3961            return 1;
     3962        }
     3963        goto again;
     3964    }
     3965#if ENABLE_HUSH_TICK
     3966    if (ch == '`') {
     3967        //unsigned pos = dest->length;
     3968        o_addchr(dest, SPECIAL_VAR_SYMBOL);
     3969        o_addchr(dest, 0x80 | '`');
     3970        add_till_backquote(dest, input, /*in_dquote:*/ dquote_end == '"');
     3971        o_addchr(dest, SPECIAL_VAR_SYMBOL);
     3972        //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos);
     3973        goto again;
     3974    }
     3975#endif
     3976    o_addQchr(dest, ch);
     3977    goto again;
     3978#undef as_string
     3979}
     3980
     3981/*
     3982 * Scan input until EOF or end_trigger char.
     3983 * Return a list of pipes to execute, or NULL on EOF
     3984 * or if end_trigger character is met.
     3985 * On syntax error, exit is shell is not interactive,
     3986 * reset parsing machinery and start parsing anew,
     3987 * or return ERR_PTR.
     3988 */
     3989static struct pipe *parse_stream(char **pstring,
     3990        struct in_str *input,
     3991        int end_trigger)
     3992{
     3993    struct parse_context ctx;
     3994    o_string dest = NULL_O_STRING;
     3995    int heredoc_cnt;
     3996
     3997    /* Single-quote triggers a bypass of the main loop until its mate is
     3998     * found.  When recursing, quote state is passed in via dest->o_expflags.
     3999     */
     4000    debug_printf_parse("parse_stream entered, end_trigger='%c'\n",
     4001            end_trigger ? end_trigger : 'X');
     4002    debug_enter();
     4003
     4004    /* If very first arg is "" or '', dest.data may end up NULL.
     4005     * Preventing this: */
     4006    o_addchr(&dest, '\0');
     4007    dest.length = 0;
     4008
     4009    /* We used to separate words on $IFS here. This was wrong.
     4010     * $IFS is used only for word splitting when $var is expanded,
     4011     * here we should use blank chars as separators, not $IFS
     4012     */
     4013
     4014 reset: /* we come back here only on syntax errors in interactive shell */
     4015
     4016#if ENABLE_HUSH_INTERACTIVE
     4017    input->promptmode = 0; /* PS1 */
     4018#endif
     4019    if (MAYBE_ASSIGNMENT != 0)
     4020        dest.o_assignment = MAYBE_ASSIGNMENT;
     4021    initialize_context(&ctx);
     4022    heredoc_cnt = 0;
     4023    while (1) {
     4024        const char *is_blank;
     4025        const char *is_special;
     4026        int ch;
     4027        int next;
     4028        int redir_fd;
     4029        redir_type redir_style;
     4030
     4031        ch = i_getch(input);
     4032        debug_printf_parse(": ch=%c (%d) escape=%d\n",
     4033                ch, ch, !!(dest.o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
     4034        if (ch == EOF) {
     4035            struct pipe *pi;
     4036
     4037            if (heredoc_cnt) {
     4038                syntax_error_unterm_str("here document");
     4039                goto parse_error;
     4040            }
     4041            /* end_trigger == '}' case errors out earlier,
     4042             * checking only ')' */
     4043            if (end_trigger == ')') {
     4044                syntax_error_unterm_ch('('); /* exits */
     4045                /* goto parse_error; */
     4046            }
     4047
     4048            if (done_word(&dest, &ctx)) {
     4049                goto parse_error;
     4050            }
     4051            o_free(&dest);
     4052            done_pipe(&ctx, PIPE_SEQ);
     4053            pi = ctx.list_head;
     4054            /* If we got nothing... */
     4055            /* (this makes bare "&" cmd a no-op.
     4056             * bash says: "syntax error near unexpected token '&'") */
     4057            if (pi->num_cmds == 0
     4058                IF_HAS_KEYWORDS( && pi->res_word == RES_NONE)
     4059            ) {
     4060                free_pipe_list(pi);
     4061                pi = NULL;
     4062            }
     4063#if !BB_MMU
     4064            debug_printf_parse("as_string '%s'\n", ctx.as_string.data);
     4065            if (pstring)
     4066                *pstring = ctx.as_string.data;
     4067            else
     4068                o_free_unsafe(&ctx.as_string);
     4069#endif
     4070            debug_leave();
     4071            debug_printf_parse("parse_stream return %p\n", pi);
     4072            return pi;
     4073        }
     4074        nommu_addchr(&ctx.as_string, ch);
     4075
     4076        next = '\0';
     4077        if (ch != '\n')
     4078            next = i_peek(input);
     4079
     4080        is_special = "{}<>;&|()#'" /* special outside of "str" */
     4081                "\\$\"" IF_HUSH_TICK("`"); /* always special */
     4082        /* Are { and } special here? */
     4083        if (ctx.command->argv /* word [word]{... - non-special */
     4084         || dest.length       /* word{... - non-special */
     4085         || dest.has_quoted_part     /* ""{... - non-special */
     4086         || (next != ';'             /* }; - special */
     4087            && next != ')'           /* }) - special */
     4088            && next != '&'           /* }& and }&& ... - special */
     4089            && next != '|'           /* }|| ... - special */
     4090            && !strchr(defifs, next) /* {word - non-special */
     4091            )
     4092        ) {
     4093            /* They are not special, skip "{}" */
     4094            is_special += 2;
     4095        }
     4096        is_special = strchr(is_special, ch);
     4097        is_blank = strchr(defifs, ch);
     4098
     4099        if (!is_special && !is_blank) { /* ordinary char */
     4100 ordinary_char:
     4101            o_addQchr(&dest, ch);
     4102            if ((dest.o_assignment == MAYBE_ASSIGNMENT
     4103                || dest.o_assignment == WORD_IS_KEYWORD)
     4104             && ch == '='
     4105             && is_well_formed_var_name(dest.data, '=')
     4106            ) {
     4107                dest.o_assignment = DEFINITELY_ASSIGNMENT;
     4108            }
     4109            continue;
     4110        }
     4111
     4112        if (is_blank) {
     4113            if (done_word(&dest, &ctx)) {
     4114                goto parse_error;
     4115            }
     4116            if (ch == '\n') {
     4117                /* Is this a case when newline is simply ignored?
     4118                 * Some examples:
     4119                 * "cmd | <newline> cmd ..."
     4120                 * "case ... in <newline> word) ..."
     4121                 */
     4122                if (IS_NULL_CMD(ctx.command)
     4123                 && dest.length == 0 && !dest.has_quoted_part
     4124                ) {
     4125                    /* This newline can be ignored. But...
     4126                     * Without check #1, interactive shell
     4127                     * ignores even bare <newline>,
     4128                     * and shows the continuation prompt:
     4129                     * ps1_prompt$ <enter>
     4130                     * ps2> _   <=== wrong, should be ps1
     4131                     * Without check #2, "cmd & <newline>"
     4132                     * is similarly mistreated.
     4133                     * (BTW, this makes "cmd & cmd"
     4134                     * and "cmd && cmd" non-orthogonal.
     4135                     * Really, ask yourself, why
     4136                     * "cmd && <newline>" doesn't start
     4137                     * cmd but waits for more input?
     4138                     * No reason...)
     4139                     */
     4140                    struct pipe *pi = ctx.list_head;
     4141                    if (pi->num_cmds != 0       /* check #1 */
     4142                     && pi->followup != PIPE_BG /* check #2 */
     4143                    ) {
     4144                        continue;
     4145                    }
     4146                }
     4147                /* Treat newline as a command separator. */
     4148                done_pipe(&ctx, PIPE_SEQ);
     4149                debug_printf_parse("heredoc_cnt:%d\n", heredoc_cnt);
     4150                if (heredoc_cnt) {
     4151                    if (fetch_heredocs(heredoc_cnt, &ctx, input)) {
     4152                        goto parse_error;
     4153                    }
     4154                    heredoc_cnt = 0;
     4155                }
     4156                dest.o_assignment = MAYBE_ASSIGNMENT;
     4157                ch = ';';
     4158                /* note: if (is_blank) continue;
     4159                 * will still trigger for us */
     4160            }
     4161        }
     4162
     4163        /* "cmd}" or "cmd }..." without semicolon or &:
     4164         * } is an ordinary char in this case, even inside { cmd; }
     4165         * Pathological example: { ""}; } should exec "}" cmd
     4166         */
     4167        if (ch == '}') {
     4168            if (!IS_NULL_CMD(ctx.command) /* cmd } */
     4169             || dest.length != 0 /* word} */
     4170             || dest.has_quoted_part    /* ""} */
     4171            ) {
     4172                goto ordinary_char;
     4173            }
     4174            if (!IS_NULL_PIPE(ctx.pipe)) /* cmd | } */
     4175                goto skip_end_trigger;
     4176            /* else: } does terminate a group */
     4177        }
     4178
     4179        if (end_trigger && end_trigger == ch
     4180         && (ch != ';' || heredoc_cnt == 0)
     4181#if ENABLE_HUSH_CASE
     4182         && (ch != ')'
     4183            || ctx.ctx_res_w != RES_MATCH
     4184            || (!dest.has_quoted_part && strcmp(dest.data, "esac") == 0)
     4185            )
     4186#endif
     4187        ) {
     4188            if (heredoc_cnt) {
     4189                /* This is technically valid:
     4190                 * { cat <<HERE; }; echo Ok
     4191                 * heredoc
     4192                 * heredoc
     4193                 * HERE
     4194                 * but we don't support this.
     4195                 * We require heredoc to be in enclosing {}/(),
     4196                 * if any.
     4197                 */
     4198                syntax_error_unterm_str("here document");
     4199                goto parse_error;
     4200            }
     4201            if (done_word(&dest, &ctx)) {
     4202                goto parse_error;
     4203            }
     4204            done_pipe(&ctx, PIPE_SEQ);
     4205            dest.o_assignment = MAYBE_ASSIGNMENT;
     4206            /* Do we sit outside of any if's, loops or case's? */
     4207            if (!HAS_KEYWORDS
     4208             IF_HAS_KEYWORDS(|| (ctx.ctx_res_w == RES_NONE && ctx.old_flag == 0))
     4209            ) {
     4210                o_free(&dest);
     4211#if !BB_MMU
     4212                debug_printf_parse("as_string '%s'\n", ctx.as_string.data);
     4213                if (pstring)
     4214                    *pstring = ctx.as_string.data;
     4215                else
     4216                    o_free_unsafe(&ctx.as_string);
     4217#endif
     4218                debug_leave();
     4219                debug_printf_parse("parse_stream return %p: "
     4220                        "end_trigger char found\n",
     4221                        ctx.list_head);
     4222                return ctx.list_head;
     4223            }
     4224        }
     4225 skip_end_trigger:
     4226        if (is_blank)
     4227            continue;
     4228
     4229        /* Catch <, > before deciding whether this word is
     4230         * an assignment. a=1 2>z b=2: b=2 is still assignment */
     4231        switch (ch) {
     4232        case '>':
     4233            redir_fd = redirect_opt_num(&dest);
     4234            if (done_word(&dest, &ctx)) {
     4235                goto parse_error;
     4236            }
     4237            redir_style = REDIRECT_OVERWRITE;
     4238            if (next == '>') {
     4239                redir_style = REDIRECT_APPEND;
     4240                ch = i_getch(input);
     4241                nommu_addchr(&ctx.as_string, ch);
     4242            }
     4243#if 0
     4244            else if (next == '(') {
     4245                syntax_error(">(process) not supported");
     4246                goto parse_error;
     4247            }
     4248#endif
     4249            if (parse_redirect(&ctx, redir_fd, redir_style, input))
     4250                goto parse_error;
     4251            continue; /* back to top of while (1) */
     4252        case '<':
     4253            redir_fd = redirect_opt_num(&dest);
     4254            if (done_word(&dest, &ctx)) {
     4255                goto parse_error;
     4256            }
     4257            redir_style = REDIRECT_INPUT;
     4258            if (next == '<') {
     4259                redir_style = REDIRECT_HEREDOC;
     4260                heredoc_cnt++;
     4261                debug_printf_parse("++heredoc_cnt=%d\n", heredoc_cnt);
     4262                ch = i_getch(input);
     4263                nommu_addchr(&ctx.as_string, ch);
     4264            } else if (next == '>') {
     4265                redir_style = REDIRECT_IO;
     4266                ch = i_getch(input);
     4267                nommu_addchr(&ctx.as_string, ch);
     4268            }
     4269#if 0
     4270            else if (next == '(') {
     4271                syntax_error("<(process) not supported");
     4272                goto parse_error;
     4273            }
     4274#endif
     4275            if (parse_redirect(&ctx, redir_fd, redir_style, input))
     4276                goto parse_error;
     4277            continue; /* back to top of while (1) */
     4278        case '#':
     4279            if (dest.length == 0 && !dest.has_quoted_part) {
     4280                /* skip "#comment" */
     4281                while (1) {
     4282                    ch = i_peek(input);
     4283                    if (ch == EOF || ch == '\n')
     4284                        break;
     4285                    i_getch(input);
     4286                    /* note: we do not add it to &ctx.as_string */
     4287                }
     4288                nommu_addchr(&ctx.as_string, '\n');
     4289                continue; /* back to top of while (1) */
     4290            }
     4291            break;
     4292        case '\\':
     4293            if (next == '\n') {
     4294                /* It's "\<newline>" */
     4295#if !BB_MMU
     4296                /* Remove trailing '\' from ctx.as_string */
     4297                ctx.as_string.data[--ctx.as_string.length] = '\0';
     4298#endif
     4299                ch = i_getch(input); /* eat it */
     4300                continue; /* back to top of while (1) */
     4301            }
     4302            break;
     4303        }
     4304
     4305        if (dest.o_assignment == MAYBE_ASSIGNMENT
     4306         /* check that we are not in word in "a=1 2>word b=1": */
     4307         && !ctx.pending_redirect
     4308        ) {
     4309            /* ch is a special char and thus this word
     4310             * cannot be an assignment */
     4311            dest.o_assignment = NOT_ASSIGNMENT;
     4312        }
     4313
     4314        /* Note: nommu_addchr(&ctx.as_string, ch) is already done */
     4315
     4316        switch (ch) {
     4317        case '#': /* non-comment #: "echo a#b" etc */
     4318            o_addQchr(&dest, ch);
     4319            break;
     4320        case '\\':
     4321            if (next == EOF) {
     4322                syntax_error("\\<eof>");
     4323                xfunc_die();
     4324            }
     4325            ch = i_getch(input);
     4326            /* note: ch != '\n' (that case does not reach this place) */
     4327            o_addchr(&dest, '\\');
     4328            /*nommu_addchr(&ctx.as_string, '\\'); - already done */
     4329            o_addchr(&dest, ch);
     4330            nommu_addchr(&ctx.as_string, ch);
     4331            /* Example: echo Hello \2>file
     4332             * we need to know that word 2 is quoted */
     4333            dest.has_quoted_part = 1;
     4334            break;
     4335        case '$':
     4336            if (parse_dollar(&ctx.as_string, &dest, input, /*quote_mask:*/ 0) != 0) {
     4337                debug_printf_parse("parse_stream parse error: "
     4338                    "parse_dollar returned non-0\n");
     4339                goto parse_error;
     4340            }
     4341            break;
     4342        case '\'':
     4343            dest.has_quoted_part = 1;
     4344            while (1) {
     4345                ch = i_getch(input);
     4346                if (ch == EOF) {
     4347                    syntax_error_unterm_ch('\'');
     4348                    /*xfunc_die(); - redundant */
     4349                }
     4350                nommu_addchr(&ctx.as_string, ch);
     4351                if (ch == '\'')
     4352                    break;
     4353                o_addqchr(&dest, ch);
     4354            }
     4355            break;
     4356        case '"':
     4357            dest.has_quoted_part = 1;
     4358            if (dest.o_assignment == NOT_ASSIGNMENT)
     4359                dest.o_expflags |= EXP_FLAG_ESC_GLOB_CHARS;
     4360            if (encode_string(&ctx.as_string, &dest, input, '"', /*process_bkslash:*/ 1))
     4361                goto parse_error;
     4362            dest.o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS;
     4363            break;
     4364#if ENABLE_HUSH_TICK
     4365        case '`': {
     4366            unsigned pos;
     4367
     4368            o_addchr(&dest, SPECIAL_VAR_SYMBOL);
     4369            o_addchr(&dest, '`');
     4370            pos = dest.length;
     4371            add_till_backquote(&dest, input, /*in_dquote:*/ 0);
     4372# if !BB_MMU
     4373            o_addstr(&ctx.as_string, dest.data + pos);
     4374            o_addchr(&ctx.as_string, '`');
     4375# endif
     4376            o_addchr(&dest, SPECIAL_VAR_SYMBOL);
     4377            //debug_printf_subst("SUBST RES3 '%s'\n", dest.data + pos);
     4378            break;
     4379        }
     4380#endif
     4381        case ';':
     4382#if ENABLE_HUSH_CASE
     4383 case_semi:
     4384#endif
     4385            if (done_word(&dest, &ctx)) {
     4386                goto parse_error;
     4387            }
     4388            done_pipe(&ctx, PIPE_SEQ);
     4389#if ENABLE_HUSH_CASE
     4390            /* Eat multiple semicolons, detect
     4391             * whether it means something special */
     4392            while (1) {
     4393                ch = i_peek(input);
     4394                if (ch != ';')
     4395                    break;
     4396                ch = i_getch(input);
     4397                nommu_addchr(&ctx.as_string, ch);
     4398                if (ctx.ctx_res_w == RES_CASE_BODY) {
     4399                    ctx.ctx_dsemicolon = 1;
     4400                    ctx.ctx_res_w = RES_MATCH;
     4401                    break;
     4402                }
     4403            }
     4404#endif
     4405 new_cmd:
     4406            /* We just finished a cmd. New one may start
     4407             * with an assignment */
     4408            dest.o_assignment = MAYBE_ASSIGNMENT;
     4409            break;
     4410        case '&':
     4411            if (done_word(&dest, &ctx)) {
     4412                goto parse_error;
     4413            }
     4414            if (next == '&') {
     4415                ch = i_getch(input);
     4416                nommu_addchr(&ctx.as_string, ch);
     4417                done_pipe(&ctx, PIPE_AND);
     4418            } else {
     4419                done_pipe(&ctx, PIPE_BG);
     4420            }
     4421            goto new_cmd;
     4422        case '|':
     4423            if (done_word(&dest, &ctx)) {
     4424                goto parse_error;
     4425            }
     4426#if ENABLE_HUSH_CASE
     4427            if (ctx.ctx_res_w == RES_MATCH)
     4428                break; /* we are in case's "word | word)" */
     4429#endif
     4430            if (next == '|') { /* || */
     4431                ch = i_getch(input);
     4432                nommu_addchr(&ctx.as_string, ch);
     4433                done_pipe(&ctx, PIPE_OR);
     4434            } else {
     4435                /* we could pick up a file descriptor choice here
     4436                 * with redirect_opt_num(), but bash doesn't do it.
     4437                 * "echo foo 2| cat" yields "foo 2". */
     4438                done_command(&ctx);
     4439#if !BB_MMU
     4440                o_reset_to_empty_unquoted(&ctx.as_string);
     4441#endif
     4442            }
     4443            goto new_cmd;
     4444        case '(':
     4445#if ENABLE_HUSH_CASE
     4446            /* "case... in [(]word)..." - skip '(' */
     4447            if (ctx.ctx_res_w == RES_MATCH
     4448             && ctx.command->argv == NULL /* not (word|(... */
     4449             && dest.length == 0 /* not word(... */
     4450             && dest.has_quoted_part == 0 /* not ""(... */
     4451            ) {
     4452                continue;
     4453            }
     4454#endif
     4455        case '{':
     4456            if (parse_group(&dest, &ctx, input, ch) != 0) {
     4457                goto parse_error;
     4458            }
     4459            goto new_cmd;
     4460        case ')':
     4461#if ENABLE_HUSH_CASE
     4462            if (ctx.ctx_res_w == RES_MATCH)
     4463                goto case_semi;
     4464#endif
     4465        case '}':
     4466            /* proper use of this character is caught by end_trigger:
     4467             * if we see {, we call parse_group(..., end_trigger='}')
     4468             * and it will match } earlier (not here). */
     4469            syntax_error_unexpected_ch(ch);
     4470            goto parse_error;
     4471        default:
     4472            if (HUSH_DEBUG)
     4473                bb_error_msg_and_die("BUG: unexpected %c\n", ch);
     4474        }
     4475    } /* while (1) */
     4476
     4477 parse_error:
     4478    {
     4479        struct parse_context *pctx;
     4480        IF_HAS_KEYWORDS(struct parse_context *p2;)
     4481
     4482        /* Clean up allocated tree.
     4483         * Sample for finding leaks on syntax error recovery path.
     4484         * Run it from interactive shell, watch pmap `pidof hush`.
     4485         * while if false; then false; fi; do break; fi
     4486         * Samples to catch leaks at execution:
     4487         * while if (true | {true;}); then echo ok; fi; do break; done
     4488         * while if (true | {true;}); then echo ok; fi; do (if echo ok; break; then :; fi) | cat; break; done
     4489         */
     4490        pctx = &ctx;
     4491        do {
     4492            /* Update pipe/command counts,
     4493             * otherwise freeing may miss some */
     4494            done_pipe(pctx, PIPE_SEQ);
     4495            debug_printf_clean("freeing list %p from ctx %p\n",
     4496                    pctx->list_head, pctx);
     4497            debug_print_tree(pctx->list_head, 0);
     4498            free_pipe_list(pctx->list_head);
     4499            debug_printf_clean("freed list %p\n", pctx->list_head);
     4500#if !BB_MMU
     4501            o_free_unsafe(&pctx->as_string);
     4502#endif
     4503            IF_HAS_KEYWORDS(p2 = pctx->stack;)
     4504            if (pctx != &ctx) {
     4505                free(pctx);
     4506            }
     4507            IF_HAS_KEYWORDS(pctx = p2;)
     4508        } while (HAS_KEYWORDS && pctx);
     4509        /* Free text, clear all dest fields */
     4510        o_free(&dest);
     4511        /* If we are not in top-level parse, we return,
     4512         * our caller will propagate error.
     4513         */
     4514        if (end_trigger != ';') {
     4515#if !BB_MMU
     4516            if (pstring)
     4517                *pstring = NULL;
     4518#endif
     4519            debug_leave();
     4520            return ERR_PTR;
     4521        }
     4522        /* Discard cached input, force prompt */
     4523        input->p = NULL;
     4524        IF_HUSH_INTERACTIVE(input->promptme = 1;)
     4525        goto reset;
     4526    }
     4527}
     4528
     4529
     4530/*** Execution routines ***/
     4531
     4532/* Expansion can recurse, need forward decls: */
     4533#if !ENABLE_HUSH_BASH_COMPAT
     4534/* only ${var/pattern/repl} (its pattern part) needs additional mode */
     4535#define expand_string_to_string(str, do_unbackslash) \
     4536    expand_string_to_string(str)
     4537#endif
     4538static char *expand_string_to_string(const char *str, int do_unbackslash);
     4539#if ENABLE_HUSH_TICK
     4540static int process_command_subs(o_string *dest, const char *s);
     4541#endif
     4542
     4543/* expand_strvec_to_strvec() takes a list of strings, expands
     4544 * all variable references within and returns a pointer to
     4545 * a list of expanded strings, possibly with larger number
     4546 * of strings. (Think VAR="a b"; echo $VAR).
     4547 * This new list is allocated as a single malloc block.
     4548 * NULL-terminated list of char* pointers is at the beginning of it,
     4549 * followed by strings themselves.
     4550 * Caller can deallocate entire list by single free(list). */
     4551
     4552/* A horde of its helpers come first: */
     4553
     4554static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len)
     4555{
     4556    while (--len >= 0) {
     4557        char c = *str++;
     4558
     4559#if ENABLE_HUSH_BRACE_EXPANSION
     4560        if (c == '{' || c == '}') {
     4561            /* { -> \{, } -> \} */
     4562            o_addchr(o, '\\');
     4563            /* And now we want to add { or } and continue:
     4564             *  o_addchr(o, c);
     4565             *  continue;
     4566             * luckily, just falling throught achieves this.
     4567             */
     4568        }
     4569#endif
     4570        o_addchr(o, c);
     4571        if (c == '\\') {
     4572            /* \z -> \\\z; \<eol> -> \\<eol> */
     4573            o_addchr(o, '\\');
     4574            if (len) {
     4575                len--;
     4576                o_addchr(o, '\\');
     4577                o_addchr(o, *str++);
     4578            }
     4579        }
     4580    }
     4581}
     4582
     4583/* Store given string, finalizing the word and starting new one whenever
     4584 * we encounter IFS char(s). This is used for expanding variable values.
     4585 * End-of-string does NOT finalize word: think about 'echo -$VAR-' */
     4586static int expand_on_ifs(o_string *output, int n, const char *str)
     4587{
     4588    while (1) {
     4589        int word_len = strcspn(str, G.ifs);
     4590        if (word_len) {
     4591            if (!(output->o_expflags & EXP_FLAG_GLOB)) {
     4592                o_addblock(output, str, word_len);
     4593            } else {
     4594                /* Protect backslashes against globbing up :)
     4595                 * Example: "v='\*'; echo b$v" prints "b\*"
     4596                 * (and does not try to glob on "*")
     4597                 */
     4598                o_addblock_duplicate_backslash(output, str, word_len);
     4599                /*/ Why can't we do it easier? */
     4600                /*o_addblock(output, str, word_len); - WRONG: "v='\*'; echo Z$v" prints "Z*" instead of "Z\*" */
     4601                /*o_addqblock(output, str, word_len); - WRONG: "v='*'; echo Z$v" prints "Z*" instead of Z* files */
     4602            }
     4603            str += word_len;
     4604        }
     4605        if (!*str)  /* EOL - do not finalize word */
     4606            break;
     4607        o_addchr(output, '\0');
     4608        debug_print_list("expand_on_ifs", output, n);
     4609        n = o_save_ptr(output, n);
     4610        str += strspn(str, G.ifs); /* skip ifs chars */
     4611    }
     4612    debug_print_list("expand_on_ifs[1]", output, n);
     4613    return n;
     4614}
     4615
     4616/* Helper to expand $((...)) and heredoc body. These act as if
     4617 * they are in double quotes, with the exception that they are not :).
     4618 * Just the rules are similar: "expand only $var and `cmd`"
     4619 *
     4620 * Returns malloced string.
     4621 * As an optimization, we return NULL if expansion is not needed.
     4622 */
     4623#if !ENABLE_HUSH_BASH_COMPAT
     4624/* only ${var/pattern/repl} (its pattern part) needs additional mode */
     4625#define encode_then_expand_string(str, process_bkslash, do_unbackslash) \
     4626    encode_then_expand_string(str)
     4627#endif
     4628static char *encode_then_expand_string(const char *str, int process_bkslash, int do_unbackslash)
     4629{
     4630    char *exp_str;
     4631    struct in_str input;
     4632    o_string dest = NULL_O_STRING;
     4633
     4634    if (!strchr(str, '$')
     4635     && !strchr(str, '\\')
     4636#if ENABLE_HUSH_TICK
     4637     && !strchr(str, '`')
     4638#endif
     4639    ) {
     4640        return NULL;
     4641    }
     4642
     4643    /* We need to expand. Example:
     4644     * echo $(($a + `echo 1`)) $((1 + $((2)) ))
     4645     */
     4646    setup_string_in_str(&input, str);
     4647    encode_string(NULL, &dest, &input, EOF, process_bkslash);
     4648    //bb_error_msg("'%s' -> '%s'", str, dest.data);
     4649    exp_str = expand_string_to_string(dest.data, /*unbackslash:*/ do_unbackslash);
     4650    //bb_error_msg("'%s' -> '%s'", dest.data, exp_str);
     4651    o_free_unsafe(&dest);
     4652    return exp_str;
     4653}
     4654
     4655#if ENABLE_SH_MATH_SUPPORT
     4656static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p)
     4657{
     4658    arith_state_t math_state;
     4659    arith_t res;
     4660    char *exp_str;
     4661
     4662    math_state.lookupvar = get_local_var_value;
     4663    math_state.setvar = set_local_var_from_halves;
     4664    //math_state.endofname = endofname;
     4665    exp_str = encode_then_expand_string(arg, /*process_bkslash:*/ 1, /*unbackslash:*/ 1);
     4666    res = arith(&math_state, exp_str ? exp_str : arg);
     4667    free(exp_str);
     4668    if (errmsg_p)
     4669        *errmsg_p = math_state.errmsg;
     4670    if (math_state.errmsg)
     4671        die_if_script(math_state.errmsg);
     4672    return res;
     4673}
     4674#endif
     4675
     4676#if ENABLE_HUSH_BASH_COMPAT
     4677/* ${var/[/]pattern[/repl]} helpers */
     4678static char *strstr_pattern(char *val, const char *pattern, int *size)
     4679{
     4680    while (1) {
     4681        char *end = scan_and_match(val, pattern, SCAN_MOVE_FROM_RIGHT + SCAN_MATCH_LEFT_HALF);
     4682        debug_printf_varexp("val:'%s' pattern:'%s' end:'%s'\n", val, pattern, end);
     4683        if (end) {
     4684            *size = end - val;
     4685            return val;
     4686        }
     4687        if (*val == '\0')
     4688            return NULL;
     4689        /* Optimization: if "*pat" did not match the start of "string",
     4690         * we know that "tring", "ring" etc will not match too:
     4691         */
     4692        if (pattern[0] == '*')
     4693            return NULL;
     4694        val++;
     4695    }
     4696}
     4697static char *replace_pattern(char *val, const char *pattern, const char *repl, char exp_op)
     4698{
     4699    char *result = NULL;
     4700    unsigned res_len = 0;
     4701    unsigned repl_len = strlen(repl);
     4702
     4703    while (1) {
     4704        int size;
     4705        char *s = strstr_pattern(val, pattern, &size);
     4706        if (!s)
     4707            break;
     4708
     4709        result = xrealloc(result, res_len + (s - val) + repl_len + 1);
     4710        memcpy(result + res_len, val, s - val);
     4711        res_len += s - val;
     4712        strcpy(result + res_len, repl);
     4713        res_len += repl_len;
     4714        debug_printf_varexp("val:'%s' s:'%s' result:'%s'\n", val, s, result);
     4715
     4716        val = s + size;
     4717        if (exp_op == '/')
     4718            break;
     4719    }
     4720    if (val[0] && result) {
     4721        result = xrealloc(result, res_len + strlen(val) + 1);
     4722        strcpy(result + res_len, val);
     4723        debug_printf_varexp("val:'%s' result:'%s'\n", val, result);
     4724    }
     4725    debug_printf_varexp("result:'%s'\n", result);
     4726    return result;
     4727}
     4728#endif
     4729
     4730/* Helper:
     4731 * Handles <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct.
     4732 */
     4733static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, char **pp)
     4734{
     4735    const char *val = NULL;
     4736    char *to_be_freed = NULL;
     4737    char *p = *pp;
     4738    char *var;
     4739    char first_char;
     4740    char exp_op;
     4741    char exp_save = exp_save; /* for compiler */
     4742    char *exp_saveptr; /* points to expansion operator */
     4743    char *exp_word = exp_word; /* for compiler */
     4744    char arg0;
     4745
     4746    *p = '\0'; /* replace trailing SPECIAL_VAR_SYMBOL */
     4747    var = arg;
     4748    exp_saveptr = arg[1] ? strchr(VAR_ENCODED_SUBST_OPS, arg[1]) : NULL;
     4749    arg0 = arg[0];
     4750    first_char = arg[0] = arg0 & 0x7f;
     4751    exp_op = 0;
     4752
     4753    if (first_char == '#'      /* ${#... */
     4754     && arg[1] && !exp_saveptr /* not ${#} and not ${#<op_char>...} */
     4755    ) {
     4756        /* It must be length operator: ${#var} */
     4757        var++;
     4758        exp_op = 'L';
     4759    } else {
     4760        /* Maybe handle parameter expansion */
     4761        if (exp_saveptr /* if 2nd char is one of expansion operators */
     4762         && strchr(NUMERIC_SPECVARS_STR, first_char) /* 1st char is special variable */
     4763        ) {
     4764            /* ${?:0}, ${#[:]%0} etc */
     4765            exp_saveptr = var + 1;
     4766        } else {
     4767            /* ${?}, ${var}, ${var:0}, ${var[:]%0} etc */
     4768            exp_saveptr = var+1 + strcspn(var+1, VAR_ENCODED_SUBST_OPS);
     4769        }
     4770        exp_op = exp_save = *exp_saveptr;
     4771        if (exp_op) {
     4772            exp_word = exp_saveptr + 1;
     4773            if (exp_op == ':') {
     4774                exp_op = *exp_word++;
     4775//TODO: try ${var:} and ${var:bogus} in non-bash config
     4776                if (ENABLE_HUSH_BASH_COMPAT
     4777                 && (!exp_op || !strchr(MINUS_PLUS_EQUAL_QUESTION, exp_op))
     4778                ) {
     4779                    /* oops... it's ${var:N[:M]}, not ${var:?xxx} or some such */
     4780                    exp_op = ':';
     4781                    exp_word--;
     4782                }
     4783            }
     4784            *exp_saveptr = '\0';
     4785        } /* else: it's not an expansion op, but bare ${var} */
     4786    }
     4787
     4788    /* Look up the variable in question */
     4789    if (isdigit(var[0])) {
     4790        /* parse_dollar should have vetted var for us */
     4791        int n = xatoi_positive(var);
     4792        if (n < G.global_argc)
     4793            val = G.global_argv[n];
     4794        /* else val remains NULL: $N with too big N */
     4795    } else {
     4796        switch (var[0]) {
     4797        case '$': /* pid */
     4798            val = utoa(G.root_pid);
     4799            break;
     4800        case '!': /* bg pid */
     4801            val = G.last_bg_pid ? utoa(G.last_bg_pid) : "";
     4802            break;
     4803        case '?': /* exitcode */
     4804            val = utoa(G.last_exitcode);
     4805            break;
     4806        case '#': /* argc */
     4807            val = utoa(G.global_argc ? G.global_argc-1 : 0);
     4808            break;
     4809        default:
     4810            val = get_local_var_value(var);
     4811        }
     4812    }
     4813
     4814    /* Handle any expansions */
     4815    if (exp_op == 'L') {
     4816        debug_printf_expand("expand: length(%s)=", val);
     4817        val = utoa(val ? strlen(val) : 0);
     4818        debug_printf_expand("%s\n", val);
     4819    } else if (exp_op) {
     4820        if (exp_op == '%' || exp_op == '#') {
     4821            /* Standard-mandated substring removal ops:
     4822             * ${parameter%word} - remove smallest suffix pattern
     4823             * ${parameter%%word} - remove largest suffix pattern
     4824             * ${parameter#word} - remove smallest prefix pattern
     4825             * ${parameter##word} - remove largest prefix pattern
     4826             *
     4827             * Word is expanded to produce a glob pattern.
     4828             * Then var's value is matched to it and matching part removed.
     4829             */
     4830            if (val && val[0]) {
     4831                char *t;
     4832                char *exp_exp_word;
     4833                char *loc;
     4834                unsigned scan_flags = pick_scan(exp_op, *exp_word);
     4835                if (exp_op == *exp_word)  /* ## or %% */
     4836                    exp_word++;
     4837                exp_exp_word = encode_then_expand_string(exp_word, /*process_bkslash:*/ 1, /*unbackslash:*/ 1);
     4838                if (exp_exp_word)
     4839                    exp_word = exp_exp_word;
     4840                /* HACK ALERT. We depend here on the fact that
     4841                 * G.global_argv and results of utoa and get_local_var_value
     4842                 * are actually in writable memory:
     4843                 * scan_and_match momentarily stores NULs there. */
     4844                t = (char*)val;
     4845                loc = scan_and_match(t, exp_word, scan_flags);
     4846                //bb_error_msg("op:%c str:'%s' pat:'%s' res:'%s'",
     4847                //      exp_op, t, exp_word, loc);
     4848                free(exp_exp_word);
     4849                if (loc) { /* match was found */
     4850                    if (scan_flags & SCAN_MATCH_LEFT_HALF) /* #[#] */
     4851                        val = loc; /* take right part */
     4852                    else /* %[%] */
     4853                        val = to_be_freed = xstrndup(val, loc - val); /* left */
     4854                }
     4855            }
     4856        }
     4857#if ENABLE_HUSH_BASH_COMPAT
     4858        else if (exp_op == '/' || exp_op == '\\') {
     4859            /* It's ${var/[/]pattern[/repl]} thing.
     4860             * Note that in encoded form it has TWO parts:
     4861             * var/pattern<SPECIAL_VAR_SYMBOL>repl<SPECIAL_VAR_SYMBOL>
     4862             * and if // is used, it is encoded as \:
     4863             * var\pattern<SPECIAL_VAR_SYMBOL>repl<SPECIAL_VAR_SYMBOL>
     4864             */
     4865            /* Empty variable always gives nothing: */
     4866            // "v=''; echo ${v/*/w}" prints "", not "w"
     4867            if (val && val[0]) {
     4868                /* pattern uses non-standard expansion.
     4869                 * repl should be unbackslashed and globbed
     4870                 * by the usual expansion rules:
     4871                 * >az; >bz;
     4872                 * v='a bz'; echo "${v/a*z/a*z}" prints "a*z"
     4873                 * v='a bz'; echo "${v/a*z/\z}"  prints "\z"
     4874                 * v='a bz'; echo ${v/a*z/a*z}   prints "az"
     4875                 * v='a bz'; echo ${v/a*z/\z}    prints "z"
     4876                 * (note that a*z _pattern_ is never globbed!)
     4877                 */
     4878                char *pattern, *repl, *t;
     4879                pattern = encode_then_expand_string(exp_word, /*process_bkslash:*/ 0, /*unbackslash:*/ 0);
     4880                if (!pattern)
     4881                    pattern = xstrdup(exp_word);
     4882                debug_printf_varexp("pattern:'%s'->'%s'\n", exp_word, pattern);
     4883                *p++ = SPECIAL_VAR_SYMBOL;
     4884                exp_word = p;
     4885                p = strchr(p, SPECIAL_VAR_SYMBOL);
     4886                *p = '\0';
     4887                repl = encode_then_expand_string(exp_word, /*process_bkslash:*/ arg0 & 0x80, /*unbackslash:*/ 1);
     4888                debug_printf_varexp("repl:'%s'->'%s'\n", exp_word, repl);
     4889                /* HACK ALERT. We depend here on the fact that
     4890                 * G.global_argv and results of utoa and get_local_var_value
     4891                 * are actually in writable memory:
     4892                 * replace_pattern momentarily stores NULs there. */
     4893                t = (char*)val;
     4894                to_be_freed = replace_pattern(t,
     4895                        pattern,
     4896                        (repl ? repl : exp_word),
     4897                        exp_op);
     4898                if (to_be_freed) /* at least one replace happened */
     4899                    val = to_be_freed;
     4900                free(pattern);
     4901                free(repl);
     4902            }
     4903        }
     4904#endif
     4905        else if (exp_op == ':') {
     4906#if ENABLE_HUSH_BASH_COMPAT && ENABLE_SH_MATH_SUPPORT
     4907            /* It's ${var:N[:M]} bashism.
     4908             * Note that in encoded form it has TWO parts:
     4909             * var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL>
     4910             */
     4911            arith_t beg, len;
     4912            const char *errmsg;
     4913
     4914            beg = expand_and_evaluate_arith(exp_word, &errmsg);
     4915            if (errmsg)
     4916                goto arith_err;
     4917            debug_printf_varexp("beg:'%s'=%lld\n", exp_word, (long long)beg);
     4918            *p++ = SPECIAL_VAR_SYMBOL;
     4919            exp_word = p;
     4920            p = strchr(p, SPECIAL_VAR_SYMBOL);
     4921            *p = '\0';
     4922            len = expand_and_evaluate_arith(exp_word, &errmsg);
     4923            if (errmsg)
     4924                goto arith_err;
     4925            debug_printf_varexp("len:'%s'=%lld\n", exp_word, (long long)len);
     4926            if (len >= 0) { /* bash compat: len < 0 is illegal */
     4927                if (beg < 0) /* bash compat */
     4928                    beg = 0;
     4929                debug_printf_varexp("from val:'%s'\n", val);
     4930                if (len == 0 || !val || beg >= strlen(val)) {
     4931 arith_err:
     4932                    val = NULL;
     4933                } else {
     4934                    /* Paranoia. What if user entered 9999999999999
     4935                     * which fits in arith_t but not int? */
     4936                    if (len >= INT_MAX)
     4937                        len = INT_MAX;
     4938                    val = to_be_freed = xstrndup(val + beg, len);
     4939                }
     4940                debug_printf_varexp("val:'%s'\n", val);
     4941            } else
     4942#endif
     4943            {
     4944                die_if_script("malformed ${%s:...}", var);
     4945                val = NULL;
     4946            }
     4947        } else { /* one of "-=+?" */
     4948            /* Standard-mandated substitution ops:
     4949             * ${var?word} - indicate error if unset
     4950             *      If var is unset, word (or a message indicating it is unset
     4951             *      if word is null) is written to standard error
     4952             *      and the shell exits with a non-zero exit status.
     4953             *      Otherwise, the value of var is substituted.
     4954             * ${var-word} - use default value
     4955             *      If var is unset, word is substituted.
     4956             * ${var=word} - assign and use default value
     4957             *      If var is unset, word is assigned to var.
     4958             *      In all cases, final value of var is substituted.
     4959             * ${var+word} - use alternative value
     4960             *      If var is unset, null is substituted.
     4961             *      Otherwise, word is substituted.
     4962             *
     4963             * Word is subjected to tilde expansion, parameter expansion,
     4964             * command substitution, and arithmetic expansion.
     4965             * If word is not needed, it is not expanded.
     4966             *
     4967             * Colon forms (${var:-word}, ${var:=word} etc) do the same,
     4968             * but also treat null var as if it is unset.
     4969             */
     4970            int use_word = (!val || ((exp_save == ':') && !val[0]));
     4971            if (exp_op == '+')
     4972                use_word = !use_word;
     4973            debug_printf_expand("expand: op:%c (null:%s) test:%i\n", exp_op,
     4974                    (exp_save == ':') ? "true" : "false", use_word);
     4975            if (use_word) {
     4976                to_be_freed = encode_then_expand_string(exp_word, /*process_bkslash:*/ 1, /*unbackslash:*/ 1);
     4977                if (to_be_freed)
     4978                    exp_word = to_be_freed;
     4979                if (exp_op == '?') {
     4980                    /* mimic bash message */
     4981                    die_if_script("%s: %s",
     4982                        var,
     4983                        exp_word[0] ? exp_word : "parameter null or not set"
     4984                    );
     4985//TODO: how interactive bash aborts expansion mid-command?
     4986                } else {
     4987                    val = exp_word;
     4988                }
     4989
     4990                if (exp_op == '=') {
     4991                    /* ${var=[word]} or ${var:=[word]} */
     4992                    if (isdigit(var[0]) || var[0] == '#') {
     4993                        /* mimic bash message */
     4994                        die_if_script("$%s: cannot assign in this way", var);
     4995                        val = NULL;
     4996                    } else {
     4997                        char *new_var = xasprintf("%s=%s", var, val);
     4998                        set_local_var(new_var, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
     4999                    }
     5000                }
     5001            }
     5002        } /* one of "-=+?" */
     5003
     5004        *exp_saveptr = exp_save;
     5005    } /* if (exp_op) */
     5006
     5007    arg[0] = arg0;
     5008
     5009    *pp = p;
     5010    *to_be_freed_pp = to_be_freed;
     5011    return val;
     5012}
     5013
     5014/* Expand all variable references in given string, adding words to list[]
     5015 * at n, n+1,... positions. Return updated n (so that list[n] is next one
     5016 * to be filled). This routine is extremely tricky: has to deal with
     5017 * variables/parameters with whitespace, $* and $@, and constructs like
     5018 * 'echo -$*-'. If you play here, you must run testsuite afterwards! */
     5019static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
     5020{
     5021    /* output->o_expflags & EXP_FLAG_SINGLEWORD (0x80) if we are in
     5022     * expansion of right-hand side of assignment == 1-element expand.
     5023     */
     5024    char cant_be_null = 0; /* only bit 0x80 matters */
     5025    char *p;
     5026
     5027    debug_printf_expand("expand_vars_to_list: arg:'%s' singleword:%x\n", arg,
     5028            !!(output->o_expflags & EXP_FLAG_SINGLEWORD));
     5029    debug_print_list("expand_vars_to_list", output, n);
     5030    n = o_save_ptr(output, n);
     5031    debug_print_list("expand_vars_to_list[0]", output, n);
     5032
     5033    while ((p = strchr(arg, SPECIAL_VAR_SYMBOL)) != NULL) {
     5034        char first_ch;
     5035        char *to_be_freed = NULL;
     5036        const char *val = NULL;
     5037#if ENABLE_HUSH_TICK
     5038        o_string subst_result = NULL_O_STRING;
     5039#endif
     5040#if ENABLE_SH_MATH_SUPPORT
     5041        char arith_buf[sizeof(arith_t)*3 + 2];
     5042#endif
     5043        o_addblock(output, arg, p - arg);
     5044        debug_print_list("expand_vars_to_list[1]", output, n);
     5045        arg = ++p;
     5046        p = strchr(p, SPECIAL_VAR_SYMBOL);
     5047
     5048        /* Fetch special var name (if it is indeed one of them)
     5049         * and quote bit, force the bit on if singleword expansion -
     5050         * important for not getting v=$@ expand to many words. */
     5051        first_ch = arg[0] | (output->o_expflags & EXP_FLAG_SINGLEWORD);
     5052
     5053        /* Is this variable quoted and thus expansion can't be null?
     5054         * "$@" is special. Even if quoted, it can still
     5055         * expand to nothing (not even an empty string),
     5056         * thus it is excluded. */
     5057        if ((first_ch & 0x7f) != '@')
     5058            cant_be_null |= first_ch;
     5059
     5060        switch (first_ch & 0x7f) {
     5061        /* Highest bit in first_ch indicates that var is double-quoted */
     5062        case '*':
     5063        case '@': {
     5064            int i;
     5065            if (!G.global_argv[1])
     5066                break;
     5067            i = 1;
     5068            cant_be_null |= first_ch; /* do it for "$@" _now_, when we know it's not empty */
     5069            if (!(first_ch & 0x80)) { /* unquoted $* or $@ */
     5070                while (G.global_argv[i]) {
     5071                    n = expand_on_ifs(output, n, G.global_argv[i]);
     5072                    debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, G.global_argc - 1);
     5073                    if (G.global_argv[i++][0] && G.global_argv[i]) {
     5074                        /* this argv[] is not empty and not last:
     5075                         * put terminating NUL, start new word */
     5076                        o_addchr(output, '\0');
     5077                        debug_print_list("expand_vars_to_list[2]", output, n);
     5078                        n = o_save_ptr(output, n);
     5079                        debug_print_list("expand_vars_to_list[3]", output, n);
     5080                    }
     5081                }
     5082            } else
     5083            /* If EXP_FLAG_SINGLEWORD, we handle assignment 'a=....$@.....'
     5084             * and in this case should treat it like '$*' - see 'else...' below */
     5085            if (first_ch == ('@'|0x80)  /* quoted $@ */
     5086             && !(output->o_expflags & EXP_FLAG_SINGLEWORD) /* not v="$@" case */
     5087            ) {
     5088                while (1) {
     5089                    o_addQstr(output, G.global_argv[i]);
     5090                    if (++i >= G.global_argc)
     5091                        break;
     5092                    o_addchr(output, '\0');
     5093                    debug_print_list("expand_vars_to_list[4]", output, n);
     5094                    n = o_save_ptr(output, n);
     5095                }
     5096            } else { /* quoted $* (or v="$@" case): add as one word */
     5097                while (1) {
     5098                    o_addQstr(output, G.global_argv[i]);
     5099                    if (!G.global_argv[++i])
     5100                        break;
     5101                    if (G.ifs[0])
     5102                        o_addchr(output, G.ifs[0]);
     5103                }
     5104            }
     5105            break;
     5106        }
     5107        case SPECIAL_VAR_SYMBOL: /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_SYMBOL> */
     5108            /* "Empty variable", used to make "" etc to not disappear */
     5109            arg++;
     5110            cant_be_null = 0x80;
     5111            break;
     5112#if ENABLE_HUSH_TICK
     5113        case '`': /* <SPECIAL_VAR_SYMBOL>`cmd<SPECIAL_VAR_SYMBOL> */
     5114            *p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */
     5115            arg++;
     5116            /* Can't just stuff it into output o_string,
     5117             * expanded result may need to be globbed
     5118             * and $IFS-splitted */
     5119            debug_printf_subst("SUBST '%s' first_ch %x\n", arg, first_ch);
     5120            G.last_exitcode = process_command_subs(&subst_result, arg);
     5121            debug_printf_subst("SUBST RES:%d '%s'\n", G.last_exitcode, subst_result.data);
     5122            val = subst_result.data;
     5123            goto store_val;
     5124#endif
     5125#if ENABLE_SH_MATH_SUPPORT
     5126        case '+': { /* <SPECIAL_VAR_SYMBOL>+cmd<SPECIAL_VAR_SYMBOL> */
     5127            arith_t res;
     5128
     5129            arg++; /* skip '+' */
     5130            *p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */
     5131            debug_printf_subst("ARITH '%s' first_ch %x\n", arg, first_ch);
     5132            res = expand_and_evaluate_arith(arg, NULL);
     5133            debug_printf_subst("ARITH RES '"ARITH_FMT"'\n", res);
     5134            sprintf(arith_buf, ARITH_FMT, res);
     5135            val = arith_buf;
     5136            break;
     5137        }
     5138#endif
     5139        default:
     5140            val = expand_one_var(&to_be_freed, arg, &p);
     5141 IF_HUSH_TICK(store_val:)
     5142            if (!(first_ch & 0x80)) { /* unquoted $VAR */
     5143                debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val,
     5144                        !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
     5145                if (val && val[0]) {
     5146                    n = expand_on_ifs(output, n, val);
     5147                    val = NULL;
     5148                }
     5149            } else { /* quoted $VAR, val will be appended below */
     5150                debug_printf_expand("quoted '%s', output->o_escape:%d\n", val,
     5151                        !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
     5152            }
     5153            break;
     5154
     5155        } /* switch (char after <SPECIAL_VAR_SYMBOL>) */
     5156
     5157        if (val && val[0]) {
     5158            o_addQstr(output, val);
     5159        }
     5160        free(to_be_freed);
     5161
     5162        /* Restore NULL'ed SPECIAL_VAR_SYMBOL.
     5163         * Do the check to avoid writing to a const string. */
     5164        if (*p != SPECIAL_VAR_SYMBOL)
     5165            *p = SPECIAL_VAR_SYMBOL;
     5166
     5167#if ENABLE_HUSH_TICK
     5168        o_free(&subst_result);
     5169#endif
     5170        arg = ++p;
     5171    } /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */
     5172
     5173    if (arg[0]) {
     5174        debug_print_list("expand_vars_to_list[a]", output, n);
     5175        /* this part is literal, and it was already pre-quoted
     5176         * if needed (much earlier), do not use o_addQstr here! */
     5177        o_addstr_with_NUL(output, arg);
     5178        debug_print_list("expand_vars_to_list[b]", output, n);
     5179    } else if (output->length == o_get_last_ptr(output, n) /* expansion is empty */
     5180     && !(cant_be_null & 0x80) /* and all vars were not quoted. */
     5181    ) {
     5182        n--;
     5183        /* allow to reuse list[n] later without re-growth */
     5184        output->has_empty_slot = 1;
     5185    } else {
     5186        o_addchr(output, '\0');
     5187    }
     5188
     5189    return n;
     5190}
     5191
     5192static char **expand_variables(char **argv, unsigned expflags)
     5193{
     5194    int n;
     5195    char **list;
     5196    o_string output = NULL_O_STRING;
     5197
     5198    output.o_expflags = expflags;
     5199
     5200    n = 0;
     5201    while (*argv) {
     5202        n = expand_vars_to_list(&output, n, *argv);
     5203        argv++;
     5204    }
     5205    debug_print_list("expand_variables", &output, n);
     5206
     5207    /* output.data (malloced in one block) gets returned in "list" */
     5208    list = o_finalize_list(&output, n);
     5209    debug_print_strings("expand_variables[1]", list);
     5210    return list;
     5211}
     5212
     5213static char **expand_strvec_to_strvec(char **argv)
     5214{
     5215    return expand_variables(argv, EXP_FLAG_GLOB | EXP_FLAG_ESC_GLOB_CHARS);
     5216}
     5217
     5218#if ENABLE_HUSH_BASH_COMPAT
     5219static char **expand_strvec_to_strvec_singleword_noglob(char **argv)
     5220{
     5221    return expand_variables(argv, EXP_FLAG_SINGLEWORD);
     5222}
     5223#endif
     5224
     5225/* Used for expansion of right hand of assignments,
     5226 * $((...)), heredocs, variable espansion parts.
     5227 *
     5228 * NB: should NOT do globbing!
     5229 * "export v=/bin/c*; env | grep ^v=" outputs "v=/bin/c*"
     5230 */
     5231static char *expand_string_to_string(const char *str, int do_unbackslash)
     5232{
     5233#if !ENABLE_HUSH_BASH_COMPAT
     5234    const int do_unbackslash = 1;
     5235#endif
     5236    char *argv[2], **list;
     5237
     5238    debug_printf_expand("string_to_string<='%s'\n", str);
     5239    /* This is generally an optimization, but it also
     5240     * handles "", which otherwise trips over !list[0] check below.
     5241     * (is this ever happens that we actually get str="" here?)
     5242     */
     5243    if (!strchr(str, SPECIAL_VAR_SYMBOL) && !strchr(str, '\\')) {
     5244        //TODO: Can use on strings with \ too, just unbackslash() them?
     5245        debug_printf_expand("string_to_string(fast)=>'%s'\n", str);
     5246        return xstrdup(str);
     5247    }
     5248
     5249    argv[0] = (char*)str;
     5250    argv[1] = NULL;
     5251    list = expand_variables(argv, do_unbackslash
     5252            ? EXP_FLAG_ESC_GLOB_CHARS | EXP_FLAG_SINGLEWORD
     5253            : EXP_FLAG_SINGLEWORD
     5254    );
     5255    if (HUSH_DEBUG)
     5256        if (!list[0] || list[1])
     5257            bb_error_msg_and_die("BUG in varexp2");
     5258    /* actually, just move string 2*sizeof(char*) bytes back */
     5259    overlapping_strcpy((char*)list, list[0]);
     5260    if (do_unbackslash)
     5261        unbackslash((char*)list);
     5262    debug_printf_expand("string_to_string=>'%s'\n", (char*)list);
     5263    return (char*)list;
     5264}
     5265
     5266/* Used for "eval" builtin */
     5267static char* expand_strvec_to_string(char **argv)
     5268{
     5269    char **list;
     5270
     5271    list = expand_variables(argv, EXP_FLAG_SINGLEWORD);
     5272    /* Convert all NULs to spaces */
     5273    if (list[0]) {
     5274        int n = 1;
     5275        while (list[n]) {
     5276            if (HUSH_DEBUG)
     5277                if (list[n-1] + strlen(list[n-1]) + 1 != list[n])
     5278                    bb_error_msg_and_die("BUG in varexp3");
     5279            /* bash uses ' ' regardless of $IFS contents */
     5280            list[n][-1] = ' ';
     5281            n++;
     5282        }
     5283    }
     5284    overlapping_strcpy((char*)list, list[0]);
     5285    debug_printf_expand("strvec_to_string='%s'\n", (char*)list);
     5286    return (char*)list;
     5287}
     5288
     5289static char **expand_assignments(char **argv, int count)
     5290{
     5291    int i;
     5292    char **p;
     5293
     5294    G.expanded_assignments = p = NULL;
     5295    /* Expand assignments into one string each */
     5296    for (i = 0; i < count; i++) {
     5297        G.expanded_assignments = p = add_string_to_strings(p, expand_string_to_string(argv[i], /*unbackslash:*/ 1));
     5298    }
     5299    G.expanded_assignments = NULL;
     5300    return p;
     5301}
     5302
     5303
     5304#if BB_MMU
     5305/* never called */
     5306void re_execute_shell(char ***to_free, const char *s,
     5307        char *g_argv0, char **g_argv,
     5308        char **builtin_argv) NORETURN;
     5309
     5310static void reset_traps_to_defaults(void)
     5311{
     5312    /* This function is always called in a child shell
     5313     * after fork (not vfork, NOMMU doesn't use this function).
     5314     */
     5315    unsigned sig;
     5316    unsigned mask;
     5317
     5318    /* Child shells are not interactive.
     5319     * SIGTTIN/SIGTTOU/SIGTSTP should not have special handling.
     5320     * Testcase: (while :; do :; done) + ^Z should background.
     5321     * Same goes for SIGTERM, SIGHUP, SIGINT.
     5322     */
     5323    if (!G.traps && !(G.non_DFL_mask & SPECIAL_INTERACTIVE_SIGS))
     5324        return; /* already no traps and no SPECIAL_INTERACTIVE_SIGS */
     5325
     5326    /* Switching off SPECIAL_INTERACTIVE_SIGS.
     5327     * Stupid. It can be done with *single* &= op, but we can't use
     5328     * the fact that G.blocked_set is implemented as a bitmask
     5329     * in libc... */
     5330    mask = (SPECIAL_INTERACTIVE_SIGS >> 1);
     5331    sig = 1;
     5332    while (1) {
     5333        if (mask & 1) {
     5334            /* Careful. Only if no trap or trap is not "" */
     5335            if (!G.traps || !G.traps[sig] || G.traps[sig][0])
     5336                sigdelset(&G.blocked_set, sig);
     5337        }
     5338        mask >>= 1;
     5339        if (!mask)
     5340            break;
     5341        sig++;
     5342    }
     5343    /* Our homegrown sig mask is saner to work with :) */
     5344    G.non_DFL_mask &= ~SPECIAL_INTERACTIVE_SIGS;
     5345
     5346    /* Resetting all traps to default except empty ones */
     5347    mask = G.non_DFL_mask;
     5348    if (G.traps) for (sig = 0; sig < NSIG; sig++, mask >>= 1) {
     5349        if (!G.traps[sig] || !G.traps[sig][0])
     5350            continue;
     5351        free(G.traps[sig]);
     5352        G.traps[sig] = NULL;
     5353        /* There is no signal for 0 (EXIT) */
     5354        if (sig == 0)
     5355            continue;
     5356        /* There was a trap handler, we just removed it.
     5357         * But if sig still has non-DFL handling,
     5358         * we should not unblock the sig. */
     5359        if (mask & 1)
     5360            continue;
     5361        sigdelset(&G.blocked_set, sig);
     5362    }
     5363    sigprocmask(SIG_SETMASK, &G.blocked_set, NULL);
     5364}
     5365
     5366#else /* !BB_MMU */
     5367
     5368static void re_execute_shell(char ***to_free, const char *s,
     5369        char *g_argv0, char **g_argv,
     5370        char **builtin_argv) NORETURN;
     5371static void re_execute_shell(char ***to_free, const char *s,
     5372        char *g_argv0, char **g_argv,
     5373        char **builtin_argv)
     5374{
     5375# define NOMMU_HACK_FMT ("-$%x:%x:%x:%x:%x:%llx" IF_HUSH_LOOPS(":%x"))
     5376    /* delims + 2 * (number of bytes in printed hex numbers) */
     5377    char param_buf[sizeof(NOMMU_HACK_FMT) + 2 * (sizeof(int)*6 + sizeof(long long)*1)];
     5378    char *heredoc_argv[4];
     5379    struct variable *cur;
     5380# if ENABLE_HUSH_FUNCTIONS
     5381    struct function *funcp;
     5382# endif
     5383    char **argv, **pp;
     5384    unsigned cnt;
     5385    unsigned long long empty_trap_mask;
     5386
     5387    if (!g_argv0) { /* heredoc */
     5388        argv = heredoc_argv;
     5389        argv[0] = (char *) G.argv0_for_re_execing;
     5390        argv[1] = (char *) "-<";
     5391        argv[2] = (char *) s;
     5392        argv[3] = NULL;
     5393        pp = &argv[3]; /* used as pointer to empty environment */
     5394        goto do_exec;
     5395    }
     5396
     5397    cnt = 0;
     5398    pp = builtin_argv;
     5399    if (pp) while (*pp++)
     5400        cnt++;
     5401
     5402    empty_trap_mask = 0;
     5403    if (G.traps) {
     5404        int sig;
     5405        for (sig = 1; sig < NSIG; sig++) {
     5406            if (G.traps[sig] && !G.traps[sig][0])
     5407                empty_trap_mask |= 1LL << sig;
     5408        }
     5409    }
     5410
     5411    sprintf(param_buf, NOMMU_HACK_FMT
     5412            , (unsigned) G.root_pid
     5413            , (unsigned) G.root_ppid
     5414            , (unsigned) G.last_bg_pid
     5415            , (unsigned) G.last_exitcode
     5416            , cnt
     5417            , empty_trap_mask
     5418            IF_HUSH_LOOPS(, G.depth_of_loop)
     5419            );
     5420# undef NOMMU_HACK_FMT
     5421    /* 1:hush 2:-$<pid>:<pid>:<exitcode>:<etc...> <vars...> <funcs...>
     5422     * 3:-c 4:<cmd> 5:<arg0> <argN...> 6:NULL
     5423     */
     5424    cnt += 6;
     5425    for (cur = G.top_var; cur; cur = cur->next) {
     5426        if (!cur->flg_export || cur->flg_read_only)
     5427            cnt += 2;
     5428    }
     5429# if ENABLE_HUSH_FUNCTIONS
     5430    for (funcp = G.top_func; funcp; funcp = funcp->next)
     5431        cnt += 3;
     5432# endif
     5433    pp = g_argv;
     5434    while (*pp++)
     5435        cnt++;
     5436    *to_free = argv = pp = xzalloc(sizeof(argv[0]) * cnt);
     5437    *pp++ = (char *) G.argv0_for_re_execing;
     5438    *pp++ = param_buf;
     5439    for (cur = G.top_var; cur; cur = cur->next) {
     5440        if (strcmp(cur->varstr, hush_version_str) == 0)
     5441            continue;
     5442        if (cur->flg_read_only) {
     5443            *pp++ = (char *) "-R";
     5444            *pp++ = cur->varstr;
     5445        } else if (!cur->flg_export) {
     5446            *pp++ = (char *) "-V";
     5447            *pp++ = cur->varstr;
     5448        }
     5449    }
     5450# if ENABLE_HUSH_FUNCTIONS
     5451    for (funcp = G.top_func; funcp; funcp = funcp->next) {
     5452        *pp++ = (char *) "-F";
     5453        *pp++ = funcp->name;
     5454        *pp++ = funcp->body_as_string;
     5455    }
     5456# endif
     5457    /* We can pass activated traps here. Say, -Tnn:trap_string
     5458     *
     5459     * However, POSIX says that subshells reset signals with traps
     5460     * to SIG_DFL.
     5461     * I tested bash-3.2 and it not only does that with true subshells
     5462     * of the form ( list ), but with any forked children shells.
     5463     * I set trap "echo W" WINCH; and then tried:
     5464     *
     5465     * { echo 1; sleep 20; echo 2; } &
     5466     * while true; do echo 1; sleep 20; echo 2; break; done &
     5467     * true | { echo 1; sleep 20; echo 2; } | cat
     5468     *
     5469     * In all these cases sending SIGWINCH to the child shell
     5470     * did not run the trap. If I add trap "echo V" WINCH;
     5471     * _inside_ group (just before echo 1), it works.
     5472     *
     5473     * I conclude it means we don't need to pass active traps here.
     5474     * Even if we would use signal handlers instead of signal masking
     5475     * in order to implement trap handling,
     5476     * exec syscall below resets signals to SIG_DFL for us.
     5477     */
     5478    *pp++ = (char *) "-c";
     5479    *pp++ = (char *) s;
     5480    if (builtin_argv) {
     5481        while (*++builtin_argv)
     5482            *pp++ = *builtin_argv;
     5483        *pp++ = (char *) "";
     5484    }
     5485    *pp++ = g_argv0;
     5486    while (*g_argv)
     5487        *pp++ = *g_argv++;
     5488    /* *pp = NULL; - is already there */
     5489    pp = environ;
     5490
     5491 do_exec:
     5492    debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s);
     5493    sigprocmask(SIG_SETMASK, &G.inherited_set, NULL);
     5494    execve(bb_busybox_exec_path, argv, pp);
     5495    /* Fallback. Useful for init=/bin/hush usage etc */
     5496    if (argv[0][0] == '/')
     5497        execve(argv[0], argv, pp);
     5498    xfunc_error_retval = 127;
     5499    bb_error_msg_and_die("can't re-execute the shell");
     5500}
     5501#endif  /* !BB_MMU */
     5502
     5503
     5504static int run_and_free_list(struct pipe *pi);
     5505
     5506/* Executing from string: eval, sh -c '...'
     5507 *          or from file: /etc/profile, . file, sh <script>, sh (intereactive)
     5508 * end_trigger controls how often we stop parsing
     5509 * NUL: parse all, execute, return
     5510 * ';': parse till ';' or newline, execute, repeat till EOF
     5511 */
     5512static void parse_and_run_stream(struct in_str *inp, int end_trigger)
     5513{
     5514    /* Why we need empty flag?
     5515     * An obscure corner case "false; ``; echo $?":
     5516     * empty command in `` should still set $? to 0.
     5517     * But we can't just set $? to 0 at the start,
     5518     * this breaks "false; echo `echo $?`" case.
     5519     */
     5520    bool empty = 1;
     5521    while (1) {
     5522        struct pipe *pipe_list;
     5523
     5524        pipe_list = parse_stream(NULL, inp, end_trigger);
     5525        if (!pipe_list) { /* EOF */
     5526            if (empty)
     5527                G.last_exitcode = 0;
     5528            break;
     5529        }
     5530        debug_print_tree(pipe_list, 0);
     5531        debug_printf_exec("parse_and_run_stream: run_and_free_list\n");
     5532        run_and_free_list(pipe_list);
     5533        empty = 0;
     5534    }
     5535}
     5536
     5537static void parse_and_run_string(const char *s)
     5538{
     5539    struct in_str input;
     5540    setup_string_in_str(&input, s);
     5541    parse_and_run_stream(&input, '\0');
     5542}
     5543
     5544static void parse_and_run_file(FILE *f)
     5545{
     5546    struct in_str input;
     5547    setup_file_in_str(&input, f);
     5548    parse_and_run_stream(&input, ';');
     5549}
     5550
     5551#if ENABLE_HUSH_TICK
     5552static FILE *generate_stream_from_string(const char *s, pid_t *pid_p)
     5553{
     5554    pid_t pid;
     5555    int channel[2];
     5556# if !BB_MMU
     5557    char **to_free = NULL;
     5558# endif
     5559
     5560    xpipe(channel);
     5561    pid = BB_MMU ? xfork() : xvfork();
     5562    if (pid == 0) { /* child */
     5563        disable_restore_tty_pgrp_on_exit();
     5564        /* Process substitution is not considered to be usual
     5565         * 'command execution'.
     5566         * SUSv3 says ctrl-Z should be ignored, ctrl-C should not.
     5567         */
     5568        bb_signals(0
     5569            + (1 << SIGTSTP)
     5570            + (1 << SIGTTIN)
     5571            + (1 << SIGTTOU)
     5572            , SIG_IGN);
     5573        CLEAR_RANDOM_T(&G.random_gen); /* or else $RANDOM repeats in child */
     5574        close(channel[0]); /* NB: close _first_, then move fd! */
     5575        xmove_fd(channel[1], 1);
     5576        /* Prevent it from trying to handle ctrl-z etc */
     5577        IF_HUSH_JOB(G.run_list_level = 1;)
     5578        /* Awful hack for `trap` or $(trap).
     5579         *
     5580         * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
     5581         * contains an example where "trap" is executed in a subshell:
     5582         *
     5583         * save_traps=$(trap)
     5584         * ...
     5585         * eval "$save_traps"
     5586         *
     5587         * Standard does not say that "trap" in subshell shall print
     5588         * parent shell's traps. It only says that its output
     5589         * must have suitable form, but then, in the above example
     5590         * (which is not supposed to be normative), it implies that.
     5591         *
     5592         * bash (and probably other shell) does implement it
     5593         * (traps are reset to defaults, but "trap" still shows them),
     5594         * but as a result, "trap" logic is hopelessly messed up:
     5595         *
     5596         * # trap
     5597         * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
     5598         * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
     5599         * # true | trap   <--- trap is in subshell - no output (ditto)
     5600         * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
     5601         * trap -- 'echo Ho' SIGWINCH
     5602         * # echo `(trap)`         <--- in subshell in subshell - output
     5603         * trap -- 'echo Ho' SIGWINCH
     5604         * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
     5605         * trap -- 'echo Ho' SIGWINCH
     5606         *
     5607         * The rules when to forget and when to not forget traps
     5608         * get really complex and nonsensical.
     5609         *
     5610         * Our solution: ONLY bare $(trap) or `trap` is special.
     5611         */
     5612        s = skip_whitespace(s);
     5613        if (strncmp(s, "trap", 4) == 0
     5614         && skip_whitespace(s + 4)[0] == '\0'
     5615        ) {
     5616            static const char *const argv[] = { NULL, NULL };
     5617            builtin_trap((char**)argv);
     5618            exit(0); /* not _exit() - we need to fflush */
     5619        }
     5620# if BB_MMU
     5621        reset_traps_to_defaults();
     5622        parse_and_run_string(s);
     5623        _exit(G.last_exitcode);
     5624# else
     5625    /* We re-execute after vfork on NOMMU. This makes this script safe:
     5626     * yes "0123456789012345678901234567890" | dd bs=32 count=64k >BIG
     5627     * huge=`cat BIG` # was blocking here forever
     5628     * echo OK
     5629     */
     5630        re_execute_shell(&to_free,
     5631                s,
     5632                G.global_argv[0],
     5633                G.global_argv + 1,
     5634                NULL);
     5635# endif
     5636    }
     5637
     5638    /* parent */
     5639    *pid_p = pid;
     5640# if ENABLE_HUSH_FAST
     5641    G.count_SIGCHLD++;
     5642//bb_error_msg("[%d] fork in generate_stream_from_string:"
     5643//      " G.count_SIGCHLD:%d G.handled_SIGCHLD:%d",
     5644//      getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
     5645# endif
     5646    enable_restore_tty_pgrp_on_exit();
     5647# if !BB_MMU
     5648    free(to_free);
     5649# endif
     5650    close(channel[1]);
     5651    close_on_exec_on(channel[0]);
     5652    return xfdopen_for_read(channel[0]);
     5653}
     5654
     5655/* Return code is exit status of the process that is run. */
     5656static int process_command_subs(o_string *dest, const char *s)
     5657{
     5658    FILE *fp;
     5659    struct in_str pipe_str;
     5660    pid_t pid;
     5661    int status, ch, eol_cnt;
     5662
     5663    fp = generate_stream_from_string(s, &pid);
     5664
     5665    /* Now send results of command back into original context */
     5666    setup_file_in_str(&pipe_str, fp);
     5667    eol_cnt = 0;
     5668    while ((ch = i_getch(&pipe_str)) != EOF) {
     5669        if (ch == '\n') {
     5670            eol_cnt++;
     5671            continue;
     5672        }
     5673        while (eol_cnt) {
     5674            o_addchr(dest, '\n');
     5675            eol_cnt--;
     5676        }
     5677        o_addQchr(dest, ch);
     5678    }
     5679
     5680    debug_printf("done reading from `cmd` pipe, closing it\n");
     5681    fclose(fp);
     5682    /* We need to extract exitcode. Test case
     5683     * "true; echo `sleep 1; false` $?"
     5684     * should print 1 */
     5685    safe_waitpid(pid, &status, 0);
     5686    debug_printf("child exited. returning its exitcode:%d\n", WEXITSTATUS(status));
     5687    return WEXITSTATUS(status);
     5688}
     5689#endif /* ENABLE_HUSH_TICK */
     5690
     5691
     5692static void setup_heredoc(struct redir_struct *redir)
     5693{
     5694    struct fd_pair pair;
     5695    pid_t pid;
     5696    int len, written;
     5697    /* the _body_ of heredoc (misleading field name) */
     5698    const char *heredoc = redir->rd_filename;
     5699    char *expanded;
     5700#if !BB_MMU
     5701    char **to_free;
     5702#endif
     5703
     5704    expanded = NULL;
     5705    if (!(redir->rd_dup & HEREDOC_QUOTED)) {
     5706        expanded = encode_then_expand_string(heredoc, /*process_bkslash:*/ 1, /*unbackslash:*/ 1);
     5707        if (expanded)
     5708            heredoc = expanded;
     5709    }
     5710    len = strlen(heredoc);
     5711
     5712    close(redir->rd_fd); /* often saves dup2+close in xmove_fd */
     5713    xpiped_pair(pair);
     5714    xmove_fd(pair.rd, redir->rd_fd);
     5715
     5716    /* Try writing without forking. Newer kernels have
     5717     * dynamically growing pipes. Must use non-blocking write! */
     5718    ndelay_on(pair.wr);
     5719    while (1) {
     5720        written = write(pair.wr, heredoc, len);
     5721        if (written <= 0)
     5722            break;
     5723        len -= written;
     5724        if (len == 0) {
     5725            close(pair.wr);
     5726            free(expanded);
     5727            return;
     5728        }
     5729        heredoc += written;
     5730    }
     5731    ndelay_off(pair.wr);
     5732
     5733    /* Okay, pipe buffer was not big enough */
     5734    /* Note: we must not create a stray child (bastard? :)
     5735     * for the unsuspecting parent process. Child creates a grandchild
     5736     * and exits before parent execs the process which consumes heredoc
     5737     * (that exec happens after we return from this function) */
     5738#if !BB_MMU
     5739    to_free = NULL;
     5740#endif
     5741    pid = xvfork();
     5742    if (pid == 0) {
     5743        /* child */
     5744        disable_restore_tty_pgrp_on_exit();
     5745        pid = BB_MMU ? xfork() : xvfork();
     5746        if (pid != 0)
     5747            _exit(0);
     5748        /* grandchild */
     5749        close(redir->rd_fd); /* read side of the pipe */
     5750#if BB_MMU
     5751        full_write(pair.wr, heredoc, len); /* may loop or block */
     5752        _exit(0);
     5753#else
     5754        /* Delegate blocking writes to another process */
     5755        xmove_fd(pair.wr, STDOUT_FILENO);
     5756        re_execute_shell(&to_free, heredoc, NULL, NULL, NULL);
     5757#endif
     5758    }
     5759    /* parent */
     5760#if ENABLE_HUSH_FAST
     5761    G.count_SIGCHLD++;
     5762//bb_error_msg("[%d] fork in setup_heredoc: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
     5763#endif
     5764    enable_restore_tty_pgrp_on_exit();
     5765#if !BB_MMU
     5766    free(to_free);
     5767#endif
     5768    close(pair.wr);
     5769    free(expanded);
     5770    wait(NULL); /* wait till child has died */
    12775771}
    12785772
    12795773/* squirrel != NULL means we squirrel away copies of stdin, stdout,
    12805774 * and stderr if they are redirected. */
    1281 static int setup_redirects(struct child_prog *prog, int squirrel[])
     5775static int setup_redirects(struct command *prog, int squirrel[])
    12825776{
    12835777    int openfd, mode;
     
    12855779
    12865780    for (redir = prog->redirects; redir; redir = redir->next) {
    1287         if (redir->dup == -1 && redir->word.gl_pathv == NULL) {
    1288             /* something went wrong in the parse.  Pretend it didn't happen */
     5781        if (redir->rd_type == REDIRECT_HEREDOC2) {
     5782            /* rd_fd<<HERE case */
     5783            if (squirrel && redir->rd_fd < 3
     5784             && squirrel[redir->rd_fd] < 0
     5785            ) {
     5786                squirrel[redir->rd_fd] = dup(redir->rd_fd);
     5787            }
     5788            /* for REDIRECT_HEREDOC2, rd_filename holds _contents_
     5789             * of the heredoc */
     5790            debug_printf_parse("set heredoc '%s'\n",
     5791                    redir->rd_filename);
     5792            setup_heredoc(redir);
    12895793            continue;
    12905794        }
    1291         if (redir->dup == -1) {
    1292             mode = redir_table[redir->type].mode;
    1293             openfd = open_or_warn(redir->word.gl_pathv[0], mode);
     5795
     5796        if (redir->rd_dup == REDIRFD_TO_FILE) {
     5797            /* rd_fd<*>file case (<*> is <,>,>>,<>) */
     5798            char *p;
     5799            if (redir->rd_filename == NULL) {
     5800                /* Something went wrong in the parse.
     5801                 * Pretend it didn't happen */
     5802                bb_error_msg("bug in redirect parse");
     5803                continue;
     5804            }
     5805            mode = redir_table[redir->rd_type].mode;
     5806            p = expand_string_to_string(redir->rd_filename, /*unbackslash:*/ 1);
     5807            openfd = open_or_warn(p, mode);
     5808            free(p);
    12945809            if (openfd < 0) {
    12955810            /* this could get lost if stderr has been redirected, but
    1296                bash and ash both lose it as well (though zsh doesn't!) */
     5811             * bash and ash both lose it as well (though zsh doesn't!) */
     5812//what the above comment tries to say?
    12975813                return 1;
    12985814            }
    12995815        } else {
    1300             openfd = redir->dup;
    1301         }
    1302 
    1303         if (openfd != redir->fd) {
    1304             if (squirrel && redir->fd < 3) {
    1305                 squirrel[redir->fd] = dup(redir->fd);
    1306             }
    1307             if (openfd == -3) {
    1308                 close(openfd);
     5816            /* rd_fd<*>rd_dup or rd_fd<*>- cases */
     5817            openfd = redir->rd_dup;
     5818        }
     5819
     5820        if (openfd != redir->rd_fd) {
     5821            if (squirrel && redir->rd_fd < 3
     5822             && squirrel[redir->rd_fd] < 0
     5823            ) {
     5824                squirrel[redir->rd_fd] = dup(redir->rd_fd);
     5825            }
     5826            if (openfd == REDIRFD_CLOSE) {
     5827                /* "n>-" means "close me" */
     5828                close(redir->rd_fd);
    13095829            } else {
    1310                 dup2(openfd, redir->fd);
    1311                 if (redir->dup == -1)
     5830                xdup2(openfd, redir->rd_fd);
     5831                if (redir->rd_dup == REDIRFD_TO_FILE)
    13125832                    close(openfd);
    13135833            }
     
    13295849}
    13305850
    1331 /* never returns */
    1332 /* XXX no exit() here.  If you don't exec, use _exit instead.
     5851static char *find_in_path(const char *arg)
     5852{
     5853    char *ret = NULL;
     5854    const char *PATH = get_local_var_value("PATH");
     5855
     5856    if (!PATH)
     5857        return NULL;
     5858
     5859    while (1) {
     5860        const char *end = strchrnul(PATH, ':');
     5861        int sz = end - PATH; /* must be int! */
     5862
     5863        free(ret);
     5864        if (sz != 0) {
     5865            ret = xasprintf("%.*s/%s", sz, PATH, arg);
     5866        } else {
     5867            /* We have xxx::yyyy in $PATH,
     5868             * it means "use current dir" */
     5869            ret = xstrdup(arg);
     5870        }
     5871        if (access(ret, F_OK) == 0)
     5872            break;
     5873
     5874        if (*end == '\0') {
     5875            free(ret);
     5876            return NULL;
     5877        }
     5878        PATH = end + 1;
     5879    }
     5880
     5881    return ret;
     5882}
     5883
     5884static const struct built_in_command *find_builtin_helper(const char *name,
     5885        const struct built_in_command *x,
     5886        const struct built_in_command *end)
     5887{
     5888    while (x != end) {
     5889        if (strcmp(name, x->b_cmd) != 0) {
     5890            x++;
     5891            continue;
     5892        }
     5893        debug_printf_exec("found builtin '%s'\n", name);
     5894        return x;
     5895    }
     5896    return NULL;
     5897}
     5898static const struct built_in_command *find_builtin1(const char *name)
     5899{
     5900    return find_builtin_helper(name, bltins1, &bltins1[ARRAY_SIZE(bltins1)]);
     5901}
     5902static const struct built_in_command *find_builtin(const char *name)
     5903{
     5904    const struct built_in_command *x = find_builtin1(name);
     5905    if (x)
     5906        return x;
     5907    return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]);
     5908}
     5909
     5910#if ENABLE_HUSH_FUNCTIONS
     5911static struct function **find_function_slot(const char *name)
     5912{
     5913    struct function **funcpp = &G.top_func;
     5914    while (*funcpp) {
     5915        if (strcmp(name, (*funcpp)->name) == 0) {
     5916            break;
     5917        }
     5918        funcpp = &(*funcpp)->next;
     5919    }
     5920    return funcpp;
     5921}
     5922
     5923static const struct function *find_function(const char *name)
     5924{
     5925    const struct function *funcp = *find_function_slot(name);
     5926    if (funcp)
     5927        debug_printf_exec("found function '%s'\n", name);
     5928    return funcp;
     5929}
     5930
     5931/* Note: takes ownership on name ptr */
     5932static struct function *new_function(char *name)
     5933{
     5934    struct function **funcpp = find_function_slot(name);
     5935    struct function *funcp = *funcpp;
     5936
     5937    if (funcp != NULL) {
     5938        struct command *cmd = funcp->parent_cmd;
     5939        debug_printf_exec("func %p parent_cmd %p\n", funcp, cmd);
     5940        if (!cmd) {
     5941            debug_printf_exec("freeing & replacing function '%s'\n", funcp->name);
     5942            free(funcp->name);
     5943            /* Note: if !funcp->body, do not free body_as_string!
     5944             * This is a special case of "-F name body" function:
     5945             * body_as_string was not malloced! */
     5946            if (funcp->body) {
     5947                free_pipe_list(funcp->body);
     5948# if !BB_MMU
     5949                free(funcp->body_as_string);
     5950# endif
     5951            }
     5952        } else {
     5953            debug_printf_exec("reinserting in tree & replacing function '%s'\n", funcp->name);
     5954            cmd->argv[0] = funcp->name;
     5955            cmd->group = funcp->body;
     5956# if !BB_MMU
     5957            cmd->group_as_string = funcp->body_as_string;
     5958# endif
     5959        }
     5960    } else {
     5961        debug_printf_exec("remembering new function '%s'\n", name);
     5962        funcp = *funcpp = xzalloc(sizeof(*funcp));
     5963        /*funcp->next = NULL;*/
     5964    }
     5965
     5966    funcp->name = name;
     5967    return funcp;
     5968}
     5969
     5970static void unset_func(const char *name)
     5971{
     5972    struct function **funcpp = find_function_slot(name);
     5973    struct function *funcp = *funcpp;
     5974
     5975    if (funcp != NULL) {
     5976        debug_printf_exec("freeing function '%s'\n", funcp->name);
     5977        *funcpp = funcp->next;
     5978        /* funcp is unlinked now, deleting it.
     5979         * Note: if !funcp->body, the function was created by
     5980         * "-F name body", do not free ->body_as_string
     5981         * and ->name as they were not malloced. */
     5982        if (funcp->body) {
     5983            free_pipe_list(funcp->body);
     5984            free(funcp->name);
     5985# if !BB_MMU
     5986            free(funcp->body_as_string);
     5987# endif
     5988        }
     5989        free(funcp);
     5990    }
     5991}
     5992
     5993# if BB_MMU
     5994#define exec_function(to_free, funcp, argv) \
     5995    exec_function(funcp, argv)
     5996# endif
     5997static void exec_function(char ***to_free,
     5998        const struct function *funcp,
     5999        char **argv) NORETURN;
     6000static void exec_function(char ***to_free,
     6001        const struct function *funcp,
     6002        char **argv)
     6003{
     6004# if BB_MMU
     6005    int n = 1;
     6006
     6007    argv[0] = G.global_argv[0];
     6008    G.global_argv = argv;
     6009    while (*++argv)
     6010        n++;
     6011    G.global_argc = n;
     6012    /* On MMU, funcp->body is always non-NULL */
     6013    n = run_list(funcp->body);
     6014    fflush_all();
     6015    _exit(n);
     6016# else
     6017    re_execute_shell(to_free,
     6018            funcp->body_as_string,
     6019            G.global_argv[0],
     6020            argv + 1,
     6021            NULL);
     6022# endif
     6023}
     6024
     6025static int run_function(const struct function *funcp, char **argv)
     6026{
     6027    int rc;
     6028    save_arg_t sv;
     6029    smallint sv_flg;
     6030
     6031    save_and_replace_G_args(&sv, argv);
     6032
     6033    /* "we are in function, ok to use return" */
     6034    sv_flg = G.flag_return_in_progress;
     6035    G.flag_return_in_progress = -1;
     6036# if ENABLE_HUSH_LOCAL
     6037    G.func_nest_level++;
     6038# endif
     6039
     6040    /* On MMU, funcp->body is always non-NULL */
     6041# if !BB_MMU
     6042    if (!funcp->body) {
     6043        /* Function defined by -F */
     6044        parse_and_run_string(funcp->body_as_string);
     6045        rc = G.last_exitcode;
     6046    } else
     6047# endif
     6048    {
     6049        rc = run_list(funcp->body);
     6050    }
     6051
     6052# if ENABLE_HUSH_LOCAL
     6053    {
     6054        struct variable *var;
     6055        struct variable **var_pp;
     6056
     6057        var_pp = &G.top_var;
     6058        while ((var = *var_pp) != NULL) {
     6059            if (var->func_nest_level < G.func_nest_level) {
     6060                var_pp = &var->next;
     6061                continue;
     6062            }
     6063            /* Unexport */
     6064            if (var->flg_export)
     6065                bb_unsetenv(var->varstr);
     6066            /* Remove from global list */
     6067            *var_pp = var->next;
     6068            /* Free */
     6069            if (!var->max_len)
     6070                free(var->varstr);
     6071            free(var);
     6072        }
     6073        G.func_nest_level--;
     6074    }
     6075# endif
     6076    G.flag_return_in_progress = sv_flg;
     6077
     6078    restore_G_args(&sv, argv);
     6079
     6080    return rc;
     6081}
     6082#endif /* ENABLE_HUSH_FUNCTIONS */
     6083
     6084
     6085#if BB_MMU
     6086#define exec_builtin(to_free, x, argv) \
     6087    exec_builtin(x, argv)
     6088#else
     6089#define exec_builtin(to_free, x, argv) \
     6090    exec_builtin(to_free, argv)
     6091#endif
     6092static void exec_builtin(char ***to_free,
     6093        const struct built_in_command *x,
     6094        char **argv) NORETURN;
     6095static void exec_builtin(char ***to_free,
     6096        const struct built_in_command *x,
     6097        char **argv)
     6098{
     6099#if BB_MMU
     6100    int rcode = x->b_function(argv);
     6101    fflush_all();
     6102    _exit(rcode);
     6103#else
     6104    /* On NOMMU, we must never block!
     6105     * Example: { sleep 99 | read line; } & echo Ok
     6106     */
     6107    re_execute_shell(to_free,
     6108            argv[0],
     6109            G.global_argv[0],
     6110            G.global_argv + 1,
     6111            argv);
     6112#endif
     6113}
     6114
     6115
     6116static void execvp_or_die(char **argv) NORETURN;
     6117static void execvp_or_die(char **argv)
     6118{
     6119    debug_printf_exec("execing '%s'\n", argv[0]);
     6120    sigprocmask(SIG_SETMASK, &G.inherited_set, NULL);
     6121    execvp(argv[0], argv);
     6122    bb_perror_msg("can't execute '%s'", argv[0]);
     6123    _exit(127); /* bash compat */
     6124}
     6125
     6126#if ENABLE_HUSH_MODE_X
     6127static void dump_cmd_in_x_mode(char **argv)
     6128{
     6129    if (G_x_mode && argv) {
     6130        /* We want to output the line in one write op */
     6131        char *buf, *p;
     6132        int len;
     6133        int n;
     6134
     6135        len = 3;
     6136        n = 0;
     6137        while (argv[n])
     6138            len += strlen(argv[n++]) + 1;
     6139        buf = xmalloc(len);
     6140        buf[0] = '+';
     6141        p = buf + 1;
     6142        n = 0;
     6143        while (argv[n])
     6144            p += sprintf(p, " %s", argv[n++]);
     6145        *p++ = '\n';
     6146        *p = '\0';
     6147        fputs(buf, stderr);
     6148        free(buf);
     6149    }
     6150}
     6151#else
     6152# define dump_cmd_in_x_mode(argv) ((void)0)
     6153#endif
     6154
     6155#if BB_MMU
     6156#define pseudo_exec_argv(nommu_save, argv, assignment_cnt, argv_expanded) \
     6157    pseudo_exec_argv(argv, assignment_cnt, argv_expanded)
     6158#define pseudo_exec(nommu_save, command, argv_expanded) \
     6159    pseudo_exec(command, argv_expanded)
     6160#endif
     6161
     6162/* Called after [v]fork() in run_pipe, or from builtin_exec.
     6163 * Never returns.
     6164 * Don't exit() here.  If you don't exec, use _exit instead.
    13336165 * The at_exit handlers apparently confuse the calling process,
    13346166 * in particular stdin handling.  Not sure why? -- because of vfork! (vda) */
    1335 static void pseudo_exec_argv(char **argv)
    1336 {
    1337     int i, rcode;
    1338     char *p;
    1339     const struct built_in_command *x;
    1340 
    1341     for (i = 0; is_assignment(argv[i]); i++) {
    1342         debug_printf_exec("pid %d environment modification: %s\n",
    1343                 getpid(), argv[i]);
    1344 // FIXME: vfork case??
    1345         p = expand_string_to_string(argv[i]);
    1346         putenv(p);
    1347     }
    1348     argv += i;
    1349     /* If a variable is assigned in a forest, and nobody listens,
    1350      * was it ever really set?
    1351     */
    1352     if (argv[0] == NULL) {
     6167static void pseudo_exec_argv(nommu_save_t *nommu_save,
     6168        char **argv, int assignment_cnt,
     6169        char **argv_expanded) NORETURN;
     6170static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save,
     6171        char **argv, int assignment_cnt,
     6172        char **argv_expanded)
     6173{
     6174    char **new_env;
     6175
     6176    new_env = expand_assignments(argv, assignment_cnt);
     6177    dump_cmd_in_x_mode(new_env);
     6178
     6179    if (!argv[assignment_cnt]) {
     6180        /* Case when we are here: ... | var=val | ...
     6181         * (note that we do not exit early, i.e., do not optimize out
     6182         * expand_assignments(): think about ... | var=`sleep 1` | ...
     6183        */
     6184        free_strings(new_env);
    13536185        _exit(EXIT_SUCCESS);
    13546186    }
    13556187
    1356     argv = expand_strvec_to_strvec(argv);
    1357 
    1358     /*
    1359      * Check if the command matches any of the builtins.
     6188#if BB_MMU
     6189    set_vars_and_save_old(new_env);
     6190    free(new_env); /* optional */
     6191    /* we can also destroy set_vars_and_save_old's return value,
     6192     * to save memory */
     6193#else
     6194    nommu_save->new_env = new_env;
     6195    nommu_save->old_vars = set_vars_and_save_old(new_env);
     6196#endif
     6197
     6198    if (argv_expanded) {
     6199        argv = argv_expanded;
     6200    } else {
     6201        argv = expand_strvec_to_strvec(argv + assignment_cnt);
     6202#if !BB_MMU
     6203        nommu_save->argv = argv;
     6204#endif
     6205    }
     6206    dump_cmd_in_x_mode(argv);
     6207
     6208#if ENABLE_FEATURE_SH_STANDALONE || BB_MMU
     6209    if (strchr(argv[0], '/') != NULL)
     6210        goto skip;
     6211#endif
     6212
     6213    /* Check if the command matches any of the builtins.
    13606214     * Depending on context, this might be redundant.  But it's
    13616215     * easier to waste a few CPU cycles than it is to figure out
    13626216     * if this is one of those cases.
    13636217     */
    1364     for (x = bltins; x->cmd; x++) {
    1365         if (strcmp(argv[0], x->cmd) == 0) {
    1366             debug_printf_exec("running builtin '%s'\n", argv[0]);
    1367             rcode = x->function(argv);
    1368             fflush(stdout);
    1369             _exit(rcode);
    1370         }
    1371     }
    1372 
     6218    {
     6219        /* On NOMMU, it is more expensive to re-execute shell
     6220         * just in order to run echo or test builtin.
     6221         * It's better to skip it here and run corresponding
     6222         * non-builtin later. */
     6223        const struct built_in_command *x;
     6224        x = BB_MMU ? find_builtin(argv[0]) : find_builtin1(argv[0]);
     6225        if (x) {
     6226            exec_builtin(&nommu_save->argv_from_re_execing, x, argv);
     6227        }
     6228    }
     6229#if ENABLE_HUSH_FUNCTIONS
     6230    /* Check if the command matches any functions */
     6231    {
     6232        const struct function *funcp = find_function(argv[0]);
     6233        if (funcp) {
     6234            exec_function(&nommu_save->argv_from_re_execing, funcp, argv);
     6235        }
     6236    }
     6237#endif
     6238
     6239#if ENABLE_FEATURE_SH_STANDALONE
    13736240    /* Check if the command matches any busybox applets */
    1374 #if ENABLE_FEATURE_SH_STANDALONE
    1375     if (strchr(argv[0], '/') == NULL) {
    1376         const struct bb_applet *a = find_applet_by_name(argv[0]);
    1377         if (a) {
    1378             if (a->noexec) {
    1379                 current_applet = a;
     6241    {
     6242        int a = find_applet_by_name(argv[0]);
     6243        if (a >= 0) {
     6244# if BB_MMU /* see above why on NOMMU it is not allowed */
     6245            if (APPLET_IS_NOEXEC(a)) {
    13806246                debug_printf_exec("running applet '%s'\n", argv[0]);
    1381 // is it ok that run_current_applet_and_exit() does exit(), not _exit()?
    1382                 run_current_applet_and_exit(argv);
    1383             }
    1384             /* re-exec ourselves with the new arguments */
     6247                run_applet_no_and_exit(a, argv);
     6248            }
     6249# endif
     6250            /* Re-exec ourselves */
    13856251            debug_printf_exec("re-execing applet '%s'\n", argv[0]);
    1386             execvp(bb_busybox_exec_path, argv);
     6252            sigprocmask(SIG_SETMASK, &G.inherited_set, NULL);
     6253            execv(bb_busybox_exec_path, argv);
    13876254            /* If they called chroot or otherwise made the binary no longer
    13886255             * executable, fall through */
     
    13916258#endif
    13926259
    1393     debug_printf_exec("execing '%s'\n", argv[0]);
    1394     execvp(argv[0], argv);
    1395     bb_perror_msg("cannot exec '%s'", argv[0]);
    1396     _exit(1);
    1397 }
    1398 
    1399 static void pseudo_exec(struct child_prog *child)
    1400 {
    1401 // FIXME: buggy wrt NOMMU! Must not modify any global data
    1402 // until it does exec/_exit, but currently it does.
    1403     int rcode;
    1404 
    1405     if (child->argv) {
    1406         pseudo_exec_argv(child->argv);
    1407     }
    1408 
    1409     if (child->group) {
    1410     // FIXME: do not modify globals! Think vfork!
    1411 #if ENABLE_HUSH_INTERACTIVE
    1412         debug_printf_exec("pseudo_exec: setting interactive_fd=0\n");
    1413         interactive_fd = 0;    /* crucial!!!! */
    1414 #endif
    1415         debug_printf_exec("pseudo_exec: run_list_real\n");
    1416         rcode = run_list_real(child->group);
     6260#if ENABLE_FEATURE_SH_STANDALONE || BB_MMU
     6261 skip:
     6262#endif
     6263    execvp_or_die(argv);
     6264}
     6265
     6266/* Called after [v]fork() in run_pipe
     6267 */
     6268static void pseudo_exec(nommu_save_t *nommu_save,
     6269        struct command *command,
     6270        char **argv_expanded) NORETURN;
     6271static void pseudo_exec(nommu_save_t *nommu_save,
     6272        struct command *command,
     6273        char **argv_expanded)
     6274{
     6275    if (command->argv) {
     6276        pseudo_exec_argv(nommu_save, command->argv,
     6277                command->assignment_cnt, argv_expanded);
     6278    }
     6279
     6280    if (command->group) {
     6281        /* Cases when we are here:
     6282         * ( list )
     6283         * { list } &
     6284         * ... | ( list ) | ...
     6285         * ... | { list } | ...
     6286         */
     6287#if BB_MMU
     6288        int rcode;
     6289        debug_printf_exec("pseudo_exec: run_list\n");
     6290        reset_traps_to_defaults();
     6291        rcode = run_list(command->group);
    14176292        /* OK to leak memory by not calling free_pipe_list,
    14186293         * since this process is about to exit */
    14196294        _exit(rcode);
    1420     }
    1421 
    1422     /* Can happen.  See what bash does with ">foo" by itself. */
    1423     debug_printf("trying to pseudo_exec null command\n");
     6295#else
     6296        re_execute_shell(&nommu_save->argv_from_re_execing,
     6297                command->group_as_string,
     6298                G.global_argv[0],
     6299                G.global_argv + 1,
     6300                NULL);
     6301#endif
     6302    }
     6303
     6304    /* Case when we are here: ... | >file */
     6305    debug_printf_exec("pseudo_exec'ed null command\n");
    14246306    _exit(EXIT_SUCCESS);
    14256307}
     
    14376319    if (pi->cmdtext)
    14386320        return pi->cmdtext;
    1439     argv = pi->progs[0].argv;
    1440     if (!argv || !argv[0])
    1441         return (pi->cmdtext = xzalloc(1));
     6321    argv = pi->cmds[0].argv;
     6322    if (!argv || !argv[0]) {
     6323        pi->cmdtext = xzalloc(1);
     6324        return pi->cmdtext;
     6325    }
    14426326
    14436327    len = 0;
    1444     do len += strlen(*argv) + 1; while (*++argv);
    1445     pi->cmdtext = p = xmalloc(len);
    1446     argv = pi->progs[0].argv;
     6328    do {
     6329        len += strlen(*argv) + 1;
     6330    } while (*++argv);
     6331    p = xmalloc(len);
     6332    pi->cmdtext = p;
     6333    argv = pi->cmds[0].argv;
    14476334    do {
    14486335        len = strlen(*argv);
     
    14576344static void insert_bg_job(struct pipe *pi)
    14586345{
    1459     struct pipe *thejob;
     6346    struct pipe *job, **jobp;
    14606347    int i;
    14616348
    14626349    /* Linear search for the ID of the job to use */
    14636350    pi->jobid = 1;
    1464     for (thejob = job_list; thejob; thejob = thejob->next)
    1465         if (thejob->jobid >= pi->jobid)
    1466             pi->jobid = thejob->jobid + 1;
    1467 
    1468     /* Add thejob to the list of running jobs */
    1469     if (!job_list) {
    1470         thejob = job_list = xmalloc(sizeof(*thejob));
     6351    for (job = G.job_list; job; job = job->next)
     6352        if (job->jobid >= pi->jobid)
     6353            pi->jobid = job->jobid + 1;
     6354
     6355    /* Add job to the list of running jobs */
     6356    jobp = &G.job_list;
     6357    while ((job = *jobp) != NULL)
     6358        jobp = &job->next;
     6359    job = *jobp = xmalloc(sizeof(*job));
     6360
     6361    *job = *pi; /* physical copy */
     6362    job->next = NULL;
     6363    job->cmds = xzalloc(sizeof(pi->cmds[0]) * pi->num_cmds);
     6364    /* Cannot copy entire pi->cmds[] vector! This causes double frees */
     6365    for (i = 0; i < pi->num_cmds; i++) {
     6366        job->cmds[i].pid = pi->cmds[i].pid;
     6367        /* all other fields are not used and stay zero */
     6368    }
     6369    job->cmdtext = xstrdup(get_cmdtext(pi));
     6370
     6371    if (G_interactive_fd)
     6372        printf("[%d] %d %s\n", job->jobid, job->cmds[0].pid, job->cmdtext);
     6373    G.last_jobid = job->jobid;
     6374}
     6375
     6376static void remove_bg_job(struct pipe *pi)
     6377{
     6378    struct pipe *prev_pipe;
     6379
     6380    if (pi == G.job_list) {
     6381        G.job_list = pi->next;
    14716382    } else {
    1472         for (thejob = job_list; thejob->next; thejob = thejob->next)
    1473             continue;
    1474         thejob->next = xmalloc(sizeof(*thejob));
    1475         thejob = thejob->next;
    1476     }
    1477 
    1478     /* Physically copy the struct job */
    1479     memcpy(thejob, pi, sizeof(struct pipe));
    1480     thejob->progs = xzalloc(sizeof(pi->progs[0]) * pi->num_progs);
    1481     /* We cannot copy entire pi->progs[] vector! Double free()s will happen */
    1482     for (i = 0; i < pi->num_progs; i++) {
    1483 // TODO: do we really need to have so many fields which are just dead weight
    1484 // at execution stage?
    1485         thejob->progs[i].pid = pi->progs[i].pid;
    1486         /* all other fields are not used and stay zero */
    1487     }
    1488     thejob->next = NULL;
    1489     thejob->cmdtext = xstrdup(get_cmdtext(pi));
    1490 
    1491     /* We don't wait for background thejobs to return -- append it
    1492        to the list of backgrounded thejobs and leave it alone */
    1493     printf("[%d] %d %s\n", thejob->jobid, thejob->progs[0].pid, thejob->cmdtext);
    1494     last_bg_pid = thejob->progs[0].pid;
    1495     last_jobid = thejob->jobid;
    1496 }
    1497 
    1498 static void remove_bg_job(struct pipe *pi)
    1499 {
    1500     struct pipe *prev_pipe;
    1501 
    1502     if (pi == job_list) {
    1503         job_list = pi->next;
    1504     } else {
    1505         prev_pipe = job_list;
     6383        prev_pipe = G.job_list;
    15066384        while (prev_pipe->next != pi)
    15076385            prev_pipe = prev_pipe->next;
    15086386        prev_pipe->next = pi->next;
    15096387    }
    1510     if (job_list)
    1511         last_jobid = job_list->jobid;
     6388    if (G.job_list)
     6389        G.last_jobid = G.job_list->jobid;
    15126390    else
    1513         last_jobid = 0;
    1514 }
    1515 
    1516 /* remove a backgrounded job */
     6391        G.last_jobid = 0;
     6392}
     6393
     6394/* Remove a backgrounded job */
    15176395static void delete_finished_bg_job(struct pipe *pi)
    15186396{
    15196397    remove_bg_job(pi);
    1520     pi->stopped_progs = 0;
    1521     free_pipe(pi, 0);
    1522     free(pi);
     6398    free_pipe(pi);
    15236399}
    15246400#endif /* JOB */
    15256401
    1526 /* Checks to see if any processes have exited -- if they
    1527    have, figure out why and see if a job has completed */
    1528 static int checkjobs(struct pipe* fg_pipe)
     6402/* Check to see if any processes have exited -- if they
     6403 * have, figure out why and see if a job has completed */
     6404static int checkjobs(struct pipe *fg_pipe)
    15296405{
    15306406    int attributes;
    15316407    int status;
    15326408#if ENABLE_HUSH_JOB
    1533     int prognum = 0;
    15346409    struct pipe *pi;
    15356410#endif
     
    15376412    int rcode = 0;
    15386413
     6414    debug_printf_jobs("checkjobs %p\n", fg_pipe);
     6415
    15396416    attributes = WUNTRACED;
    1540     if (fg_pipe == NULL) {
     6417    if (fg_pipe == NULL)
    15416418        attributes |= WNOHANG;
    1542     }
     6419
     6420    errno = 0;
     6421#if ENABLE_HUSH_FAST
     6422    if (G.handled_SIGCHLD == G.count_SIGCHLD) {
     6423//bb_error_msg("[%d] checkjobs: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d children?:%d fg_pipe:%p",
     6424//getpid(), G.count_SIGCHLD, G.handled_SIGCHLD, G.we_have_children, fg_pipe);
     6425        /* There was neither fork nor SIGCHLD since last waitpid */
     6426        /* Avoid doing waitpid syscall if possible */
     6427        if (!G.we_have_children) {
     6428            errno = ECHILD;
     6429            return -1;
     6430        }
     6431        if (fg_pipe == NULL) { /* is WNOHANG set? */
     6432            /* We have children, but they did not exit
     6433             * or stop yet (we saw no SIGCHLD) */
     6434            return 0;
     6435        }
     6436        /* else: !WNOHANG, waitpid will block, can't short-circuit */
     6437    }
     6438#endif
    15436439
    15446440/* Do we do this right?
     
    15486444 * bash-3.00# echo $?
    15496445 * 1   <========== bg pipe is not fully done, but exitcode is already known!
     6446 * [hush 1.14.0: yes we do it right]
    15506447 */
    1551 
    1552 //FIXME: non-interactive bash does not continue even if all processes in fg pipe
    1553 //are stopped. Testcase: "cat | cat" in a script (not on command line)
    1554 // + killall -STOP cat
    1555 
    15566448 wait_more:
    1557     while ((childpid = waitpid(-1, &status, attributes)) > 0) {
    1558         const int dead = WIFEXITED(status) || WIFSIGNALED(status);
    1559 
    1560 #ifdef DEBUG_SHELL_JOBS
     6449    while (1) {
     6450        int i;
     6451        int dead;
     6452
     6453#if ENABLE_HUSH_FAST
     6454        i = G.count_SIGCHLD;
     6455#endif
     6456        childpid = waitpid(-1, &status, attributes);
     6457        if (childpid <= 0) {
     6458            if (childpid && errno != ECHILD)
     6459                bb_perror_msg("waitpid");
     6460#if ENABLE_HUSH_FAST
     6461            else { /* Until next SIGCHLD, waitpid's are useless */
     6462                G.we_have_children = (childpid == 0);
     6463                G.handled_SIGCHLD = i;
     6464//bb_error_msg("[%d] checkjobs: waitpid returned <= 0, G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
     6465            }
     6466#endif
     6467            break;
     6468        }
     6469        dead = WIFEXITED(status) || WIFSIGNALED(status);
     6470
     6471#if DEBUG_JOBS
    15616472        if (WIFSTOPPED(status))
    15626473            debug_printf_jobs("pid %d stopped by sig %d (exitcode %d)\n",
     
    15716482        /* Were we asked to wait for fg pipe? */
    15726483        if (fg_pipe) {
    1573             int i;
    1574             for (i = 0; i < fg_pipe->num_progs; i++) {
    1575                 debug_printf_jobs("check pid %d\n", fg_pipe->progs[i].pid);
    1576                 if (fg_pipe->progs[i].pid == childpid) {
    1577                     /* printf("process %d exit %d\n", i, WEXITSTATUS(status)); */
    1578                     if (dead) {
    1579                         fg_pipe->progs[i].pid = 0;
    1580                         fg_pipe->running_progs--;
    1581                         if (i == fg_pipe->num_progs-1)
    1582                             /* last process gives overall exitstatus */
    1583                             rcode = WEXITSTATUS(status);
    1584                     } else {
    1585                         fg_pipe->progs[i].is_stopped = 1;
    1586                         fg_pipe->stopped_progs++;
     6484            i = fg_pipe->num_cmds;
     6485            while (--i >= 0) {
     6486                debug_printf_jobs("check pid %d\n", fg_pipe->cmds[i].pid);
     6487                if (fg_pipe->cmds[i].pid != childpid)
     6488                    continue;
     6489                if (dead) {
     6490                    int ex;
     6491                    fg_pipe->cmds[i].pid = 0;
     6492                    fg_pipe->alive_cmds--;
     6493                    ex = WEXITSTATUS(status);
     6494                    /* bash prints killer signal's name for *last*
     6495                     * process in pipe (prints just newline for SIGINT).
     6496                     * Mimic this. Example: "sleep 5" + (^\ or kill -QUIT)
     6497                     */
     6498                    if (WIFSIGNALED(status)) {
     6499                        int sig = WTERMSIG(status);
     6500                        if (i == fg_pipe->num_cmds-1)
     6501                            printf("%s\n", sig == SIGINT ? "" : get_signame(sig));
     6502                        /* TODO: MIPS has 128 sigs (1..128), what if sig==128 here?
     6503                         * Maybe we need to use sig | 128? */
     6504                        ex = sig + 128;
    15876505                    }
    1588                     debug_printf_jobs("fg_pipe: running_progs %d stopped_progs %d\n",
    1589                             fg_pipe->running_progs, fg_pipe->stopped_progs);
    1590                     if (fg_pipe->running_progs - fg_pipe->stopped_progs <= 0) {
    1591                         /* All processes in fg pipe have exited/stopped */
     6506                    fg_pipe->cmds[i].cmd_exitcode = ex;
     6507                } else {
     6508                    fg_pipe->cmds[i].is_stopped = 1;
     6509                    fg_pipe->stopped_cmds++;
     6510                }
     6511                debug_printf_jobs("fg_pipe: alive_cmds %d stopped_cmds %d\n",
     6512                        fg_pipe->alive_cmds, fg_pipe->stopped_cmds);
     6513                if (fg_pipe->alive_cmds == fg_pipe->stopped_cmds) {
     6514                    /* All processes in fg pipe have exited or stopped */
     6515                    i = fg_pipe->num_cmds;
     6516                    while (--i >= 0) {
     6517                        rcode = fg_pipe->cmds[i].cmd_exitcode;
     6518                        /* usually last process gives overall exitstatus,
     6519                         * but with "set -o pipefail", last *failed* process does */
     6520                        if (G.o_opt[OPT_O_PIPEFAIL] == 0 || rcode != 0)
     6521                            break;
     6522                    }
     6523                    IF_HAS_KEYWORDS(if (fg_pipe->pi_inverted) rcode = !rcode;)
     6524/* Note: *non-interactive* bash does not continue if all processes in fg pipe
     6525 * are stopped. Testcase: "cat | cat" in a script (not on command line!)
     6526 * and "killall -STOP cat" */
     6527                    if (G_interactive_fd) {
    15926528#if ENABLE_HUSH_JOB
    1593                         if (fg_pipe->running_progs)
     6529                        if (fg_pipe->alive_cmds != 0)
    15946530                            insert_bg_job(fg_pipe);
    15956531#endif
    15966532                        return rcode;
    15976533                    }
    1598                     /* There are still running processes in the fg pipe */
    1599                     goto wait_more;
     6534                    if (fg_pipe->alive_cmds == 0)
     6535                        return rcode;
    16006536                }
    1601             }
    1602             /* fall through to searching process in bg pipes */
     6537                /* There are still running processes in the fg pipe */
     6538                goto wait_more; /* do waitpid again */
     6539            }
     6540            /* it wasnt fg_pipe, look for process in bg pipes */
    16036541        }
    16046542
     
    16066544        /* We asked to wait for bg or orphaned children */
    16076545        /* No need to remember exitcode in this case */
    1608         for (pi = job_list; pi; pi = pi->next) {
    1609             prognum = 0;
    1610             while (prognum < pi->num_progs) {
    1611                 if (pi->progs[prognum].pid == childpid)
     6546        for (pi = G.job_list; pi; pi = pi->next) {
     6547            for (i = 0; i < pi->num_cmds; i++) {
     6548                if (pi->cmds[i].pid == childpid)
    16126549                    goto found_pi_and_prognum;
    1613                 prognum++;
    1614             }
    1615         }
    1616 #endif
    1617 
     6550            }
     6551        }
    16186552        /* Happens when shell is used as init process (init=/bin/sh) */
    16196553        debug_printf("checkjobs: pid %d was not in our list!\n", childpid);
    1620         goto wait_more;
    1621 
    1622 #if ENABLE_HUSH_JOB
     6554        continue; /* do waitpid again */
     6555
    16236556 found_pi_and_prognum:
    16246557        if (dead) {
    16256558            /* child exited */
    1626             pi->progs[prognum].pid = 0;
    1627             pi->running_progs--;
    1628             if (!pi->running_progs) {
    1629                 printf(JOB_STATUS_FORMAT, pi->jobid,
     6559            pi->cmds[i].pid = 0;
     6560            pi->alive_cmds--;
     6561            if (!pi->alive_cmds) {
     6562                if (G_interactive_fd)
     6563                    printf(JOB_STATUS_FORMAT, pi->jobid,
    16306564                            "Done", pi->cmdtext);
    16316565                delete_finished_bg_job(pi);
     
    16336567        } else {
    16346568            /* child stopped */
    1635             pi->stopped_progs++;
    1636             pi->progs[prognum].is_stopped = 1;
    1637         }
    1638 #endif
    1639     }
    1640 
    1641     /* wait found no children or failed */
    1642 
    1643     if (childpid && errno != ECHILD)
    1644         bb_perror_msg("waitpid");
     6569            pi->cmds[i].is_stopped = 1;
     6570            pi->stopped_cmds++;
     6571        }
     6572#endif
     6573    } /* while (waitpid succeeds)... */
     6574
    16456575    return rcode;
    16466576}
    16476577
    16486578#if ENABLE_HUSH_JOB
    1649 static int checkjobs_and_fg_shell(struct pipe* fg_pipe)
     6579static int checkjobs_and_fg_shell(struct pipe *fg_pipe)
    16506580{
    16516581    pid_t p;
    16526582    int rcode = checkjobs(fg_pipe);
    1653     /* Job finished, move the shell to the foreground */
    1654     p = getpgid(0); /* pgid of our process */
    1655     debug_printf_jobs("fg'ing ourself: getpgid(0)=%d\n", (int)p);
    1656     if (tcsetpgrp(interactive_fd, p) && errno != ENOTTY)
    1657         bb_perror_msg("tcsetpgrp-4a");
     6583    if (G_saved_tty_pgrp) {
     6584        /* Job finished, move the shell to the foreground */
     6585        p = getpgrp(); /* our process group id */
     6586        debug_printf_jobs("fg'ing ourself: getpgrp()=%d\n", (int)p);
     6587        tcsetpgrp(G_interactive_fd, p);
     6588    }
    16586589    return rcode;
    16596590}
    16606591#endif
    16616592
    1662 /* run_pipe_real() starts all the jobs, but doesn't wait for anything
    1663  * to finish.  See checkjobs().
     6593/* Start all the jobs, but don't wait for anything to finish.
     6594 * See checkjobs().
    16646595 *
    1665  * return code is normally -1, when the caller has to wait for children
     6596 * Return code is normally -1, when the caller has to wait for children
    16666597 * to finish to determine the exit status of the pipe.  If the pipe
    16676598 * is a simple builtin command, however, the action is done by the
    1668  * time run_pipe_real returns, and the exit code is provided as the
     6599 * time run_pipe returns, and the exit code is provided as the
    16696600 * return value.
    1670  *
    1671  * The input of the pipe is always stdin, the output is always
    1672  * stdout.  The outpipe[] mechanism in BusyBox-0.48 lash is bogus,
    1673  * because it tries to avoid running the command substitution in
    1674  * subshell, when that is in fact necessary.  The subshell process
    1675  * now has its stdout directed to the input of the appropriate pipe,
    1676  * so this routine is noticeably simpler.
    16776601 *
    16786602 * Returns -1 only if started some children. IOW: we have to
    16796603 * mask out retvals of builtins etc with 0xff!
     6604 *
     6605 * The only case when we do not need to [v]fork is when the pipe
     6606 * is single, non-backgrounded, non-subshell command. Examples:
     6607 * cmd ; ...   { list } ; ...
     6608 * cmd && ...  { list } && ...
     6609 * cmd || ...  { list } || ...
     6610 * If it is, then we can run cmd as a builtin, NOFORK [do we do this?],
     6611 * or (if SH_STANDALONE) an applet, and we can run the { list }
     6612 * with run_list. If it isn't one of these, we fork and exec cmd.
     6613 *
     6614 * Cases when we must fork:
     6615 * non-single:   cmd | cmd
     6616 * backgrounded: cmd &     { list } &
     6617 * subshell:     ( list ) [&]
    16806618 */
    1681 static int run_pipe_real(struct pipe *pi)
    1682 {
    1683     int i;
    1684     int nextin, nextout;
    1685     int pipefds[2];             /* pipefds[0] is for reading */
    1686     struct child_prog *child;
    1687     const struct built_in_command *x;
    1688     char *p;
     6619#if !ENABLE_HUSH_MODE_X
     6620#define redirect_and_varexp_helper(new_env_p, old_vars_p, command, squirrel, argv_expanded) \
     6621    redirect_and_varexp_helper(new_env_p, old_vars_p, command, squirrel)
     6622#endif
     6623static int redirect_and_varexp_helper(char ***new_env_p,
     6624        struct variable **old_vars_p,
     6625        struct command *command,
     6626        int squirrel[3],
     6627        char **argv_expanded)
     6628{
     6629    /* setup_redirects acts on file descriptors, not FILEs.
     6630     * This is perfect for work that comes after exec().
     6631     * Is it really safe for inline use?  Experimentally,
     6632     * things seem to work. */
     6633    int rcode = setup_redirects(command, squirrel);
     6634    if (rcode == 0) {
     6635        char **new_env = expand_assignments(command->argv, command->assignment_cnt);
     6636        *new_env_p = new_env;
     6637        dump_cmd_in_x_mode(new_env);
     6638        dump_cmd_in_x_mode(argv_expanded);
     6639        if (old_vars_p)
     6640            *old_vars_p = set_vars_and_save_old(new_env);
     6641    }
     6642    return rcode;
     6643}
     6644static NOINLINE int run_pipe(struct pipe *pi)
     6645{
     6646    static const char *const null_ptr = NULL;
     6647
     6648    int cmd_no;
     6649    int next_infd;
     6650    struct command *command;
     6651    char **argv_expanded;
     6652    char **argv;
    16896653    /* it is not always needed, but we aim to smaller code */
    16906654    int squirrel[] = { -1, -1, -1 };
    16916655    int rcode;
    1692     const int single_fg = (pi->num_progs == 1 && pi->followup != PIPE_BG);
    1693 
    1694     debug_printf_exec("run_pipe_real start: single_fg=%d\n", single_fg);
    1695 
    1696     nextin = 0;
     6656
     6657    debug_printf_exec("run_pipe start: members:%d\n", pi->num_cmds);
     6658    debug_enter();
     6659
     6660    /* Testcase: set -- q w e; (IFS='' echo "$*"; IFS=''; echo "$*"); echo "$*"
     6661     * Result should be 3 lines: q w e, qwe, q w e
     6662     */
     6663    G.ifs = get_local_var_value("IFS");
     6664    if (!G.ifs)
     6665        G.ifs = defifs;
     6666
     6667    IF_HUSH_JOB(pi->pgrp = -1;)
     6668    pi->stopped_cmds = 0;
     6669    command = &pi->cmds[0];
     6670    argv_expanded = NULL;
     6671
     6672    if (pi->num_cmds != 1
     6673     || pi->followup == PIPE_BG
     6674     || command->cmd_type == CMD_SUBSHELL
     6675    ) {
     6676        goto must_fork;
     6677    }
     6678
     6679    pi->alive_cmds = 1;
     6680
     6681    debug_printf_exec(": group:%p argv:'%s'\n",
     6682        command->group, command->argv ? command->argv[0] : "NONE");
     6683
     6684    if (command->group) {
     6685#if ENABLE_HUSH_FUNCTIONS
     6686        if (command->cmd_type == CMD_FUNCDEF) {
     6687            /* "executing" func () { list } */
     6688            struct function *funcp;
     6689
     6690            funcp = new_function(command->argv[0]);
     6691            /* funcp->name is already set to argv[0] */
     6692            funcp->body = command->group;
     6693# if !BB_MMU
     6694            funcp->body_as_string = command->group_as_string;
     6695            command->group_as_string = NULL;
     6696# endif
     6697            command->group = NULL;
     6698            command->argv[0] = NULL;
     6699            debug_printf_exec("cmd %p has child func at %p\n", command, funcp);
     6700            funcp->parent_cmd = command;
     6701            command->child_func = funcp;
     6702
     6703            debug_printf_exec("run_pipe: return EXIT_SUCCESS\n");
     6704            debug_leave();
     6705            return EXIT_SUCCESS;
     6706        }
     6707#endif
     6708        /* { list } */
     6709        debug_printf("non-subshell group\n");
     6710        rcode = 1; /* exitcode if redir failed */
     6711        if (setup_redirects(command, squirrel) == 0) {
     6712            debug_printf_exec(": run_list\n");
     6713            rcode = run_list(command->group) & 0xff;
     6714        }
     6715        restore_redirects(squirrel);
     6716        IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
     6717        debug_leave();
     6718        debug_printf_exec("run_pipe: return %d\n", rcode);
     6719        return rcode;
     6720    }
     6721
     6722    argv = command->argv ? command->argv : (char **) &null_ptr;
     6723    {
     6724        const struct built_in_command *x;
     6725#if ENABLE_HUSH_FUNCTIONS
     6726        const struct function *funcp;
     6727#else
     6728        enum { funcp = 0 };
     6729#endif
     6730        char **new_env = NULL;
     6731        struct variable *old_vars = NULL;
     6732
     6733        if (argv[command->assignment_cnt] == NULL) {
     6734            /* Assignments, but no command */
     6735            /* Ensure redirects take effect (that is, create files).
     6736             * Try "a=t >file" */
     6737#if 0 /* A few cases in testsuite fail with this code. FIXME */
     6738            rcode = redirect_and_varexp_helper(&new_env, /*old_vars:*/ NULL, command, squirrel, /*argv_expanded:*/ NULL);
     6739            /* Set shell variables */
     6740            if (new_env) {
     6741                argv = new_env;
     6742                while (*argv) {
     6743                    set_local_var(*argv, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
     6744                    /* Do we need to flag set_local_var() errors?
     6745                     * "assignment to readonly var" and "putenv error"
     6746                     */
     6747                    argv++;
     6748                }
     6749            }
     6750            /* Redirect error sets $? to 1. Otherwise,
     6751             * if evaluating assignment value set $?, retain it.
     6752             * Try "false; q=`exit 2`; echo $?" - should print 2: */
     6753            if (rcode == 0)
     6754                rcode = G.last_exitcode;
     6755            /* Exit, _skipping_ variable restoring code: */
     6756            goto clean_up_and_ret0;
     6757
     6758#else /* Older, bigger, but more correct code */
     6759
     6760            rcode = setup_redirects(command, squirrel);
     6761            restore_redirects(squirrel);
     6762            /* Set shell variables */
     6763            if (G_x_mode)
     6764                bb_putchar_stderr('+');
     6765            while (*argv) {
     6766                char *p = expand_string_to_string(*argv, /*unbackslash:*/ 1);
     6767                if (G_x_mode)
     6768                    fprintf(stderr, " %s", p);
     6769                debug_printf_exec("set shell var:'%s'->'%s'\n",
     6770                        *argv, p);
     6771                set_local_var(p, /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
     6772                /* Do we need to flag set_local_var() errors?
     6773                 * "assignment to readonly var" and "putenv error"
     6774                 */
     6775                argv++;
     6776            }
     6777            if (G_x_mode)
     6778                bb_putchar_stderr('\n');
     6779            /* Redirect error sets $? to 1. Otherwise,
     6780             * if evaluating assignment value set $?, retain it.
     6781             * Try "false; q=`exit 2`; echo $?" - should print 2: */
     6782            if (rcode == 0)
     6783                rcode = G.last_exitcode;
     6784            IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
     6785            debug_leave();
     6786            debug_printf_exec("run_pipe: return %d\n", rcode);
     6787            return rcode;
     6788#endif
     6789        }
     6790
     6791        /* Expand the rest into (possibly) many strings each */
     6792        if (0) {}
     6793#if ENABLE_HUSH_BASH_COMPAT
     6794        else if (command->cmd_type == CMD_SINGLEWORD_NOGLOB) {
     6795            argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt);
     6796        }
     6797#endif
     6798        else {
     6799            argv_expanded = expand_strvec_to_strvec(argv + command->assignment_cnt);
     6800        }
     6801
     6802        /* if someone gives us an empty string: `cmd with empty output` */
     6803        if (!argv_expanded[0]) {
     6804            free(argv_expanded);
     6805            debug_leave();
     6806            return G.last_exitcode;
     6807        }
     6808
     6809        x = find_builtin(argv_expanded[0]);
     6810#if ENABLE_HUSH_FUNCTIONS
     6811        funcp = NULL;
     6812        if (!x)
     6813            funcp = find_function(argv_expanded[0]);
     6814#endif
     6815        if (x || funcp) {
     6816            if (!funcp) {
     6817                if (x->b_function == builtin_exec && argv_expanded[1] == NULL) {
     6818                    debug_printf("exec with redirects only\n");
     6819                    rcode = setup_redirects(command, NULL);
     6820                    goto clean_up_and_ret1;
     6821                }
     6822            }
     6823            rcode = redirect_and_varexp_helper(&new_env, &old_vars, command, squirrel, argv_expanded);
     6824            if (rcode == 0) {
     6825                if (!funcp) {
     6826                    debug_printf_exec(": builtin '%s' '%s'...\n",
     6827                        x->b_cmd, argv_expanded[1]);
     6828                    rcode = x->b_function(argv_expanded) & 0xff;
     6829                    fflush_all();
     6830                }
     6831#if ENABLE_HUSH_FUNCTIONS
     6832                else {
     6833# if ENABLE_HUSH_LOCAL
     6834                    struct variable **sv;
     6835                    sv = G.shadowed_vars_pp;
     6836                    G.shadowed_vars_pp = &old_vars;
     6837# endif
     6838                    debug_printf_exec(": function '%s' '%s'...\n",
     6839                        funcp->name, argv_expanded[1]);
     6840                    rcode = run_function(funcp, argv_expanded) & 0xff;
     6841# if ENABLE_HUSH_LOCAL
     6842                    G.shadowed_vars_pp = sv;
     6843# endif
     6844                }
     6845#endif
     6846            }
     6847 clean_up_and_ret:
     6848            unset_vars(new_env);
     6849            add_vars(old_vars);
     6850/* clean_up_and_ret0: */
     6851            restore_redirects(squirrel);
     6852 clean_up_and_ret1:
     6853            free(argv_expanded);
     6854            IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
     6855            debug_leave();
     6856            debug_printf_exec("run_pipe return %d\n", rcode);
     6857            return rcode;
     6858        }
     6859
     6860        if (ENABLE_FEATURE_SH_STANDALONE) {
     6861            int n = find_applet_by_name(argv_expanded[0]);
     6862            if (n >= 0 && APPLET_IS_NOFORK(n)) {
     6863                rcode = redirect_and_varexp_helper(&new_env, &old_vars, command, squirrel, argv_expanded);
     6864                if (rcode == 0) {
     6865                    debug_printf_exec(": run_nofork_applet '%s' '%s'...\n",
     6866                        argv_expanded[0], argv_expanded[1]);
     6867                    rcode = run_nofork_applet(n, argv_expanded);
     6868                }
     6869                goto clean_up_and_ret;
     6870            }
     6871        }
     6872        /* It is neither builtin nor applet. We must fork. */
     6873    }
     6874
     6875 must_fork:
     6876    /* NB: argv_expanded may already be created, and that
     6877     * might include `cmd` runs! Do not rerun it! We *must*
     6878     * use argv_expanded if it's non-NULL */
     6879
     6880    /* Going to fork a child per each pipe member */
     6881    pi->alive_cmds = 0;
     6882    next_infd = 0;
     6883
     6884    cmd_no = 0;
     6885    while (cmd_no < pi->num_cmds) {
     6886        struct fd_pair pipefds;
     6887#if !BB_MMU
     6888        volatile nommu_save_t nommu_save;
     6889        nommu_save.new_env = NULL;
     6890        nommu_save.old_vars = NULL;
     6891        nommu_save.argv = NULL;
     6892        nommu_save.argv_from_re_execing = NULL;
     6893#endif
     6894        command = &pi->cmds[cmd_no];
     6895        cmd_no++;
     6896        if (command->argv) {
     6897            debug_printf_exec(": pipe member '%s' '%s'...\n",
     6898                    command->argv[0], command->argv[1]);
     6899        } else {
     6900            debug_printf_exec(": pipe member with no argv\n");
     6901        }
     6902
     6903        /* pipes are inserted between pairs of commands */
     6904        pipefds.rd = 0;
     6905        pipefds.wr = 1;
     6906        if (cmd_no < pi->num_cmds)
     6907            xpiped_pair(pipefds);
     6908
     6909        command->pid = BB_MMU ? fork() : vfork();
     6910        if (!command->pid) { /* child */
    16976911#if ENABLE_HUSH_JOB
    1698     pi->pgrp = -1;
    1699 #endif
    1700     pi->running_progs = 1;
    1701     pi->stopped_progs = 0;
    1702 
    1703     /* Check if this is a simple builtin (not part of a pipe).
    1704      * Builtins within pipes have to fork anyway, and are handled in
    1705      * pseudo_exec.  "echo foo | read bar" doesn't work on bash, either.
    1706      */
    1707     child = &(pi->progs[0]);
    1708     if (single_fg && child->group && child->subshell == 0) {
    1709         debug_printf("non-subshell grouping\n");
    1710         setup_redirects(child, squirrel);
    1711         debug_printf_exec(": run_list_real\n");
    1712         rcode = run_list_real(child->group);
    1713         restore_redirects(squirrel);
    1714         debug_printf_exec("run_pipe_real return %d\n", rcode);
    1715         return rcode; // do we need to add '... & 0xff' ?
    1716     }
    1717 
    1718     if (single_fg && child->argv != NULL) {
    1719         char **argv_expanded;
    1720         char **argv = child->argv;
    1721 
    1722         for (i = 0; is_assignment(argv[i]); i++)
    1723             continue;
    1724         if (i != 0 && argv[i] == NULL) {
    1725             /* assignments, but no command: set the local environment */
    1726             for (i = 0; argv[i] != NULL; i++) {
    1727                 debug_printf("local environment set: %s\n", argv[i]);
    1728                 p = expand_string_to_string(argv[i]);
    1729                 set_local_var(p, 0);
    1730             }
    1731             return EXIT_SUCCESS;   /* don't worry about errors in set_local_var() yet */
    1732         }
    1733         for (i = 0; is_assignment(argv[i]); i++) {
    1734             p = expand_string_to_string(argv[i]);
    1735             //sp: child->sp--;
    1736             putenv(p);
    1737         }
    1738         for (x = bltins; x->cmd; x++) {
    1739             if (strcmp(argv[i], x->cmd) == 0) {
    1740                 if (x->function == builtin_exec && argv[i+1] == NULL) {
    1741                     debug_printf("magic exec\n");
    1742                     setup_redirects(child, NULL);
    1743                     return EXIT_SUCCESS;
    1744                 }
    1745                 debug_printf("builtin inline %s\n", argv[0]);
    1746                 /* XXX setup_redirects acts on file descriptors, not FILEs.
    1747                  * This is perfect for work that comes after exec().
    1748                  * Is it really safe for inline use?  Experimentally,
    1749                  * things seem to work with glibc. */
    1750                 setup_redirects(child, squirrel);
    1751                 debug_printf_exec(": builtin '%s' '%s'...\n", x->cmd, argv[i+1]);
    1752                 //sp: if (child->sp) /* btw we can do it unconditionally... */
    1753                 argv_expanded = expand_strvec_to_strvec(argv + i);
    1754                 rcode = x->function(argv_expanded) & 0xff;
    1755                 free(argv_expanded);
    1756                 restore_redirects(squirrel);
    1757                 debug_printf_exec("run_pipe_real return %d\n", rcode);
    1758                 return rcode;
    1759             }
    1760         }
    1761 #if ENABLE_FEATURE_SH_STANDALONE
    1762         {
    1763             const struct bb_applet *a = find_applet_by_name(argv[i]);
    1764             if (a && a->nofork) {
    1765                 setup_redirects(child, squirrel);
    1766                 save_nofork_data(&nofork_save);
    1767                 argv_expanded = argv + i;
    1768                 //sp: if (child->sp)
    1769                 argv_expanded = expand_strvec_to_strvec(argv + i);
    1770                 debug_printf_exec(": run_nofork_applet '%s' '%s'...\n", argv_expanded[0], argv_expanded[1]);
    1771                 rcode = run_nofork_applet_prime(&nofork_save, a, argv_expanded) & 0xff;
    1772                 free(argv_expanded);
    1773                 restore_redirects(squirrel);
    1774                 debug_printf_exec("run_pipe_real return %d\n", rcode);
    1775                 return rcode;
    1776             }
    1777         }
    1778 #endif
    1779     }
    1780 
    1781     /* Going to fork a child per each pipe member */
    1782     pi->running_progs = 0;
    1783 
    1784     /* Disable job control signals for shell (parent) and
    1785      * for initial child code after fork */
    1786     set_jobctrl_sighandler(SIG_IGN);
    1787 
    1788     for (i = 0; i < pi->num_progs; i++) {
    1789         child = &(pi->progs[i]);
    1790         if (child->argv)
    1791             debug_printf_exec(": pipe member '%s' '%s'...\n", child->argv[0], child->argv[1]);
    1792         else
    1793             debug_printf_exec(": pipe member with no argv\n");
    1794 
    1795         /* pipes are inserted between pairs of commands */
    1796         if ((i + 1) < pi->num_progs) {
    1797             pipe(pipefds);
    1798             nextout = pipefds[1];
    1799         } else {
    1800             nextout = 1;
    1801             pipefds[0] = -1;
    1802         }
    1803 
    1804         /* XXX test for failed fork()? */
    1805 #if BB_MMU
    1806         child->pid = fork();
    1807 #else
    1808         child->pid = vfork();
    1809 #endif
    1810         if (!child->pid) { /* child */
     6912            disable_restore_tty_pgrp_on_exit();
     6913            CLEAR_RANDOM_T(&G.random_gen); /* or else $RANDOM repeats in child */
     6914
    18116915            /* Every child adds itself to new process group
    1812              * with pgid == pid of first child in pipe */
    1813 #if ENABLE_HUSH_JOB
    1814             if (run_list_level == 1 && interactive_fd) {
    1815                 /* Don't do pgrp restore anymore on fatal signals */
    1816                 set_fatal_sighandler(SIG_DFL);
    1817                 if (pi->pgrp < 0) /* true for 1st process only */
    1818                     pi->pgrp = getpid();
    1819                 if (setpgid(0, pi->pgrp) == 0 && pi->followup != PIPE_BG) {
     6916             * with pgid == pid_of_first_child_in_pipe */
     6917            if (G.run_list_level == 1 && G_interactive_fd) {
     6918                pid_t pgrp;
     6919                pgrp = pi->pgrp;
     6920                if (pgrp < 0) /* true for 1st process only */
     6921                    pgrp = getpid();
     6922                if (setpgid(0, pgrp) == 0
     6923                 && pi->followup != PIPE_BG
     6924                 && G_saved_tty_pgrp /* we have ctty */
     6925                ) {
    18206926                    /* We do it in *every* child, not just first,
    18216927                     * to avoid races */
    1822                     tcsetpgrp(interactive_fd, pi->pgrp);
     6928                    tcsetpgrp(G_interactive_fd, pgrp);
    18236929                }
    18246930            }
    18256931#endif
    1826             /* in non-interactive case fatal sigs are already SIG_DFL */
    1827             close_all();
    1828             if (nextin != 0) {
    1829                 dup2(nextin, 0);
    1830                 close(nextin);
    1831             }
    1832             if (nextout != 1) {
    1833                 dup2(nextout, 1);
    1834                 close(nextout);
    1835             }
    1836             if (pipefds[0] != -1) {
    1837                 close(pipefds[0]);  /* opposite end of our output pipe */
    1838             }
     6932            if (pi->alive_cmds == 0 && pi->followup == PIPE_BG) {
     6933                /* 1st cmd in backgrounded pipe
     6934                 * should have its stdin /dev/null'ed */
     6935                close(0);
     6936                if (open(bb_dev_null, O_RDONLY))
     6937                    xopen("/", O_RDONLY);
     6938            } else {
     6939                xmove_fd(next_infd, 0);
     6940            }
     6941            xmove_fd(pipefds.wr, 1);
     6942            if (pipefds.rd > 1)
     6943                close(pipefds.rd);
    18396944            /* Like bash, explicit redirects override pipes,
    18406945             * and the pipe fd is available for dup'ing. */
    1841             setup_redirects(child, NULL);
     6946            if (setup_redirects(command, NULL))
     6947                _exit(1);
    18426948
    18436949            /* Restore default handlers just prior to exec */
    1844             set_jobctrl_sighandler(SIG_DFL);
    1845             set_misc_sighandler(SIG_DFL);
    1846             signal(SIGCHLD, SIG_DFL);
    1847             pseudo_exec(child);
    1848         }
    1849 
    1850         pi->running_progs++;
    1851 
     6950            /*signal(SIGCHLD, SIG_DFL); - so far we don't have any handlers */
     6951
     6952            /* Stores to nommu_save list of env vars putenv'ed
     6953             * (NOMMU, on MMU we don't need that) */
     6954            /* cast away volatility... */
     6955            pseudo_exec((nommu_save_t*) &nommu_save, command, argv_expanded);
     6956            /* pseudo_exec() does not return */
     6957        }
     6958
     6959        /* parent or error */
     6960#if ENABLE_HUSH_FAST
     6961        G.count_SIGCHLD++;
     6962//bb_error_msg("[%d] fork in run_pipe: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
     6963#endif
     6964        enable_restore_tty_pgrp_on_exit();
     6965#if !BB_MMU
     6966        /* Clean up after vforked child */
     6967        free(nommu_save.argv);
     6968        free(nommu_save.argv_from_re_execing);
     6969        unset_vars(nommu_save.new_env);
     6970        add_vars(nommu_save.old_vars);
     6971#endif
     6972        free(argv_expanded);
     6973        argv_expanded = NULL;
     6974        if (command->pid < 0) { /* [v]fork failed */
     6975            /* Clearly indicate, was it fork or vfork */
     6976            bb_perror_msg(BB_MMU ? "vfork"+1 : "vfork");
     6977        } else {
     6978            pi->alive_cmds++;
    18526979#if ENABLE_HUSH_JOB
    1853         /* Second and next children need to know pid of first one */
    1854         if (pi->pgrp < 0)
    1855             pi->pgrp = child->pid;
    1856 #endif
    1857         if (nextin != 0)
    1858             close(nextin);
    1859         if (nextout != 1)
    1860             close(nextout);
    1861 
    1862         /* If there isn't another process, nextin is garbage
    1863            but it doesn't matter */
    1864         nextin = pipefds[0];
    1865     }
    1866     debug_printf_exec("run_pipe_real return -1\n");
     6980            /* Second and next children need to know pid of first one */
     6981            if (pi->pgrp < 0)
     6982                pi->pgrp = command->pid;
     6983#endif
     6984        }
     6985
     6986        if (cmd_no > 1)
     6987            close(next_infd);
     6988        if (cmd_no < pi->num_cmds)
     6989            close(pipefds.wr);
     6990        /* Pass read (output) pipe end to next iteration */
     6991        next_infd = pipefds.rd;
     6992    }
     6993
     6994    if (!pi->alive_cmds) {
     6995        debug_leave();
     6996        debug_printf_exec("run_pipe return 1 (all forks failed, no children)\n");
     6997        return 1;
     6998    }
     6999
     7000    debug_leave();
     7001    debug_printf_exec("run_pipe return -1 (%u children started)\n", pi->alive_cmds);
    18677002    return -1;
    18687003}
    1869 
    1870 #ifndef debug_print_tree
    1871 static void debug_print_tree(struct pipe *pi, int lvl)
    1872 {
    1873     static const char *PIPE[] = {
    1874         [PIPE_SEQ] = "SEQ",
    1875         [PIPE_AND] = "AND",
    1876         [PIPE_OR ] = "OR" ,
    1877         [PIPE_BG ] = "BG" ,
    1878     };
    1879     static const char *RES[] = {
    1880         [RES_NONE ] = "NONE" ,
    1881 #if ENABLE_HUSH_IF
    1882         [RES_IF   ] = "IF"   ,
    1883         [RES_THEN ] = "THEN" ,
    1884         [RES_ELIF ] = "ELIF" ,
    1885         [RES_ELSE ] = "ELSE" ,
    1886         [RES_FI   ] = "FI"   ,
    1887 #endif
    1888 #if ENABLE_HUSH_LOOPS
    1889         [RES_FOR  ] = "FOR"  ,
    1890         [RES_WHILE] = "WHILE",
    1891         [RES_UNTIL] = "UNTIL",
    1892         [RES_DO   ] = "DO"   ,
    1893         [RES_DONE ] = "DONE" ,
    1894         [RES_IN   ] = "IN"   ,
    1895 #endif
    1896         [RES_XXXX ] = "XXXX" ,
    1897         [RES_SNTX ] = "SNTX" ,
    1898     };
    1899 
    1900     int pin, prn;
    1901 
    1902     pin = 0;
    1903     while (pi) {
    1904         fprintf(stderr, "%*spipe %d res_word=%s followup=%d %s\n", lvl*2, "",
    1905                 pin, RES[pi->res_word], pi->followup, PIPE[pi->followup]);
    1906         prn = 0;
    1907         while (prn < pi->num_progs) {
    1908             struct child_prog *child = &pi->progs[prn];
    1909             char **argv = child->argv;
    1910 
    1911             fprintf(stderr, "%*s prog %d", lvl*2, "", prn);
    1912             if (child->group) {
    1913                 fprintf(stderr, " group %s: (argv=%p)\n",
    1914                         (child->subshell ? "()" : "{}"),
    1915                         argv);
    1916                 debug_print_tree(child->group, lvl+1);
    1917                 prn++;
    1918                 continue;
    1919             }
    1920             if (argv) while (*argv) {
    1921                 fprintf(stderr, " '%s'", *argv);
    1922                 argv++;
    1923             }
    1924             fprintf(stderr, "\n");
    1925             prn++;
    1926         }
    1927         pi = pi->next;
    1928         pin++;
    1929     }
    1930 }
    1931 #endif
    19327004
    19337005/* NB: called by pseudo_exec, and therefore must not modify any
    19347006 * global data until exec/_exit (we can be a child after vfork!) */
    1935 static int run_list_real(struct pipe *pi)
    1936 {
    1937     struct pipe *rpipe;
     7007static int run_list(struct pipe *pi)
     7008{
     7009#if ENABLE_HUSH_CASE
     7010    char *case_word = NULL;
     7011#endif
    19387012#if ENABLE_HUSH_LOOPS
    1939     char *for_varname = NULL;
     7013    struct pipe *loop_top = NULL;
    19407014    char **for_lcur = NULL;
    19417015    char **for_list = NULL;
    1942     int flag_rep = 0;
    1943 #endif
    1944     int save_num_progs;
    1945     int flag_skip = 1;
    1946     int rcode = 0; /* probably for gcc only */
    1947     int flag_restore = 0;
     7016#endif
     7017    smallint last_followup;
     7018    smalluint rcode;
     7019#if ENABLE_HUSH_IF || ENABLE_HUSH_CASE
     7020    smalluint cond_code = 0;
     7021#else
     7022    enum { cond_code = 0 };
     7023#endif
     7024#if HAS_KEYWORDS
     7025    smallint rword;      /* RES_foo */
     7026    smallint last_rword; /* ditto */
     7027#endif
     7028
     7029    debug_printf_exec("run_list start lvl %d\n", G.run_list_level);
     7030    debug_enter();
     7031
     7032#if ENABLE_HUSH_LOOPS
     7033    /* Check syntax for "for" */
     7034    {
     7035        struct pipe *cpipe;
     7036        for (cpipe = pi; cpipe; cpipe = cpipe->next) {
     7037            if (cpipe->res_word != RES_FOR && cpipe->res_word != RES_IN)
     7038                continue;
     7039            /* current word is FOR or IN (BOLD in comments below) */
     7040            if (cpipe->next == NULL) {
     7041                syntax_error("malformed for");
     7042                debug_leave();
     7043                debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level);
     7044                return 1;
     7045            }
     7046            /* "FOR v; do ..." and "for v IN a b; do..." are ok */
     7047            if (cpipe->next->res_word == RES_DO)
     7048                continue;
     7049            /* next word is not "do". It must be "in" then ("FOR v in ...") */
     7050            if (cpipe->res_word == RES_IN /* "for v IN a b; not_do..."? */
     7051             || cpipe->next->res_word != RES_IN /* FOR v not_do_and_not_in..."? */
     7052            ) {
     7053                syntax_error("malformed for");
     7054                debug_leave();
     7055                debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level);
     7056                return 1;
     7057            }
     7058        }
     7059    }
     7060#endif
     7061
     7062    /* Past this point, all code paths should jump to ret: label
     7063     * in order to return, no direct "return" statements please.
     7064     * This helps to ensure that no memory is leaked. */
     7065
     7066#if ENABLE_HUSH_JOB
     7067    G.run_list_level++;
     7068#endif
     7069
     7070#if HAS_KEYWORDS
     7071    rword = RES_NONE;
     7072    last_rword = RES_XXXX;
     7073#endif
     7074    last_followup = PIPE_SEQ;
     7075    rcode = G.last_exitcode;
     7076
     7077    /* Go through list of pipes, (maybe) executing them. */
     7078    for (; pi; pi = IF_HUSH_LOOPS(rword == RES_DONE ? loop_top : ) pi->next) {
     7079        if (G.flag_SIGINT)
     7080            break;
     7081
     7082        IF_HAS_KEYWORDS(rword = pi->res_word;)
     7083        debug_printf_exec(": rword=%d cond_code=%d last_rword=%d\n",
     7084                rword, cond_code, last_rword);
     7085#if ENABLE_HUSH_LOOPS
     7086        if ((rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR)
     7087         && loop_top == NULL /* avoid bumping G.depth_of_loop twice */
     7088        ) {
     7089            /* start of a loop: remember where loop starts */
     7090            loop_top = pi;
     7091            G.depth_of_loop++;
     7092        }
     7093#endif
     7094        /* Still in the same "if...", "then..." or "do..." branch? */
     7095        if (IF_HAS_KEYWORDS(rword == last_rword &&) 1) {
     7096            if ((rcode == 0 && last_followup == PIPE_OR)
     7097             || (rcode != 0 && last_followup == PIPE_AND)
     7098            ) {
     7099                /* It is "<true> || CMD" or "<false> && CMD"
     7100                 * and we should not execute CMD */
     7101                debug_printf_exec("skipped cmd because of || or &&\n");
     7102                last_followup = pi->followup;
     7103                continue;
     7104            }
     7105        }
     7106        last_followup = pi->followup;
     7107        IF_HAS_KEYWORDS(last_rword = rword;)
    19487108#if ENABLE_HUSH_IF
    1949     int if_code = 0, next_if_code = 0;  /* need double-buffer to handle elif */
    1950 #else
    1951     enum { if_code = 0, next_if_code = 0 };
    1952 #endif
    1953     reserved_style rword;
    1954     reserved_style skip_more_for_this_rword = RES_XXXX;
    1955 
    1956     debug_printf_exec("run_list_real start lvl %d\n", run_list_level + 1);
    1957 
     7109        if (cond_code) {
     7110            if (rword == RES_THEN) {
     7111                /* if false; then ... fi has exitcode 0! */
     7112                G.last_exitcode = rcode = EXIT_SUCCESS;
     7113                /* "if <false> THEN cmd": skip cmd */
     7114                continue;
     7115            }
     7116        } else {
     7117            if (rword == RES_ELSE || rword == RES_ELIF) {
     7118                /* "if <true> then ... ELSE/ELIF cmd":
     7119                 * skip cmd and all following ones */
     7120                break;
     7121            }
     7122        }
     7123#endif
    19587124#if ENABLE_HUSH_LOOPS
    1959     /* check syntax for "for" */
    1960     for (rpipe = pi; rpipe; rpipe = rpipe->next) {
    1961         if ((rpipe->res_word == RES_IN || rpipe->res_word == RES_FOR)
    1962          && (rpipe->next == NULL)
    1963         ) {
    1964             syntax("malformed for"); /* no IN or no commands after IN */
    1965             debug_printf_exec("run_list_real lvl %d return 1\n", run_list_level);
    1966             return 1;
    1967         }
    1968         if ((rpipe->res_word == RES_IN && rpipe->next->res_word == RES_IN && rpipe->next->progs[0].argv != NULL)
    1969          || (rpipe->res_word == RES_FOR && rpipe->next->res_word != RES_IN)
    1970         ) {
    1971             /* TODO: what is tested in the first condition? */
    1972             syntax("malformed for"); /* 2nd condition: not followed by IN */
    1973             debug_printf_exec("run_list_real lvl %d return 1\n", run_list_level);
    1974             return 1;
    1975         }
    1976     }
    1977 #else
    1978     rpipe = NULL;
    1979 #endif
    1980 
     7125        if (rword == RES_FOR) { /* && pi->num_cmds - always == 1 */
     7126            if (!for_lcur) {
     7127                /* first loop through for */
     7128
     7129                static const char encoded_dollar_at[] ALIGN1 = {
     7130                    SPECIAL_VAR_SYMBOL, '@' | 0x80, SPECIAL_VAR_SYMBOL, '\0'
     7131                }; /* encoded representation of "$@" */
     7132                static const char *const encoded_dollar_at_argv[] = {
     7133                    encoded_dollar_at, NULL
     7134                }; /* argv list with one element: "$@" */
     7135                char **vals;
     7136
     7137                vals = (char**)encoded_dollar_at_argv;
     7138                if (pi->next->res_word == RES_IN) {
     7139                    /* if no variable values after "in" we skip "for" */
     7140                    if (!pi->next->cmds[0].argv) {
     7141                        G.last_exitcode = rcode = EXIT_SUCCESS;
     7142                        debug_printf_exec(": null FOR: exitcode EXIT_SUCCESS\n");
     7143                        break;
     7144                    }
     7145                    vals = pi->next->cmds[0].argv;
     7146                } /* else: "for var; do..." -> assume "$@" list */
     7147                /* create list of variable values */
     7148                debug_print_strings("for_list made from", vals);
     7149                for_list = expand_strvec_to_strvec(vals);
     7150                for_lcur = for_list;
     7151                debug_print_strings("for_list", for_list);
     7152            }
     7153            if (!*for_lcur) {
     7154                /* "for" loop is over, clean up */
     7155                free(for_list);
     7156                for_list = NULL;
     7157                for_lcur = NULL;
     7158                break;
     7159            }
     7160            /* Insert next value from for_lcur */
     7161            /* note: *for_lcur already has quotes removed, $var expanded, etc */
     7162            set_local_var(xasprintf("%s=%s", pi->cmds[0].argv[0], *for_lcur++), /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ 0);
     7163            continue;
     7164        }
     7165        if (rword == RES_IN) {
     7166            continue; /* "for v IN list;..." - "in" has no cmds anyway */
     7167        }
     7168        if (rword == RES_DONE) {
     7169            continue; /* "done" has no cmds too */
     7170        }
     7171#endif
     7172#if ENABLE_HUSH_CASE
     7173        if (rword == RES_CASE) {
     7174            case_word = expand_strvec_to_string(pi->cmds->argv);
     7175            continue;
     7176        }
     7177        if (rword == RES_MATCH) {
     7178            char **argv;
     7179
     7180            if (!case_word) /* "case ... matched_word) ... WORD)": we executed selected branch, stop */
     7181                break;
     7182            /* all prev words didn't match, does this one match? */
     7183            argv = pi->cmds->argv;
     7184            while (*argv) {
     7185                char *pattern = expand_string_to_string(*argv, /*unbackslash:*/ 1);
     7186                /* TODO: which FNM_xxx flags to use? */
     7187                cond_code = (fnmatch(pattern, case_word, /*flags:*/ 0) != 0);
     7188                free(pattern);
     7189                if (cond_code == 0) { /* match! we will execute this branch */
     7190                    free(case_word); /* make future "word)" stop */
     7191                    case_word = NULL;
     7192                    break;
     7193                }
     7194                argv++;
     7195            }
     7196            continue;
     7197        }
     7198        if (rword == RES_CASE_BODY) { /* inside of a case branch */
     7199            if (cond_code != 0)
     7200                continue; /* not matched yet, skip this pipe */
     7201        }
     7202#endif
     7203        /* Just pressing <enter> in shell should check for jobs.
     7204         * OTOH, in non-interactive shell this is useless
     7205         * and only leads to extra job checks */
     7206        if (pi->num_cmds == 0) {
     7207            if (G_interactive_fd)
     7208                goto check_jobs_and_continue;
     7209            continue;
     7210        }
     7211
     7212        /* After analyzing all keywords and conditions, we decided
     7213         * to execute this pipe. NB: have to do checkjobs(NULL)
     7214         * after run_pipe to collect any background children,
     7215         * even if list execution is to be stopped. */
     7216        debug_printf_exec(": run_pipe with %d members\n", pi->num_cmds);
     7217        {
     7218            int r;
     7219#if ENABLE_HUSH_LOOPS
     7220            G.flag_break_continue = 0;
     7221#endif
     7222            rcode = r = run_pipe(pi); /* NB: rcode is a smallint */
     7223            if (r != -1) {
     7224                /* We ran a builtin, function, or group.
     7225                 * rcode is already known
     7226                 * and we don't need to wait for anything. */
     7227                G.last_exitcode = rcode;
     7228                debug_printf_exec(": builtin/func exitcode %d\n", rcode);
     7229                check_and_run_traps(0);
     7230#if ENABLE_HUSH_LOOPS
     7231                /* Was it "break" or "continue"? */
     7232                if (G.flag_break_continue) {
     7233                    smallint fbc = G.flag_break_continue;
     7234                    /* We might fall into outer *loop*,
     7235                     * don't want to break it too */
     7236                    if (loop_top) {
     7237                        G.depth_break_continue--;
     7238                        if (G.depth_break_continue == 0)
     7239                            G.flag_break_continue = 0;
     7240                        /* else: e.g. "continue 2" should *break* once, *then* continue */
     7241                    } /* else: "while... do... { we are here (innermost list is not a loop!) };...done" */
     7242                    if (G.depth_break_continue != 0 || fbc == BC_BREAK)
     7243                        goto check_jobs_and_break;
     7244                    /* "continue": simulate end of loop */
     7245                    rword = RES_DONE;
     7246                    continue;
     7247                }
     7248#endif
     7249#if ENABLE_HUSH_FUNCTIONS
     7250                if (G.flag_return_in_progress == 1) {
     7251                    /* same as "goto check_jobs_and_break" */
     7252                    checkjobs(NULL);
     7253                    break;
     7254                }
     7255#endif
     7256            } else if (pi->followup == PIPE_BG) {
     7257                /* What does bash do with attempts to background builtins? */
     7258                /* even bash 3.2 doesn't do that well with nested bg:
     7259                 * try "{ { sleep 10; echo DEEP; } & echo HERE; } &".
     7260                 * I'm NOT treating inner &'s as jobs */
     7261                check_and_run_traps(0);
    19817262#if ENABLE_HUSH_JOB
    1982     /* Example of nested list: "while true; do { sleep 1 | exit 2; } done".
    1983      * We are saving state before entering outermost list ("while...done")
    1984      * so that ctrl-Z will correctly background _entire_ outermost list,
    1985      * not just a part of it (like "sleep 1 | exit 2") */
    1986     if (++run_list_level == 1 && interactive_fd) {
    1987         if (sigsetjmp(toplevel_jb, 1)) {
    1988             /* ctrl-Z forked and we are parent; or ctrl-C.
    1989              * Sighandler has longjmped us here */
    1990             signal(SIGINT, SIG_IGN);
    1991             signal(SIGTSTP, SIG_IGN);
    1992             /* Restore level (we can be coming from deep inside
    1993              * nested levels) */
    1994             run_list_level = 1;
    1995 #if ENABLE_FEATURE_SH_STANDALONE
    1996             if (nofork_save.saved) { /* if save area is valid */
    1997                 debug_printf_jobs("exiting nofork early\n");
    1998                 restore_nofork_data(&nofork_save);
    1999             }
    2000 #endif
    2001             if (ctrl_z_flag) {
    2002                 /* ctrl-Z has forked and stored pid of the child in pi->pid.
    2003                  * Remember this child as background job */
    2004                 insert_bg_job(pi);
     7263                if (G.run_list_level == 1)
     7264                    insert_bg_job(pi);
     7265#endif
     7266                /* Last command's pid goes to $! */
     7267                G.last_bg_pid = pi->cmds[pi->num_cmds - 1].pid;
     7268                G.last_exitcode = rcode = EXIT_SUCCESS;
     7269                debug_printf_exec(": cmd&: exitcode EXIT_SUCCESS\n");
    20057270            } else {
    2006                 /* ctrl-C. We just stop doing whatever we were doing */
    2007                 putchar('\n');
    2008             }
    2009             rcode = 0;
    2010             goto ret;
    2011         }
    2012         /* ctrl-Z handler will store pid etc in pi */
    2013         toplevel_list = pi;
    2014         ctrl_z_flag = 0;
    2015 #if ENABLE_FEATURE_SH_STANDALONE
    2016         nofork_save.saved = 0; /* in case we will run a nofork later */
    2017 #endif
    2018         signal_SA_RESTART(SIGTSTP, handler_ctrl_z);
    2019         signal(SIGINT, handler_ctrl_c);
    2020     }
    2021 #endif
    2022 
    2023     for (; pi; pi = flag_restore ? rpipe : pi->next) {
    2024         rword = pi->res_word;
    2025 #if ENABLE_HUSH_LOOPS
    2026         if (rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR) {
    2027             flag_restore = 0;
    2028             if (!rpipe) {
    2029                 flag_rep = 0;
    2030                 rpipe = pi;
    2031             }
    2032         }
    2033 #endif
    2034         debug_printf_exec(": rword=%d if_code=%d next_if_code=%d skip_more=%d\n",
    2035                 rword, if_code, next_if_code, skip_more_for_this_rword);
    2036         if (rword == skip_more_for_this_rword && flag_skip) {
    2037             if (pi->followup == PIPE_SEQ)
    2038                 flag_skip = 0;
    2039             continue;
    2040         }
    2041         flag_skip = 1;
    2042         skip_more_for_this_rword = RES_XXXX;
    2043 #if ENABLE_HUSH_IF
    2044         if (rword == RES_THEN || rword == RES_ELSE)
    2045             if_code = next_if_code;
    2046         if (rword == RES_THEN && if_code)
    2047             continue;
    2048         if (rword == RES_ELSE && !if_code)
    2049             continue;
    2050         if (rword == RES_ELIF && !if_code)
    2051             break;
    2052 #endif
    2053 #if ENABLE_HUSH_LOOPS
    2054         if (rword == RES_FOR && pi->num_progs) {
    2055             if (!for_lcur) {
    2056                 /* if no variable values after "in" we skip "for" */
    2057                 if (!pi->next->progs->argv)
    2058                     continue;
    2059                 /* create list of variable values */
    2060                 for_list = expand_strvec_to_strvec(pi->next->progs->argv);
    2061                 for_lcur = for_list;
    2062                 for_varname = pi->progs->argv[0];
    2063                 pi->progs->argv[0] = NULL;
    2064                 flag_rep = 1;
    2065             }
    2066             free(pi->progs->argv[0]);
    2067             if (!*for_lcur) {
    2068                 free(for_list);
    2069                 for_lcur = NULL;
    2070                 flag_rep = 0;
    2071                 pi->progs->argv[0] = for_varname;
    2072                 pi->progs->glob_result.gl_pathv[0] = pi->progs->argv[0];
    2073                 continue;
    2074             }
    2075             /* insert next value from for_lcur */
    2076             /* vda: does it need escaping? */
    2077             pi->progs->argv[0] = xasprintf("%s=%s", for_varname, *for_lcur++);
    2078             pi->progs->glob_result.gl_pathv[0] = pi->progs->argv[0];
    2079         }
    2080         if (rword == RES_IN)
    2081             continue;
    2082         if (rword == RES_DO) {
    2083             if (!flag_rep)
    2084                 continue;
    2085         }
    2086         if (rword == RES_DONE) {
    2087             if (flag_rep) {
    2088                 flag_restore = 1;
    2089             } else {
    2090                 rpipe = NULL;
    2091             }
    2092         }
    2093 #endif
    2094         if (pi->num_progs == 0)
    2095             continue;
    2096         save_num_progs = pi->num_progs; /* save number of programs */
    2097         debug_printf_exec(": run_pipe_real with %d members\n", pi->num_progs);
    2098         rcode = run_pipe_real(pi);
    2099         if (rcode != -1) {
    2100             /* We only ran a builtin: rcode was set by the return value
    2101              * of run_pipe_real(), and we don't need to wait for anything. */
    2102         } else if (pi->followup == PIPE_BG) {
    2103             /* What does bash do with attempts to background builtins? */
    2104             /* Even bash 3.2 doesn't do that well with nested bg:
    2105              * try "{ { sleep 10; echo DEEP; } & echo HERE; } &".
    2106              * I'm NOT treating inner &'s as jobs */
    21077271#if ENABLE_HUSH_JOB
    2108             if (run_list_level == 1)
    2109                 insert_bg_job(pi);
    2110 #endif
    2111             rcode = EXIT_SUCCESS;
    2112         } else {
    2113 #if ENABLE_HUSH_JOB
    2114             /* Paranoia, just "interactive_fd" should be enough? */
    2115             if (run_list_level == 1 && interactive_fd) {
    2116                 /* waits for completion, then fg's main shell */
    2117                 rcode = checkjobs_and_fg_shell(pi);
    2118             } else
    2119 #endif
    2120             {
    2121                 /* this one just waits for completion */
    2122                 rcode = checkjobs(pi);
    2123             }
    2124             debug_printf_exec(": checkjobs returned %d\n", rcode);
    2125         }
    2126         debug_printf_exec(": setting last_return_code=%d\n", rcode);
    2127         last_return_code = rcode;
    2128         pi->num_progs = save_num_progs; /* restore number of programs */
     7272                if (G.run_list_level == 1 && G_interactive_fd) {
     7273                    /* Waits for completion, then fg's main shell */
     7274                    rcode = checkjobs_and_fg_shell(pi);
     7275                    debug_printf_exec(": checkjobs_and_fg_shell exitcode %d\n", rcode);
     7276                    check_and_run_traps(0);
     7277                } else
     7278#endif
     7279                { /* This one just waits for completion */
     7280                    rcode = checkjobs(pi);
     7281                    debug_printf_exec(": checkjobs exitcode %d\n", rcode);
     7282                    check_and_run_traps(0);
     7283                }
     7284                G.last_exitcode = rcode;
     7285            }
     7286        }
     7287
     7288        /* Analyze how result affects subsequent commands */
    21297289#if ENABLE_HUSH_IF
    21307290        if (rword == RES_IF || rword == RES_ELIF)
    2131             next_if_code = rcode;  /* can be overwritten a number of times */
     7291            cond_code = rcode;
    21327292#endif
    21337293#if ENABLE_HUSH_LOOPS
    2134         if (rword == RES_WHILE)
    2135             flag_rep = !last_return_code;
    2136         if (rword == RES_UNTIL)
    2137             flag_rep = last_return_code;
    2138 #endif
    2139         if ((rcode == EXIT_SUCCESS && pi->followup == PIPE_OR)
    2140          || (rcode != EXIT_SUCCESS && pi->followup == PIPE_AND)
    2141         ) {
    2142             skip_more_for_this_rword = rword;
    2143         }
     7294        /* Beware of "while false; true; do ..."! */
     7295        if (pi->next && pi->next->res_word == RES_DO) {
     7296            if (rword == RES_WHILE) {
     7297                if (rcode) {
     7298                    /* "while false; do...done" - exitcode 0 */
     7299                    G.last_exitcode = rcode = EXIT_SUCCESS;
     7300                    debug_printf_exec(": while expr is false: breaking (exitcode:EXIT_SUCCESS)\n");
     7301                    goto check_jobs_and_break;
     7302                }
     7303            }
     7304            if (rword == RES_UNTIL) {
     7305                if (!rcode) {
     7306                    debug_printf_exec(": until expr is true: breaking\n");
     7307 check_jobs_and_break:
     7308                    checkjobs(NULL);
     7309                    break;
     7310                }
     7311            }
     7312        }
     7313#endif
     7314
     7315 check_jobs_and_continue:
    21447316        checkjobs(NULL);
    2145     }
     7317    } /* for (pi) */
    21467318
    21477319#if ENABLE_HUSH_JOB
    2148     if (ctrl_z_flag) {
    2149         /* ctrl-Z forked somewhere in the past, we are the child,
    2150          * and now we completed running the list. Exit. */
    2151         exit(rcode);
    2152     }
    2153  ret:
    2154     if (!--run_list_level && interactive_fd) {
    2155         signal(SIGTSTP, SIG_IGN);
    2156         signal(SIGINT, SIG_IGN);
    2157     }
    2158 #endif
    2159     debug_printf_exec("run_list_real lvl %d return %d\n", run_list_level + 1, rcode);
     7320    G.run_list_level--;
     7321#endif
     7322#if ENABLE_HUSH_LOOPS
     7323    if (loop_top)
     7324        G.depth_of_loop--;
     7325    free(for_list);
     7326#endif
     7327#if ENABLE_HUSH_CASE
     7328    free(case_word);
     7329#endif
     7330    debug_leave();
     7331    debug_printf_exec("run_list lvl %d return %d\n", G.run_list_level + 1, rcode);
    21607332    return rcode;
    21617333}
    21627334
    2163 /* return code is the exit status of the pipe */
    2164 static int free_pipe(struct pipe *pi, int indent)
    2165 {
    2166     char **p;
    2167     struct child_prog *child;
    2168     struct redir_struct *r, *rnext;
    2169     int a, i, ret_code = 0;
    2170 
    2171     if (pi->stopped_progs > 0)
    2172         return ret_code;
    2173     debug_printf_clean("%s run pipe: (pid %d)\n", indenter(indent), getpid());
    2174     for (i = 0; i < pi->num_progs; i++) {
    2175         child = &pi->progs[i];
    2176         debug_printf_clean("%s  command %d:\n", indenter(indent), i);
    2177         if (child->argv) {
    2178             for (a = 0, p = child->argv; *p; a++, p++) {
    2179                 debug_printf_clean("%s   argv[%d] = %s\n", indenter(indent), a, *p);
    2180             }
    2181             globfree(&child->glob_result);
    2182             child->argv = NULL;
    2183         } else if (child->group) {
    2184             debug_printf_clean("%s   begin group (subshell:%d)\n", indenter(indent), child->subshell);
    2185             ret_code = free_pipe_list(child->group, indent+3);
    2186             debug_printf_clean("%s   end group\n", indenter(indent));
    2187         } else {
    2188             debug_printf_clean("%s   (nil)\n", indenter(indent));
    2189         }
    2190         for (r = child->redirects; r; r = rnext) {
    2191             debug_printf_clean("%s   redirect %d%s", indenter(indent), r->fd, redir_table[r->type].descrip);
    2192             if (r->dup == -1) {
    2193                 /* guard against the case >$FOO, where foo is unset or blank */
    2194                 if (r->word.gl_pathv) {
    2195                     debug_printf_clean(" %s\n", *r->word.gl_pathv);
    2196                     globfree(&r->word);
    2197                 }
    2198             } else {
    2199                 debug_printf_clean("&%d\n", r->dup);
    2200             }
    2201             rnext = r->next;
    2202             free(r);
    2203         }
    2204         child->redirects = NULL;
    2205     }
    2206     free(pi->progs);   /* children are an array, they get freed all at once */
    2207     pi->progs = NULL;
     7335/* Select which version we will use */
     7336static int run_and_free_list(struct pipe *pi)
     7337{
     7338    int rcode = 0;
     7339    debug_printf_exec("run_and_free_list entered\n");
     7340    if (!G.n_mode) {
     7341        debug_printf_exec(": run_list: 1st pipe with %d cmds\n", pi->num_cmds);
     7342        rcode = run_list(pi);
     7343    }
     7344    /* free_pipe_list has the side effect of clearing memory.
     7345     * In the long run that function can be merged with run_list,
     7346     * but doing that now would hobble the debugging effort. */
     7347    free_pipe_list(pi);
     7348    debug_printf_exec("run_and_free_list return %d\n", rcode);
     7349    return rcode;
     7350}
     7351
     7352
     7353/* Called a few times only (or even once if "sh -c") */
     7354static void init_sigmasks(void)
     7355{
     7356    unsigned sig;
     7357    unsigned mask;
     7358    sigset_t old_blocked_set;
     7359
     7360    if (!G.inherited_set_is_saved) {
     7361        sigprocmask(SIG_SETMASK, NULL, &G.blocked_set);
     7362        G.inherited_set = G.blocked_set;
     7363    }
     7364    old_blocked_set = G.blocked_set;
     7365
     7366    mask = (1 << SIGQUIT);
     7367    if (G_interactive_fd) {
     7368        mask = (1 << SIGQUIT) | SPECIAL_INTERACTIVE_SIGS;
     7369        if (G_saved_tty_pgrp) /* we have ctty, job control sigs work */
     7370            mask |= SPECIAL_JOB_SIGS;
     7371    }
     7372    G.non_DFL_mask = mask;
     7373
     7374    sig = 0;
     7375    while (mask) {
     7376        if (mask & 1)
     7377            sigaddset(&G.blocked_set, sig);
     7378        mask >>= 1;
     7379        sig++;
     7380    }
     7381    sigdelset(&G.blocked_set, SIGCHLD);
     7382
     7383    if (memcmp(&old_blocked_set, &G.blocked_set, sizeof(old_blocked_set)) != 0)
     7384        sigprocmask(SIG_SETMASK, &G.blocked_set, NULL);
     7385
     7386    /* POSIX allows shell to re-enable SIGCHLD
     7387     * even if it was SIG_IGN on entry */
     7388#if ENABLE_HUSH_FAST
     7389    G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */
     7390    if (!G.inherited_set_is_saved)
     7391        signal(SIGCHLD, SIGCHLD_handler);
     7392#else
     7393    if (!G.inherited_set_is_saved)
     7394        signal(SIGCHLD, SIG_DFL);
     7395#endif
     7396
     7397    G.inherited_set_is_saved = 1;
     7398}
     7399
    22087400#if ENABLE_HUSH_JOB
    2209     free(pi->cmdtext);
    2210     pi->cmdtext = NULL;
    2211 #endif
    2212     return ret_code;
    2213 }
    2214 
    2215 static int free_pipe_list(struct pipe *head, int indent)
    2216 {
    2217     int rcode = 0;   /* if list has no members */
    2218     struct pipe *pi, *next;
    2219 
    2220     for (pi = head; pi; pi = next) {
    2221         debug_printf_clean("%s pipe reserved mode %d\n", indenter(indent), pi->res_word);
    2222         rcode = free_pipe(pi, indent);
    2223         debug_printf_clean("%s pipe followup code %d\n", indenter(indent), pi->followup);
    2224         next = pi->next;
    2225         /*pi->next = NULL;*/
    2226         free(pi);
    2227     }
    2228     return rcode;
    2229 }
    2230 
    2231 /* Select which version we will use */
    2232 static int run_list(struct pipe *pi)
    2233 {
    2234     int rcode = 0;
    2235     debug_printf_exec("run_list entered\n");
    2236     if (fake_mode == 0) {
    2237         debug_printf_exec(": run_list_real with %d members\n", pi->num_progs);
    2238         rcode = run_list_real(pi);
    2239     }
    2240     /* free_pipe_list has the side effect of clearing memory.
    2241      * In the long run that function can be merged with run_list_real,
    2242      * but doing that now would hobble the debugging effort. */
    2243     free_pipe_list(pi, 0);
    2244     debug_printf_exec("run_list return %d\n", rcode);
    2245     return rcode;
    2246 }
    2247 
    2248 /* The API for glob is arguably broken.  This routine pushes a non-matching
    2249  * string into the output structure, removing non-backslashed backslashes.
    2250  * If someone can prove me wrong, by performing this function within the
    2251  * original glob(3) api, feel free to rewrite this routine into oblivion.
    2252  * Return code (0 vs. GLOB_NOSPACE) matches glob(3).
    2253  * XXX broken if the last character is '\\', check that before calling.
    2254  */
    2255 static int globhack(const char *src, int flags, glob_t *pglob)
    2256 {
    2257     int cnt = 0, pathc;
    2258     const char *s;
    2259     char *dest;
    2260     for (cnt = 1, s = src; s && *s; s++) {
    2261         if (*s == '\\') s++;
    2262         cnt++;
    2263     }
    2264     dest = xmalloc(cnt);
    2265     if (!(flags & GLOB_APPEND)) {
    2266         pglob->gl_pathv = NULL;
    2267         pglob->gl_pathc = 0;
    2268         pglob->gl_offs = 0;
    2269         pglob->gl_offs = 0;
    2270     }
    2271     pathc = ++pglob->gl_pathc;
    2272     pglob->gl_pathv = xrealloc(pglob->gl_pathv, (pathc+1) * sizeof(*pglob->gl_pathv));
    2273     pglob->gl_pathv[pathc-1] = dest;
    2274     pglob->gl_pathv[pathc] = NULL;
    2275     for (s = src; s && *s; s++, dest++) {
    2276         if (*s == '\\') s++;
    2277         *dest = *s;
    2278     }
    2279     *dest = '\0';
    2280     return 0;
    2281 }
    2282 
    2283 /* XXX broken if the last character is '\\', check that before calling */
    2284 static int glob_needed(const char *s)
    2285 {
    2286     for (; *s; s++) {
    2287         if (*s == '\\') s++;
    2288         if (strchr("*[?", *s)) return 1;
    2289     }
    2290     return 0;
    2291 }
    2292 
    2293 static int xglob(o_string *dest, int flags, glob_t *pglob)
    2294 {
    2295     int gr;
    2296 
    2297     /* short-circuit for null word */
    2298     /* we can code this better when the debug_printf's are gone */
    2299     if (dest->length == 0) {
    2300         if (dest->nonnull) {
    2301             /* bash man page calls this an "explicit" null */
    2302             gr = globhack(dest->data, flags, pglob);
    2303             debug_printf("globhack returned %d\n", gr);
    2304         } else {
    2305             return 0;
    2306         }
    2307     } else if (glob_needed(dest->data)) {
    2308         gr = glob(dest->data, flags, NULL, pglob);
    2309         debug_printf("glob returned %d\n", gr);
    2310         if (gr == GLOB_NOMATCH) {
    2311             /* quote removal, or more accurately, backslash removal */
    2312             gr = globhack(dest->data, flags, pglob);
    2313             debug_printf("globhack returned %d\n", gr);
    2314         }
    2315     } else {
    2316         gr = globhack(dest->data, flags, pglob);
    2317         debug_printf("globhack returned %d\n", gr);
    2318     }
    2319     if (gr == GLOB_NOSPACE)
    2320         bb_error_msg_and_die("out of memory during glob");
    2321     if (gr != 0) { /* GLOB_ABORTED ? */
    2322         bb_error_msg("glob(3) error %d", gr);
    2323     }
    2324     /* globprint(glob_target); */
    2325     return gr;
    2326 }
    2327 
    2328 /* expand_strvec_to_strvec() takes a list of strings, expands
    2329  * all variable references within and returns a pointer to
    2330  * a list of expanded strings, possibly with larger number
    2331  * of strings. (Think VAR="a b"; echo $VAR).
    2332  * This new list is allocated as a single malloc block.
    2333  * NULL-terminated list of char* pointers is at the beginning of it,
    2334  * followed by strings themself.
    2335  * Caller can deallocate entire list by single free(list). */
    2336 
    2337 /* Helpers first:
    2338  * count_XXX estimates size of the block we need. It's okay
    2339  * to over-estimate sizes a bit, if it makes code simpler */
    2340 static int count_ifs(const char *str)
    2341 {
    2342     int cnt = 0;
    2343     debug_printf_expand("count_ifs('%s') ifs='%s'", str, ifs);
    2344     while (1) {
    2345         str += strcspn(str, ifs);
    2346         if (!*str) break;
    2347         str++; /* str += strspn(str, ifs); */
    2348         cnt++; /* cnt += strspn(str, ifs); - but this code is larger */
    2349     }
    2350     debug_printf_expand(" return %d\n", cnt);
    2351     return cnt;
    2352 }
    2353 
    2354 static void count_var_expansion_space(int *countp, int *lenp, char *arg)
    2355 {
    2356     char first_ch;
    2357     int i;
    2358     int len = *lenp;
    2359     int count = *countp;
    2360     const char *val;
    2361     char *p;
    2362 
    2363     while ((p = strchr(arg, SPECIAL_VAR_SYMBOL))) {
    2364         len += p - arg;
    2365         arg = ++p;
    2366         p = strchr(p, SPECIAL_VAR_SYMBOL);
    2367         first_ch = arg[0];
    2368 
    2369         switch (first_ch & 0x7f) {
    2370         /* high bit in 1st_ch indicates that var is double-quoted */
    2371         case '$': /* pid */
    2372         case '!': /* bg pid */
    2373         case '?': /* exitcode */
    2374         case '#': /* argc */
    2375             len += sizeof(int)*3 + 1; /* enough for int */
     7401/* helper */
     7402static void maybe_set_to_sigexit(int sig)
     7403{
     7404    void (*handler)(int);
     7405    /* non_DFL_mask'ed signals are, well, masked,
     7406     * no need to set handler for them.
     7407     */
     7408    if (!((G.non_DFL_mask >> sig) & 1)) {
     7409        handler = signal(sig, sigexit);
     7410        if (handler == SIG_IGN) /* oops... restore back to IGN! */
     7411            signal(sig, handler);
     7412    }
     7413}
     7414/* Set handlers to restore tty pgrp and exit */
     7415static void set_fatal_handlers(void)
     7416{
     7417    /* We _must_ restore tty pgrp on fatal signals */
     7418    if (HUSH_DEBUG) {
     7419        maybe_set_to_sigexit(SIGILL );
     7420        maybe_set_to_sigexit(SIGFPE );
     7421        maybe_set_to_sigexit(SIGBUS );
     7422        maybe_set_to_sigexit(SIGSEGV);
     7423        maybe_set_to_sigexit(SIGTRAP);
     7424    } /* else: hush is perfect. what SEGV? */
     7425    maybe_set_to_sigexit(SIGABRT);
     7426    /* bash 3.2 seems to handle these just like 'fatal' ones */
     7427    maybe_set_to_sigexit(SIGPIPE);
     7428    maybe_set_to_sigexit(SIGALRM);
     7429    /* if we are interactive, SIGHUP, SIGTERM and SIGINT are masked.
     7430     * if we aren't interactive... but in this case
     7431     * we never want to restore pgrp on exit, and this fn is not called */
     7432    /*maybe_set_to_sigexit(SIGHUP );*/
     7433    /*maybe_set_to_sigexit(SIGTERM);*/
     7434    /*maybe_set_to_sigexit(SIGINT );*/
     7435}
     7436#endif
     7437
     7438static int set_mode(int state, char mode, const char *o_opt)
     7439{
     7440    int idx;
     7441    switch (mode) {
     7442    case 'n':
     7443        G.n_mode = state;
     7444        break;
     7445    case 'x':
     7446        IF_HUSH_MODE_X(G_x_mode = state;)
     7447        break;
     7448    case 'o':
     7449        if (!o_opt) {
     7450            /* "set -+o" without parameter.
     7451             * in bash, set -o produces this output:
     7452             *  pipefail        off
     7453             * and set +o:
     7454             *  set +o pipefail
     7455             * We always use the second form.
     7456             */
     7457            const char *p = o_opt_strings;
     7458            idx = 0;
     7459            while (*p) {
     7460                printf("set %co %s\n", (G.o_opt[idx] ? '-' : '+'), p);
     7461                idx++;
     7462                p += strlen(p) + 1;
     7463            }
    23767464            break;
    2377         case '*':
    2378         case '@':
    2379             for (i = 1; i < global_argc; i++) {
    2380                 len += strlen(global_argv[i]) + 1;
    2381                 count++;
    2382                 if (!(first_ch & 0x80))
    2383                     count += count_ifs(global_argv[i]);
    2384             }
     7465        }
     7466        idx = index_in_strings(o_opt_strings, o_opt);
     7467        if (idx >= 0) {
     7468            G.o_opt[idx] = state;
    23857469            break;
    2386         default:
    2387             *p = '\0';
    2388             arg[0] = first_ch & 0x7f;
    2389             if (isdigit(arg[0])) {
    2390                 i = xatoi_u(arg);
    2391                 val = NULL;
    2392                 if (i < global_argc)
    2393                     val = global_argv[i];
    2394             } else
    2395                 val = lookup_param(arg);
    2396             arg[0] = first_ch;
    2397             *p = SPECIAL_VAR_SYMBOL;
    2398 
    2399             if (val) {
    2400                 len += strlen(val) + 1;
    2401                 if (!(first_ch & 0x80))
    2402                     count += count_ifs(val);
    2403             }
    2404         }
    2405         arg = ++p;
    2406     }
    2407 
    2408     len += strlen(arg) + 1;
    2409     count++;
    2410     *lenp = len;
    2411     *countp = count;
    2412 }
    2413 
    2414 /* Store given string, finalizing the word and starting new one whenever
    2415  * we encounter ifs char(s). This is used for expanding variable values.
    2416  * End-of-string does NOT finalize word: think about 'echo -$VAR-' */
    2417 static int expand_on_ifs(char **list, int n, char **posp, const char *str)
    2418 {
    2419     char *pos = *posp;
    2420     while (1) {
    2421         int word_len = strcspn(str, ifs);
    2422         if (word_len) {
    2423             memcpy(pos, str, word_len); /* store non-ifs chars */
    2424             pos += word_len;
    2425             str += word_len;
    2426         }
    2427         if (!*str)  /* EOL - do not finalize word */
    2428             break;
    2429         *pos++ = '\0';
    2430         if (n) debug_printf_expand("expand_on_ifs finalized list[%d]=%p '%s' "
    2431             "strlen=%d next=%p pos=%p\n", n-1, list[n-1], list[n-1],
    2432             strlen(list[n-1]), list[n-1] + strlen(list[n-1]) + 1, pos);
    2433         list[n++] = pos;
    2434         str += strspn(str, ifs); /* skip ifs chars */
    2435     }
    2436     *posp = pos;
    2437     return n;
    2438 }
    2439 
    2440 /* Expand all variable references in given string, adding words to list[]
    2441  * at n, n+1,... positions. Return updated n (so that list[n] is next one
    2442  * to be filled). This routine is extremely tricky: has to deal with
    2443  * variables/parameters with whitespace, $* and $@, and constructs like
    2444  * 'echo -$*-'. If you play here, you must run testsuite afterwards! */
    2445 /* NB: another bug is that we cannot detect empty strings yet:
    2446  * "" or $empty"" expands to zero words, has to expand to empty word */
    2447 static int expand_vars_to_list(char **list, int n, char **posp, char *arg, char or_mask)
    2448 {
    2449     /* or_mask is either 0 (normal case) or 0x80
    2450      * (expansion of right-hand side of assignment == 1-element expand) */
    2451 
    2452     char first_ch, ored_ch;
    2453     int i;
    2454     const char *val;
    2455     char *p;
    2456     char *pos = *posp;
    2457 
    2458     ored_ch = 0;
    2459 
    2460     if (n) debug_printf_expand("expand_vars_to_list finalized list[%d]=%p '%s' "
    2461         "strlen=%d next=%p pos=%p\n", n-1, list[n-1], list[n-1],
    2462         strlen(list[n-1]), list[n-1] + strlen(list[n-1]) + 1, pos);
    2463     list[n++] = pos;
    2464 
    2465     while ((p = strchr(arg, SPECIAL_VAR_SYMBOL))) {
    2466         memcpy(pos, arg, p - arg);
    2467         pos += (p - arg);
    2468         arg = ++p;
    2469         p = strchr(p, SPECIAL_VAR_SYMBOL);
    2470 
    2471         first_ch = arg[0] | or_mask; /* forced to "quoted" if or_mask = 0x80 */
    2472         ored_ch |= first_ch;
    2473         val = NULL;
    2474         switch (first_ch & 0x7f) {
    2475         /* Highest bit in first_ch indicates that var is double-quoted */
    2476         case '$': /* pid */
    2477             /* FIXME: (echo $$) should still print pid of main shell */
    2478             val = utoa(getpid());
    2479             break;
    2480         case '!': /* bg pid */
    2481             val = last_bg_pid ? utoa(last_bg_pid) : (char*)"";
    2482             break;
    2483         case '?': /* exitcode */
    2484             val = utoa(last_return_code);
    2485             break;
    2486         case '#': /* argc */
    2487             val = utoa(global_argc ? global_argc-1 : 0);
    2488             break;
    2489         case '*':
    2490         case '@':
    2491             i = 1;
    2492             if (!(first_ch & 0x80)) { /* unquoted $* or $@ */
    2493                 while (i < global_argc) {
    2494                     n = expand_on_ifs(list, n, &pos, global_argv[i]);
    2495                     debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, global_argc-1);
    2496                     if (global_argv[i++][0] && i < global_argc) {
    2497                         /* this argv[] is not empty and not last:
    2498                          * put terminating NUL, start new word */
    2499                         *pos++ = '\0';
    2500                         if (n) debug_printf_expand("expand_vars_to_list 2 finalized list[%d]=%p '%s' "
    2501                             "strlen=%d next=%p pos=%p\n", n-1, list[n-1], list[n-1],
    2502                             strlen(list[n-1]), list[n-1] + strlen(list[n-1]) + 1, pos);
    2503                         list[n++] = pos;
    2504                     }
    2505                 }
    2506             } else
    2507             /* If or_mask is nonzero, we handle assignment 'a=....$@.....'
    2508              * and in this case should theat it like '$*' */
    2509             if (first_ch == ('@'|0x80) && !or_mask) { /* quoted $@ */
    2510                 while (1) {
    2511                     strcpy(pos, global_argv[i]);
    2512                     pos += strlen(global_argv[i]);
    2513                     if (++i >= global_argc)
    2514                         break;
    2515                     *pos++ = '\0';
    2516                     if (n) debug_printf_expand("expand_vars_to_list 3 finalized list[%d]=%p '%s' "
    2517                         "strlen=%d next=%p pos=%p\n", n-1, list[n-1], list[n-1],
    2518                             strlen(list[n-1]), list[n-1] + strlen(list[n-1]) + 1, pos);
    2519                     list[n++] = pos;
    2520                 }
    2521             } else { /* quoted $*: add as one word */
    2522                 while (1) {
    2523                     strcpy(pos, global_argv[i]);
    2524                     pos += strlen(global_argv[i]);
    2525                     if (++i >= global_argc)
    2526                         break;
    2527                     if (ifs[0])
    2528                         *pos++ = ifs[0];
    2529                 }
    2530             }
    2531             break;
    2532         default:
    2533             *p = '\0';
    2534             arg[0] = first_ch & 0x7f;
    2535             if (isdigit(arg[0])) {
    2536                 i = xatoi_u(arg);
    2537                 val = NULL;
    2538                 if (i < global_argc)
    2539                     val = global_argv[i];
    2540             } else
    2541                 val = lookup_param(arg);
    2542             arg[0] = first_ch;
    2543             *p = SPECIAL_VAR_SYMBOL;
    2544             if (!(first_ch & 0x80)) { /* unquoted $VAR */
    2545                 if (val) {
    2546                     n = expand_on_ifs(list, n, &pos, val);
    2547                     val = NULL;
    2548                 }
    2549             } /* else: quoted $VAR, val will be appended at pos */
    2550         }
    2551         if (val) {
    2552             strcpy(pos, val);
    2553             pos += strlen(val);
    2554         }
    2555         arg = ++p;
    2556     }
    2557     debug_printf_expand("expand_vars_to_list adding tail '%s' at %p\n", arg, pos);
    2558     strcpy(pos, arg);
    2559     pos += strlen(arg) + 1;
    2560     if (pos == list[n-1] + 1) { /* expansion is empty */
    2561         if (!(ored_ch & 0x80)) { /* all vars were not quoted... */
    2562             debug_printf_expand("expand_vars_to_list list[%d] empty, going back\n", n);
    2563             pos--;
    2564             n--;
    2565         }
    2566     }
    2567 
    2568     *posp = pos;
    2569     return n;
    2570 }
    2571 
    2572 static char **expand_variables(char **argv, char or_mask)
    2573 {
    2574     int n;
    2575     int count = 1;
    2576     int len = 0;
    2577     char *pos, **v, **list;
    2578 
    2579     v = argv;
    2580     if (!*v) debug_printf_expand("count_var_expansion_space: "
    2581             "argv[0]=NULL count=%d len=%d alloc_space=%d\n",
    2582             count, len, sizeof(char*) * count + len);
    2583     while (*v) {
    2584         count_var_expansion_space(&count, &len, *v);
    2585         debug_printf_expand("count_var_expansion_space: "
    2586             "'%s' count=%d len=%d alloc_space=%d\n",
    2587             *v, count, len, sizeof(char*) * count + len);
    2588         v++;
    2589     }
    2590     len += sizeof(char*) * count; /* total to alloc */
    2591     list = xmalloc(len);
    2592     pos = (char*)(list + count);
    2593     debug_printf_expand("list=%p, list[0] should be %p\n", list, pos);
    2594     n = 0;
    2595     v = argv;
    2596     while (*v)
    2597         n = expand_vars_to_list(list, n, &pos, *v++, or_mask);
    2598 
    2599     if (n) debug_printf_expand("finalized list[%d]=%p '%s' "
    2600         "strlen=%d next=%p pos=%p\n", n-1, list[n-1], list[n-1],
    2601         strlen(list[n-1]), list[n-1] + strlen(list[n-1]) + 1, pos);
    2602     list[n] = NULL;
    2603 
    2604 #ifdef DEBUG_EXPAND
    2605     {
    2606         int m = 0;
    2607         while (m <= n) {
    2608             debug_printf_expand("list[%d]=%p '%s'\n", m, list[m], list[m]);
    2609             m++;
    2610         }
    2611         debug_printf_expand("used_space=%d\n", pos - (char*)list);
    2612     }
    2613 #endif
    2614     if (ENABLE_HUSH_DEBUG)
    2615         if (pos - (char*)list > len)
    2616             bb_error_msg_and_die("BUG in varexp");
    2617     return list;
    2618 }
    2619 
    2620 static char **expand_strvec_to_strvec(char **argv)
    2621 {
    2622     return expand_variables(argv, 0);
    2623 }
    2624 
    2625 static char *expand_string_to_string(const char *str)
    2626 {
    2627     char *argv[2], **list;
    2628 
    2629     argv[0] = (char*)str;
    2630     argv[1] = NULL;
    2631     list = expand_variables(argv, 0x80); /* 0x80: make one-element expansion */
    2632     if (ENABLE_HUSH_DEBUG)
    2633         if (!list[0] || list[1])
    2634             bb_error_msg_and_die("BUG in varexp2");
    2635     /* actually, just move string 2*sizeof(char*) bytes back */
    2636     strcpy((char*)list, list[0]);
    2637     debug_printf_expand("string_to_string='%s'\n", (char*)list);
    2638     return (char*)list;
    2639 }
    2640 
    2641 static char* expand_strvec_to_string(char **argv)
    2642 {
    2643     char **list;
    2644 
    2645     list = expand_variables(argv, 0x80);
    2646     /* Convert all NULs to spaces */
    2647     if (list[0]) {
    2648         int n = 1;
    2649         while (list[n]) {
    2650             if (ENABLE_HUSH_DEBUG)
    2651                 if (list[n-1] + strlen(list[n-1]) + 1 != list[n])
    2652                     bb_error_msg_and_die("BUG in varexp3");
    2653             list[n][-1] = ' '; /* TODO: or to ifs[0]? */
    2654             n++;
    2655         }
    2656     }
    2657     strcpy((char*)list, list[0]);
    2658     debug_printf_expand("strvec_to_string='%s'\n", (char*)list);
    2659     return (char*)list;
    2660 }
    2661 
    2662 /* This is used to get/check local shell variables */
    2663 static struct variable *get_local_var(const char *name)
    2664 {
    2665     struct variable *cur;
    2666     int len;
    2667 
    2668     if (!name)
    2669         return NULL;
    2670     len = strlen(name);
    2671     for (cur = top_var; cur; cur = cur->next) {
    2672         if (strncmp(cur->varstr, name, len) == 0 && cur->varstr[len] == '=')
    2673             return cur;
    2674     }
    2675     return NULL;
    2676 }
    2677 
    2678 /* str holds "NAME=VAL" and is expected to be malloced.
    2679  * We take ownership of it. */
    2680 static int set_local_var(char *str, int flg_export)
    2681 {
    2682     struct variable *cur;
    2683     char *value;
    2684     int name_len;
    2685 
    2686     value = strchr(str, '=');
    2687     if (!value) { /* not expected to ever happen? */
    2688         free(str);
    2689         return -1;
    2690     }
    2691 
    2692     name_len = value - str + 1; /* including '=' */
    2693     cur = top_var; /* cannot be NULL (we have HUSH_VERSION and it's RO) */
    2694     while (1) {
    2695         if (strncmp(cur->varstr, str, name_len) != 0) {
    2696             if (!cur->next) {
    2697                 /* Bail out. Note that now cur points
    2698                  * to last var in linked list */
    2699                 break;
    2700             }
    2701             cur = cur->next;
    2702             continue;
    2703         }
    2704         /* We found an existing var with this name */
    2705         *value = '\0';
    2706         if (cur->flg_read_only) {
    2707             bb_error_msg("%s: readonly variable", str);
    2708             free(str);
    2709             return -1;
    2710         }
    2711         unsetenv(str); /* just in case */
    2712         *value = '=';
    2713         if (strcmp(cur->varstr, str) == 0) {
    2714  free_and_exp:
    2715             free(str);
    2716             goto exp;
    2717         }
    2718         if (cur->max_len >= strlen(str)) {
    2719             /* This one is from startup env, reuse space */
    2720             strcpy(cur->varstr, str);
    2721             goto free_and_exp;
    2722         }
    2723         /* max_len == 0 signifies "malloced" var, which we can
    2724          * (and has to) free */
    2725         if (!cur->max_len)
    2726             free(cur->varstr);
    2727         cur->max_len = 0;
    2728         goto set_str_and_exp;
    2729     }
    2730 
    2731     /* Not found - create next variable struct */
    2732     cur->next = xzalloc(sizeof(*cur));
    2733     cur = cur->next;
    2734 
    2735  set_str_and_exp:
    2736     cur->varstr = str;
    2737  exp:
    2738     if (flg_export)
    2739         cur->flg_export = 1;
    2740     if (cur->flg_export)
    2741         return putenv(cur->varstr);
    2742     return 0;
    2743 }
    2744 
    2745 static void unset_local_var(const char *name)
    2746 {
    2747     struct variable *cur;
    2748     struct variable *prev = prev; /* for gcc */
    2749     int name_len;
    2750 
    2751     if (!name)
    2752         return;
    2753     name_len = strlen(name);
    2754     cur = top_var;
    2755     while (cur) {
    2756         if (strncmp(cur->varstr, name, name_len) == 0 && cur->varstr[name_len] == '=') {
    2757             if (cur->flg_read_only) {
    2758                 bb_error_msg("%s: readonly variable", name);
    2759                 return;
    2760             }
    2761         /* prev is ok to use here because 1st variable, HUSH_VERSION,
    2762          * is ro, and we cannot reach this code on the 1st pass */
    2763             prev->next = cur->next;
    2764             unsetenv(cur->varstr);
    2765             if (!cur->max_len)
    2766                 free(cur->varstr);
    2767             free(cur);
    2768             return;
    2769         }
    2770         prev = cur;
    2771         cur = cur->next;
    2772     }
    2773 }
    2774 
    2775 static int is_assignment(const char *s)
    2776 {
    2777     if (!s || !isalpha(*s))
    2778         return 0;
    2779     s++;
    2780     while (isalnum(*s) || *s == '_')
    2781         s++;
    2782     return *s == '=';
    2783 }
    2784 
    2785 /* the src parameter allows us to peek forward to a possible &n syntax
    2786  * for file descriptor duplication, e.g., "2>&1".
    2787  * Return code is 0 normally, 1 if a syntax error is detected in src.
    2788  * Resource errors (in xmalloc) cause the process to exit */
    2789 static int setup_redirect(struct p_context *ctx, int fd, redir_type style,
    2790     struct in_str *input)
    2791 {
    2792     struct child_prog *child = ctx->child;
    2793     struct redir_struct *redir = child->redirects;
    2794     struct redir_struct *last_redir = NULL;
    2795 
    2796     /* Create a new redir_struct and drop it onto the end of the linked list */
    2797     while (redir) {
    2798         last_redir = redir;
    2799         redir = redir->next;
    2800     }
    2801     redir = xmalloc(sizeof(struct redir_struct));
    2802     redir->next = NULL;
    2803     redir->word.gl_pathv = NULL;
    2804     if (last_redir) {
    2805         last_redir->next = redir;
    2806     } else {
    2807         child->redirects = redir;
    2808     }
    2809 
    2810     redir->type = style;
    2811     redir->fd = (fd == -1) ? redir_table[style].default_fd : fd;
    2812 
    2813     debug_printf("Redirect type %d%s\n", redir->fd, redir_table[style].descrip);
    2814 
    2815     /* Check for a '2>&1' type redirect */
    2816     redir->dup = redirect_dup_num(input);
    2817     if (redir->dup == -2) return 1;  /* syntax error */
    2818     if (redir->dup != -1) {
    2819         /* Erik had a check here that the file descriptor in question
    2820          * is legit; I postpone that to "run time"
    2821          * A "-" representation of "close me" shows up as a -3 here */
    2822         debug_printf("Duplicating redirect '%d>&%d'\n", redir->fd, redir->dup);
    2823     } else {
    2824         /* We do _not_ try to open the file that src points to,
    2825          * since we need to return and let src be expanded first.
    2826          * Set ctx->pending_redirect, so we know what to do at the
    2827          * end of the next parsed word. */
    2828         ctx->pending_redirect = redir;
    2829     }
    2830     return 0;
    2831 }
    2832 
    2833 static struct pipe *new_pipe(void)
    2834 {
    2835     struct pipe *pi;
    2836     pi = xzalloc(sizeof(struct pipe));
    2837     /*pi->num_progs = 0;*/
    2838     /*pi->progs = NULL;*/
    2839     /*pi->next = NULL;*/
    2840     /*pi->followup = 0;  invalid */
    2841     if (RES_NONE)
    2842         pi->res_word = RES_NONE;
    2843     return pi;
    2844 }
    2845 
    2846 static void initialize_context(struct p_context *ctx)
    2847 {
    2848     ctx->child = NULL;
    2849     ctx->pipe = ctx->list_head = new_pipe();
    2850     ctx->pending_redirect = NULL;
    2851     ctx->res_w = RES_NONE;
    2852     //only ctx->parse_type is not touched... is this intentional?
    2853     ctx->old_flag = 0;
    2854     ctx->stack = NULL;
    2855     done_command(ctx);   /* creates the memory for working child */
    2856 }
    2857 
    2858 /* normal return is 0
    2859  * if a reserved word is found, and processed, return 1
    2860  * should handle if, then, elif, else, fi, for, while, until, do, done.
    2861  * case, function, and select are obnoxious, save those for later.
    2862  */
    2863 #if ENABLE_HUSH_IF || ENABLE_HUSH_LOOPS
    2864 static int reserved_word(o_string *dest, struct p_context *ctx)
    2865 {
    2866     struct reserved_combo {
    2867         char literal[7];
    2868         unsigned char code;
    2869         int flag;
    2870     };
    2871     /* Mostly a list of accepted follow-up reserved words.
    2872      * FLAG_END means we are done with the sequence, and are ready
    2873      * to turn the compound list into a command.
    2874      * FLAG_START means the word must start a new compound list.
    2875      */
    2876     static const struct reserved_combo reserved_list[] = {
    2877 #if ENABLE_HUSH_IF
    2878         { "if",    RES_IF,    FLAG_THEN | FLAG_START },
    2879         { "then",  RES_THEN,  FLAG_ELIF | FLAG_ELSE | FLAG_FI },
    2880         { "elif",  RES_ELIF,  FLAG_THEN },
    2881         { "else",  RES_ELSE,  FLAG_FI   },
    2882         { "fi",    RES_FI,    FLAG_END  },
    2883 #endif
    2884 #if ENABLE_HUSH_LOOPS
    2885         { "for",   RES_FOR,   FLAG_IN   | FLAG_START },
    2886         { "while", RES_WHILE, FLAG_DO   | FLAG_START },
    2887         { "until", RES_UNTIL, FLAG_DO   | FLAG_START },
    2888         { "in",    RES_IN,    FLAG_DO   },
    2889         { "do",    RES_DO,    FLAG_DONE },
    2890         { "done",  RES_DONE,  FLAG_END  }
    2891 #endif
    2892     };
    2893 
    2894     const struct reserved_combo *r;
    2895 
    2896     for (r = reserved_list; r < reserved_list + ARRAY_SIZE(reserved_list); r++) {
    2897         if (strcmp(dest->data, r->literal) != 0)
    2898             continue;
    2899         debug_printf("found reserved word %s, code %d\n", r->literal, r->code);
    2900         if (r->flag & FLAG_START) {
    2901             struct p_context *new;
    2902             debug_printf("push stack\n");
    2903 #if ENABLE_HUSH_LOOPS
    2904             if (ctx->res_w == RES_IN || ctx->res_w == RES_FOR) {
    2905                 syntax("malformed for"); /* example: 'for if' */
    2906                 ctx->res_w = RES_SNTX;
    2907                 b_reset(dest);
    2908                 return 1;
    2909             }
    2910 #endif
    2911             new = xmalloc(sizeof(*new));
    2912             *new = *ctx;   /* physical copy */
    2913             initialize_context(ctx);
    2914             ctx->stack = new;
    2915         } else if (ctx->res_w == RES_NONE || !(ctx->old_flag & (1 << r->code))) {
    2916             syntax(NULL);
    2917             ctx->res_w = RES_SNTX;
    2918             b_reset(dest);
    2919             return 1;
    2920         }
    2921         ctx->res_w = r->code;
    2922         ctx->old_flag = r->flag;
    2923         if (ctx->old_flag & FLAG_END) {
    2924             struct p_context *old;
    2925             debug_printf("pop stack\n");
    2926             done_pipe(ctx, PIPE_SEQ);
    2927             old = ctx->stack;
    2928             old->child->group = ctx->list_head;
    2929             old->child->subshell = 0;
    2930             *ctx = *old;   /* physical copy */
    2931             free(old);
    2932         }
    2933         b_reset(dest);
    2934         return 1;
    2935     }
    2936     return 0;
    2937 }
    2938 #else
    2939 #define reserved_word(dest, ctx) ((int)0)
    2940 #endif
    2941 
    2942 /* Normal return is 0.
    2943  * Syntax or xglob errors return 1. */
    2944 static int done_word(o_string *dest, struct p_context *ctx)
    2945 {
    2946     struct child_prog *child = ctx->child;
    2947     glob_t *glob_target;
    2948     int gr, flags = 0;
    2949 
    2950     debug_printf_parse("done_word entered: '%s' %p\n", dest->data, child);
    2951     if (dest->length == 0 && !dest->nonnull) {
    2952         debug_printf_parse("done_word return 0: true null, ignored\n");
    2953         return 0;
    2954     }
    2955     if (ctx->pending_redirect) {
    2956         glob_target = &ctx->pending_redirect->word;
    2957     } else {
    2958         if (child->group) {
    2959             syntax(NULL);
    2960             debug_printf_parse("done_word return 1: syntax error, groups and arglists don't mix\n");
    2961             return 1;
    2962         }
    2963         if (!child->argv && (ctx->parse_type & PARSEFLAG_SEMICOLON)) {
    2964             debug_printf_parse(": checking '%s' for reserved-ness\n", dest->data);
    2965             if (reserved_word(dest, ctx)) {
    2966                 debug_printf_parse("done_word return %d\n", (ctx->res_w == RES_SNTX));
    2967                 return (ctx->res_w == RES_SNTX);
    2968             }
    2969         }
    2970         glob_target = &child->glob_result;
    2971         if (child->argv)
    2972             flags |= GLOB_APPEND;
    2973     }
    2974     gr = xglob(dest, flags, glob_target);
    2975     if (gr != 0) {
    2976         debug_printf_parse("done_word return 1: xglob returned %d\n", gr);
    2977         return 1;
    2978     }
    2979 
    2980     b_reset(dest);
    2981     if (ctx->pending_redirect) {
    2982         ctx->pending_redirect = NULL;
    2983         if (glob_target->gl_pathc != 1) {
    2984             bb_error_msg("ambiguous redirect");
    2985             debug_printf_parse("done_word return 1: ambiguous redirect\n");
    2986             return 1;
    2987         }
    2988     } else {
    2989         child->argv = glob_target->gl_pathv;
    2990     }
    2991 #if ENABLE_HUSH_LOOPS
    2992     if (ctx->res_w == RES_FOR) {
    2993         done_word(dest, ctx);
    2994         done_pipe(ctx, PIPE_SEQ);
    2995     }
    2996 #endif
    2997     debug_printf_parse("done_word return 0\n");
    2998     return 0;
    2999 }
    3000 
    3001 /* The only possible error here is out of memory, in which case
    3002  * xmalloc exits. */
    3003 static int done_command(struct p_context *ctx)
    3004 {
    3005     /* The child is really already in the pipe structure, so
    3006      * advance the pipe counter and make a new, null child. */
    3007     struct pipe *pi = ctx->pipe;
    3008     struct child_prog *child = ctx->child;
    3009 
    3010     if (child) {
    3011         if (child->group == NULL
    3012          && child->argv == NULL
    3013          && child->redirects == NULL
    3014         ) {
    3015             debug_printf_parse("done_command: skipping null cmd, num_progs=%d\n", pi->num_progs);
    3016             return pi->num_progs;
    3017         }
    3018         pi->num_progs++;
    3019         debug_printf_parse("done_command: ++num_progs=%d\n", pi->num_progs);
    3020     } else {
    3021         debug_printf_parse("done_command: initializing, num_progs=%d\n", pi->num_progs);
    3022     }
    3023 
    3024     /* Only real trickiness here is that the uncommitted
    3025      * child structure is not counted in pi->num_progs. */
    3026     pi->progs = xrealloc(pi->progs, sizeof(*pi->progs) * (pi->num_progs+1));
    3027     child = &pi->progs[pi->num_progs];
    3028 
    3029     memset(child, 0, sizeof(*child));
    3030     /*child->redirects = NULL;*/
    3031     /*child->argv = NULL;*/
    3032     /*child->is_stopped = 0;*/
    3033     /*child->group = NULL;*/
    3034     /*child->glob_result.gl_pathv = NULL;*/
    3035     child->family = pi;
    3036     //sp: /*child->sp = 0;*/
    3037     //pt: child->parse_type = ctx->parse_type;
    3038 
    3039     ctx->child = child;
    3040     /* but ctx->pipe and ctx->list_head remain unchanged */
    3041 
    3042     return pi->num_progs; /* used only for 0/nonzero check */
    3043 }
    3044 
    3045 static int done_pipe(struct p_context *ctx, pipe_style type)
    3046 {
    3047     struct pipe *new_p;
    3048     int not_null;
    3049 
    3050     debug_printf_parse("done_pipe entered, followup %d\n", type);
    3051     not_null = done_command(ctx);  /* implicit closure of previous command */
    3052     ctx->pipe->followup = type;
    3053     ctx->pipe->res_word = ctx->res_w;
    3054     /* Without this check, even just <enter> on command line generates
    3055      * tree of three NOPs (!). Which is harmless but annoying.
    3056      * IOW: it is safe to do it unconditionally. */
    3057     if (not_null) {
    3058         new_p = new_pipe();
    3059         ctx->pipe->next = new_p;
    3060         ctx->pipe = new_p;
    3061         ctx->child = NULL;
    3062         done_command(ctx);  /* set up new pipe to accept commands */
    3063     }
    3064     debug_printf_parse("done_pipe return 0\n");
    3065     return 0;
    3066 }
    3067 
    3068 /* peek ahead in the in_str to find out if we have a "&n" construct,
    3069  * as in "2>&1", that represents duplicating a file descriptor.
    3070  * returns either -2 (syntax error), -1 (no &), or the number found.
    3071  */
    3072 static int redirect_dup_num(struct in_str *input)
    3073 {
    3074     int ch, d = 0, ok = 0;
    3075     ch = b_peek(input);
    3076     if (ch != '&') return -1;
    3077 
    3078     b_getch(input);  /* get the & */
    3079     ch = b_peek(input);
    3080     if (ch == '-') {
    3081         b_getch(input);
    3082         return -3;  /* "-" represents "close me" */
    3083     }
    3084     while (isdigit(ch)) {
    3085         d = d*10 + (ch-'0');
    3086         ok = 1;
    3087         b_getch(input);
    3088         ch = b_peek(input);
    3089     }
    3090     if (ok) return d;
    3091 
    3092     bb_error_msg("ambiguous redirect");
    3093     return -2;
    3094 }
    3095 
    3096 /* If a redirect is immediately preceded by a number, that number is
    3097  * supposed to tell which file descriptor to redirect.  This routine
    3098  * looks for such preceding numbers.  In an ideal world this routine
    3099  * needs to handle all the following classes of redirects...
    3100  *     echo 2>foo     # redirects fd  2 to file "foo", nothing passed to echo
    3101  *     echo 49>foo    # redirects fd 49 to file "foo", nothing passed to echo
    3102  *     echo -2>foo    # redirects fd  1 to file "foo",    "-2" passed to echo
    3103  *     echo 49x>foo   # redirects fd  1 to file "foo",   "49x" passed to echo
    3104  * A -1 output from this program means no valid number was found, so the
    3105  * caller should use the appropriate default for this redirection.
    3106  */
    3107 static int redirect_opt_num(o_string *o)
    3108 {
    3109     int num;
    3110 
    3111     if (o->length == 0)
    3112         return -1;
    3113     for (num = 0; num < o->length; num++) {
    3114         if (!isdigit(*(o->data + num))) {
    3115             return -1;
    3116         }
    3117     }
    3118     /* reuse num (and save an int) */
    3119     num = atoi(o->data);
    3120     b_reset(o);
    3121     return num;
    3122 }
    3123 
    3124 #if ENABLE_HUSH_TICK
    3125 static FILE *generate_stream_from_list(struct pipe *head)
    3126 {
    3127     FILE *pf;
    3128     int pid, channel[2];
    3129 
    3130     xpipe(channel);
    3131 #if BB_MMU
    3132     pid = fork();
    3133 #else
    3134     pid = vfork();
    3135 #endif
    3136     if (pid < 0) {
    3137         bb_perror_msg_and_die("fork");
    3138     } else if (pid == 0) {
    3139         close(channel[0]);
    3140         if (channel[1] != 1) {
    3141             dup2(channel[1], 1);
    3142             close(channel[1]);
    3143         }
    3144         /* Prevent it from trying to handle ctrl-z etc */
    3145 #if ENABLE_HUSH_JOB
    3146         run_list_level = 1;
    3147 #endif
    3148         /* Process substitution is not considered to be usual
    3149          * 'command execution'.
    3150          * SUSv3 says ctrl-Z should be ignored, ctrl-C should not. */
    3151         /* Not needed, we are relying on it being disabled
    3152          * everywhere outside actual command execution. */
    3153         /*set_jobctrl_sighandler(SIG_IGN);*/
    3154         set_misc_sighandler(SIG_DFL);
    3155         _exit(run_list_real(head));   /* leaks memory */
    3156     }
    3157     close(channel[1]);
    3158     pf = fdopen(channel[0], "r");
    3159     return pf;
    3160 }
    3161 
    3162 /* Return code is exit status of the process that is run. */
    3163 static int process_command_subs(o_string *dest, struct p_context *ctx,
    3164     struct in_str *input, const char *subst_end)
    3165 {
    3166     int retcode, ch, eol_cnt;
    3167     o_string result = NULL_O_STRING;
    3168     struct p_context inner;
    3169     FILE *p;
    3170     struct in_str pipe_str;
    3171 
    3172     initialize_context(&inner);
    3173 
    3174     /* recursion to generate command */
    3175     retcode = parse_stream(&result, &inner, input, subst_end);
    3176     if (retcode != 0)
    3177         return retcode;  /* syntax error or EOF */
    3178     done_word(&result, &inner);
    3179     done_pipe(&inner, PIPE_SEQ);
    3180     b_free(&result);
    3181 
    3182     p = generate_stream_from_list(inner.list_head);
    3183     if (p == NULL) return 1;
    3184     mark_open(fileno(p));
    3185     setup_file_in_str(&pipe_str, p);
    3186 
    3187     /* now send results of command back into original context */
    3188     eol_cnt = 0;
    3189     while ((ch = b_getch(&pipe_str)) != EOF) {
    3190         if (ch == '\n') {
    3191             eol_cnt++;
    3192             continue;
    3193         }
    3194         while (eol_cnt) {
    3195             b_addqchr(dest, '\n', dest->quote);
    3196             eol_cnt--;
    3197         }
    3198         b_addqchr(dest, ch, dest->quote);
    3199     }
    3200 
    3201     debug_printf("done reading from pipe, pclose()ing\n");
    3202     /* This is the step that wait()s for the child.  Should be pretty
    3203      * safe, since we just read an EOF from its stdout.  We could try
    3204      * to do better, by using wait(), and keeping track of background jobs
    3205      * at the same time.  That would be a lot of work, and contrary
    3206      * to the KISS philosophy of this program. */
    3207     mark_closed(fileno(p));
    3208     retcode = fclose(p);
    3209     free_pipe_list(inner.list_head, 0);
    3210     debug_printf("closed FILE from child, retcode=%d\n", retcode);
    3211     return retcode;
    3212 }
    3213 #endif
    3214 
    3215 static int parse_group(o_string *dest, struct p_context *ctx,
    3216     struct in_str *input, int ch)
    3217 {
    3218     int rcode;
    3219     const char *endch = NULL;
    3220     struct p_context sub;
    3221     struct child_prog *child = ctx->child;
    3222 
    3223     debug_printf_parse("parse_group entered\n");
    3224     if (child->argv) {
    3225         syntax(NULL);
    3226         debug_printf_parse("parse_group return 1: syntax error, groups and arglists don't mix\n");
    3227         return 1;
    3228     }
    3229     initialize_context(&sub);
    3230     endch = "}";
    3231     if (ch == '(') {
    3232         endch = ")";
    3233         child->subshell = 1;
    3234     }
    3235     rcode = parse_stream(dest, &sub, input, endch);
    3236 //vda: err chk?
    3237     done_word(dest, &sub); /* finish off the final word in the subcontext */
    3238     done_pipe(&sub, PIPE_SEQ);  /* and the final command there, too */
    3239     child->group = sub.list_head;
    3240 
    3241     debug_printf_parse("parse_group return %d\n", rcode);
    3242     return rcode;
    3243     /* child remains "open", available for possible redirects */
    3244 }
    3245 
    3246 /* Basically useful version until someone wants to get fancier,
    3247  * see the bash man page under "Parameter Expansion" */
    3248 static const char *lookup_param(const char *src)
    3249 {
    3250     struct variable *var = get_local_var(src);
    3251     if (var)
    3252         return strchr(var->varstr, '=') + 1;
    3253     return NULL;
    3254 }
    3255 
    3256 /* return code: 0 for OK, 1 for syntax error */
    3257 static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input)
    3258 {
    3259     int ch = b_peek(input);  /* first character after the $ */
    3260     unsigned char quote_mask = dest->quote ? 0x80 : 0;
    3261 
    3262     debug_printf_parse("handle_dollar entered: ch='%c'\n", ch);
    3263     if (isalpha(ch)) {
    3264         b_addchr(dest, SPECIAL_VAR_SYMBOL);
    3265         //sp: ctx->child->sp++;
    3266         while (1) {
    3267             debug_printf_parse(": '%c'\n", ch);
    3268             b_getch(input);
    3269             b_addchr(dest, ch | quote_mask);
    3270             quote_mask = 0;
    3271             ch = b_peek(input);
    3272             if (!isalnum(ch) && ch != '_')
    3273                 break;
    3274         }
    3275         b_addchr(dest, SPECIAL_VAR_SYMBOL);
    3276     } else if (isdigit(ch)) {
    3277  make_one_char_var:
    3278         b_addchr(dest, SPECIAL_VAR_SYMBOL);
    3279         //sp: ctx->child->sp++;
    3280         debug_printf_parse(": '%c'\n", ch);
    3281         b_getch(input);
    3282         b_addchr(dest, ch | quote_mask);
    3283         b_addchr(dest, SPECIAL_VAR_SYMBOL);
    3284     } else switch (ch) {
    3285         case '$': /* pid */
    3286         case '!': /* last bg pid */
    3287         case '?': /* last exit code */
    3288         case '#': /* number of args */
    3289         case '*': /* args */
    3290         case '@': /* args */
    3291             goto make_one_char_var;
    3292         case '{':
    3293             b_addchr(dest, SPECIAL_VAR_SYMBOL);
    3294             //sp: ctx->child->sp++;
    3295             b_getch(input);
    3296             /* XXX maybe someone will try to escape the '}' */
    3297             while (1) {
    3298                 ch = b_getch(input);
    3299                 if (ch == '}')
    3300                     break;
    3301                 if (!isalnum(ch) && ch != '_') {
    3302                     syntax("unterminated ${name}");
    3303                     debug_printf_parse("handle_dollar return 1: unterminated ${name}\n");
    3304                     return 1;
    3305                 }
    3306                 debug_printf_parse(": '%c'\n", ch);
    3307                 b_addchr(dest, ch | quote_mask);
    3308                 quote_mask = 0;
    3309             }
    3310             b_addchr(dest, SPECIAL_VAR_SYMBOL);
    3311             break;
    3312 #if ENABLE_HUSH_TICK
    3313         case '(':
    3314             b_getch(input);
    3315             process_command_subs(dest, ctx, input, ")");
    3316             break;
    3317 #endif
    3318         case '-':
    3319         case '_':
    3320             /* still unhandled, but should be eventually */
    3321             bb_error_msg("unhandled syntax: $%c", ch);
    3322             return 1;
    3323             break;
    3324         default:
    3325             b_addqchr(dest, '$', dest->quote);
    3326     }
    3327     debug_printf_parse("handle_dollar return 0\n");
    3328     return 0;
    3329 }
    3330 
    3331 /* return code is 0 for normal exit, 1 for syntax error */
    3332 static int parse_stream(o_string *dest, struct p_context *ctx,
    3333     struct in_str *input, const char *end_trigger)
    3334 {
    3335     int ch, m;
    3336     int redir_fd;
    3337     redir_type redir_style;
    3338     int next;
    3339 
    3340     /* Only double-quote state is handled in the state variable dest->quote.
    3341      * A single-quote triggers a bypass of the main loop until its mate is
    3342      * found.  When recursing, quote state is passed in via dest->quote. */
    3343 
    3344     debug_printf_parse("parse_stream entered, end_trigger='%s'\n", end_trigger);
    3345 
    3346     while (1) {
    3347         m = CHAR_IFS;
    3348         next = '\0';
    3349         ch = b_getch(input);
    3350         if (ch != EOF) {
    3351             m = charmap[ch];
    3352             if (ch != '\n')
    3353                 next = b_peek(input);
    3354         }
    3355         debug_printf_parse(": ch=%c (%d) m=%d quote=%d\n",
    3356                         ch, ch, m, dest->quote);
    3357         if (m == CHAR_ORDINARY
    3358          || (m != CHAR_SPECIAL && dest->quote)
    3359         ) {
    3360             if (ch == EOF) {
    3361                 syntax("unterminated \"");
    3362                 debug_printf_parse("parse_stream return 1: unterminated \"\n");
    3363                 return 1;
    3364             }
    3365             b_addqchr(dest, ch, dest->quote);
    3366             continue;
    3367         }
    3368         if (m == CHAR_IFS) {
    3369             if (done_word(dest, ctx)) {
    3370                 debug_printf_parse("parse_stream return 1: done_word!=0\n");
    3371                 return 1;
    3372             }
    3373             if (ch == EOF)
    3374                 break;
    3375             /* If we aren't performing a substitution, treat
    3376              * a newline as a command separator.
    3377              * [why we don't handle it exactly like ';'? --vda] */
    3378             if (end_trigger && ch == '\n') {
    3379                 done_pipe(ctx, PIPE_SEQ);
    3380             }
    3381         }
    3382         if ((end_trigger && strchr(end_trigger, ch))
    3383          && !dest->quote && ctx->res_w == RES_NONE
    3384         ) {
    3385             debug_printf_parse("parse_stream return 0: end_trigger char found\n");
    3386             return 0;
    3387         }
    3388         if (m == CHAR_IFS)
    3389             continue;
    3390         switch (ch) {
    3391         case '#':
    3392             if (dest->length == 0 && !dest->quote) {
    3393                 while (1) {
    3394                     ch = b_peek(input);
    3395                     if (ch == EOF || ch == '\n')
    3396                         break;
    3397                     b_getch(input);
    3398                 }
    3399             } else {
    3400                 b_addqchr(dest, ch, dest->quote);
    3401             }
    3402             break;
    3403         case '\\':
    3404             if (next == EOF) {
    3405                 syntax("\\<eof>");
    3406                 debug_printf_parse("parse_stream return 1: \\<eof>\n");
    3407                 return 1;
    3408             }
    3409             b_addqchr(dest, '\\', dest->quote);
    3410             b_addqchr(dest, b_getch(input), dest->quote);
    3411             break;
    3412         case '$':
    3413             if (handle_dollar(dest, ctx, input) != 0) {
    3414                 debug_printf_parse("parse_stream return 1: handle_dollar returned non-0\n");
    3415                 return 1;
    3416             }
    3417             break;
    3418         case '\'':
    3419             dest->nonnull = 1;
    3420             while (1) {
    3421                 ch = b_getch(input);
    3422                 if (ch == EOF || ch == '\'')
    3423                     break;
    3424                 b_addchr(dest, ch);
    3425             }
    3426             if (ch == EOF) {
    3427                 syntax("unterminated '");
    3428                 debug_printf_parse("parse_stream return 1: unterminated '\n");
    3429                 return 1;
    3430             }
    3431             break;
    3432         case '"':
    3433             dest->nonnull = 1;
    3434             dest->quote = !dest->quote;
    3435             break;
    3436 #if ENABLE_HUSH_TICK
    3437         case '`':
    3438             process_command_subs(dest, ctx, input, "`");
    3439             break;
    3440 #endif
    3441         case '>':
    3442             redir_fd = redirect_opt_num(dest);
    3443             done_word(dest, ctx);
    3444             redir_style = REDIRECT_OVERWRITE;
    3445             if (next == '>') {
    3446                 redir_style = REDIRECT_APPEND;
    3447                 b_getch(input);
    3448             }
    3449 #if 0
    3450             else if (next == '(') {
    3451                 syntax(">(process) not supported");
    3452                 debug_printf_parse("parse_stream return 1: >(process) not supported\n");
    3453                 return 1;
    3454             }
    3455 #endif
    3456             setup_redirect(ctx, redir_fd, redir_style, input);
    3457             break;
    3458         case '<':
    3459             redir_fd = redirect_opt_num(dest);
    3460             done_word(dest, ctx);
    3461             redir_style = REDIRECT_INPUT;
    3462             if (next == '<') {
    3463                 redir_style = REDIRECT_HEREIS;
    3464                 b_getch(input);
    3465             } else if (next == '>') {
    3466                 redir_style = REDIRECT_IO;
    3467                 b_getch(input);
    3468             }
    3469 #if 0
    3470             else if (next == '(') {
    3471                 syntax("<(process) not supported");
    3472                 debug_printf_parse("parse_stream return 1: <(process) not supported\n");
    3473                 return 1;
    3474             }
    3475 #endif
    3476             setup_redirect(ctx, redir_fd, redir_style, input);
    3477             break;
    3478         case ';':
    3479             done_word(dest, ctx);
    3480             done_pipe(ctx, PIPE_SEQ);
    3481             break;
    3482         case '&':
    3483             done_word(dest, ctx);
    3484             if (next == '&') {
    3485                 b_getch(input);
    3486                 done_pipe(ctx, PIPE_AND);
    3487             } else {
    3488                 done_pipe(ctx, PIPE_BG);
    3489             }
    3490             break;
    3491         case '|':
    3492             done_word(dest, ctx);
    3493             if (next == '|') {
    3494                 b_getch(input);
    3495                 done_pipe(ctx, PIPE_OR);
    3496             } else {
    3497                 /* we could pick up a file descriptor choice here
    3498                  * with redirect_opt_num(), but bash doesn't do it.
    3499                  * "echo foo 2| cat" yields "foo 2". */
    3500                 done_command(ctx);
    3501             }
    3502             break;
    3503         case '(':
    3504         case '{':
    3505             if (parse_group(dest, ctx, input, ch) != 0) {
    3506                 debug_printf_parse("parse_stream return 1: parse_group returned non-0\n");
    3507                 return 1;
    3508             }
    3509             break;
    3510         case ')':
    3511         case '}':
    3512             syntax("unexpected }");   /* Proper use of this character is caught by end_trigger */
    3513             debug_printf_parse("parse_stream return 1: unexpected '}'\n");
    3514             return 1;
    3515         default:
    3516             if (ENABLE_HUSH_DEBUG)
    3517                 bb_error_msg_and_die("BUG: unexpected %c\n", ch);
    3518         }
    3519     }
    3520     /* Complain if quote?  No, maybe we just finished a command substitution
    3521      * that was quoted.  Example:
    3522      * $ echo "`cat foo` plus more"
    3523      * and we just got the EOF generated by the subshell that ran "cat foo"
    3524      * The only real complaint is if we got an EOF when end_trigger != NULL,
    3525      * that is, we were really supposed to get end_trigger, and never got
    3526      * one before the EOF.  Can't use the standard "syntax error" return code,
    3527      * so that parse_stream_outer can distinguish the EOF and exit smoothly. */
    3528     debug_printf_parse("parse_stream return %d\n", -(end_trigger != NULL));
    3529     if (end_trigger)
    3530         return -1;
    3531     return 0;
    3532 }
    3533 
    3534 static void set_in_charmap(const char *set, int code)
    3535 {
    3536     while (*set)
    3537         charmap[(unsigned char)*set++] = code;
    3538 }
    3539 
    3540 static void update_charmap(void)
    3541 {
    3542     /* char *ifs and char charmap[256] are both globals. */
    3543     ifs = getenv("IFS");
    3544     if (ifs == NULL)
    3545         ifs = " \t\n";
    3546     /* Precompute a list of 'flow through' behavior so it can be treated
    3547      * quickly up front.  Computation is necessary because of IFS.
    3548      * Special case handling of IFS == " \t\n" is not implemented.
    3549      * The charmap[] array only really needs two bits each,
    3550      * and on most machines that would be faster (reduced L1 cache use).
    3551      */
    3552     memset(charmap, CHAR_ORDINARY, sizeof(charmap));
    3553 #if ENABLE_HUSH_TICK
    3554     set_in_charmap("\\$\"`", CHAR_SPECIAL);
    3555 #else
    3556     set_in_charmap("\\$\"", CHAR_SPECIAL);
    3557 #endif
    3558     set_in_charmap("<>;&|(){}#'", CHAR_ORDINARY_IF_QUOTED);
    3559     set_in_charmap(ifs, CHAR_IFS);  /* are ordinary if quoted */
    3560 }
    3561 
    3562 /* most recursion does not come through here, the exception is
    3563  * from builtin_source() and builtin_eval() */
    3564 static int parse_and_run_stream(struct in_str *inp, int parse_flag)
    3565 {
    3566     struct p_context ctx;
    3567     o_string temp = NULL_O_STRING;
    3568     int rcode;
    3569     do {
    3570         ctx.parse_type = parse_flag;
    3571         initialize_context(&ctx);
    3572         update_charmap();
    3573         if (!(parse_flag & PARSEFLAG_SEMICOLON) || (parse_flag & PARSEFLAG_REPARSING))
    3574             set_in_charmap(";$&|", CHAR_ORDINARY);
    3575 #if ENABLE_HUSH_INTERACTIVE
    3576         inp->promptmode = 0; /* PS1 */
    3577 #endif
    3578         /* We will stop & execute after each ';' or '\n'.
    3579          * Example: "sleep 9999; echo TEST" + ctrl-C:
    3580          * TEST should be printed */
    3581         rcode = parse_stream(&temp, &ctx, inp, ";\n");
    3582         if (rcode != 1 && ctx.old_flag != 0) {
    3583             syntax(NULL);
    3584         }
    3585         if (rcode != 1 && ctx.old_flag == 0) {
    3586             done_word(&temp, &ctx);
    3587             done_pipe(&ctx, PIPE_SEQ);
    3588             debug_print_tree(ctx.list_head, 0);
    3589             debug_printf_exec("parse_stream_outer: run_list\n");
    3590             run_list(ctx.list_head);
    3591         } else {
    3592             if (ctx.old_flag != 0) {
    3593                 free(ctx.stack);
    3594                 b_reset(&temp);
    3595             }
    3596             temp.nonnull = 0;
    3597             temp.quote = 0;
    3598             inp->p = NULL;
    3599             free_pipe_list(ctx.list_head, 0);
    3600         }
    3601         b_free(&temp);
    3602     } while (rcode != -1 && !(parse_flag & PARSEFLAG_EXIT_FROM_LOOP));   /* loop on syntax errors, return on EOF */
    3603     return 0;
    3604 }
    3605 
    3606 static int parse_and_run_string(const char *s, int parse_flag)
    3607 {
    3608     struct in_str input;
    3609     setup_string_in_str(&input, s);
    3610     return parse_and_run_stream(&input, parse_flag);
    3611 }
    3612 
    3613 static int parse_and_run_file(FILE *f)
    3614 {
    3615     int rcode;
    3616     struct in_str input;
    3617     setup_file_in_str(&input, f);
    3618     rcode = parse_and_run_stream(&input, PARSEFLAG_SEMICOLON);
    3619     return rcode;
    3620 }
    3621 
    3622 #if ENABLE_HUSH_JOB
    3623 /* Make sure we have a controlling tty.  If we get started under a job
    3624  * aware app (like bash for example), make sure we are now in charge so
    3625  * we don't fight over who gets the foreground */
    3626 static void setup_job_control(void)
    3627 {
    3628     pid_t shell_pgrp;
    3629 
    3630     saved_task_pgrp = shell_pgrp = getpgrp();
    3631     debug_printf_jobs("saved_task_pgrp=%d\n", saved_task_pgrp);
    3632     fcntl(interactive_fd, F_SETFD, FD_CLOEXEC);
    3633 
    3634     /* If we were ran as 'hush &',
    3635      * sleep until we are in the foreground.  */
    3636     while (tcgetpgrp(interactive_fd) != shell_pgrp) {
    3637         /* Send TTIN to ourself (should stop us) */
    3638         kill(- shell_pgrp, SIGTTIN);
    3639         shell_pgrp = getpgrp();
    3640     }
    3641 
    3642     /* Ignore job-control and misc signals.  */
    3643     set_jobctrl_sighandler(SIG_IGN);
    3644     set_misc_sighandler(SIG_IGN);
    3645 //huh?  signal(SIGCHLD, SIG_IGN);
    3646 
    3647     /* We _must_ restore tty pgrp on fatal signals */
    3648     set_fatal_sighandler(sigexit);
    3649 
    3650     /* Put ourselves in our own process group.  */
    3651     setpgrp(); /* is the same as setpgid(our_pid, our_pid); */
    3652     /* Grab control of the terminal.  */
    3653     tcsetpgrp(interactive_fd, getpid());
    3654 }
    3655 #endif
    3656 
    3657 int hush_main(int argc, char **argv);
     7470        }
     7471    default:
     7472        return EXIT_FAILURE;
     7473    }
     7474    return EXIT_SUCCESS;
     7475}
     7476
     7477int hush_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    36587478int hush_main(int argc, char **argv)
    36597479{
    3660     static const char version_str[] ALIGN1 = "HUSH_VERSION="HUSH_VER_STR;
    3661     static const struct variable const_shell_ver = {
    3662         .next = NULL,
    3663         .varstr = (char*)version_str,
    3664         .max_len = 1, /* 0 can provoke free(name) */
    3665         .flg_export = 1,
    3666         .flg_read_only = 1,
    3667     };
    3668 
    36697480    int opt;
    3670     FILE *input;
     7481    unsigned builtin_argc;
    36717482    char **e;
    36727483    struct variable *cur_var;
    3673 
    3674     PTR_TO_GLOBALS = xzalloc(sizeof(G));
    3675 
     7484    struct variable *shell_ver;
     7485
     7486    INIT_G();
     7487    if (EXIT_SUCCESS) /* if EXIT_SUCCESS == 0, it is already done */
     7488        G.last_exitcode = EXIT_SUCCESS;
     7489#if !BB_MMU
     7490    G.argv0_for_re_execing = argv[0];
     7491#endif
    36767492    /* Deal with HUSH_VERSION */
    3677     shell_ver = const_shell_ver; /* copying struct here */
    3678     top_var = &shell_ver;
     7493    shell_ver = xzalloc(sizeof(*shell_ver));
     7494    shell_ver->flg_export = 1;
     7495    shell_ver->flg_read_only = 1;
     7496    /* Code which handles ${var<op>...} needs writable values for all variables,
     7497     * therefore we xstrdup: */
     7498    shell_ver->varstr = xstrdup(hush_version_str);
     7499    /* Create shell local variables from the values
     7500     * currently living in the environment */
     7501    debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION");
    36797502    unsetenv("HUSH_VERSION"); /* in case it exists in initial env */
    3680     /* Initialize our shell local variables with the values
    3681      * currently living in the environment */
    3682     cur_var = top_var;
     7503    G.top_var = shell_ver;
     7504    cur_var = G.top_var;
    36837505    e = environ;
    36847506    if (e) while (*e) {
     
    36937515        e++;
    36947516    }
    3695     putenv((char *)version_str); /* reinstate HUSH_VERSION */
     7517    /* (Re)insert HUSH_VERSION into env (AFTER we scanned the env!) */
     7518    debug_printf_env("putenv '%s'\n", shell_ver->varstr);
     7519    putenv(shell_ver->varstr);
     7520
     7521    /* Export PWD */
     7522    set_pwd_var(/*exp:*/ 1);
     7523    /* bash also exports SHLVL and _,
     7524     * and sets (but doesn't export) the following variables:
     7525     * BASH=/bin/bash
     7526     * BASH_VERSINFO=([0]="3" [1]="2" [2]="0" [3]="1" [4]="release" [5]="i386-pc-linux-gnu")
     7527     * BASH_VERSION='3.2.0(1)-release'
     7528     * HOSTTYPE=i386
     7529     * MACHTYPE=i386-pc-linux-gnu
     7530     * OSTYPE=linux-gnu
     7531     * HOSTNAME=<xxxxxxxxxx>
     7532     * PPID=<NNNNN> - we also do it elsewhere
     7533     * EUID=<NNNNN>
     7534     * UID=<NNNNN>
     7535     * GROUPS=()
     7536     * LINES=<NNN>
     7537     * COLUMNS=<NNN>
     7538     * BASH_ARGC=()
     7539     * BASH_ARGV=()
     7540     * BASH_LINENO=()
     7541     * BASH_SOURCE=()
     7542     * DIRSTACK=()
     7543     * PIPESTATUS=([0]="0")
     7544     * HISTFILE=/<xxx>/.bash_history
     7545     * HISTFILESIZE=500
     7546     * HISTSIZE=500
     7547     * MAILCHECK=60
     7548     * PATH=/usr/gnu/bin:/usr/local/bin:/bin:/usr/bin:.
     7549     * SHELL=/bin/bash
     7550     * SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
     7551     * TERM=dumb
     7552     * OPTERR=1
     7553     * OPTIND=1
     7554     * IFS=$' \t\n'
     7555     * PS1='\s-\v\$ '
     7556     * PS2='> '
     7557     * PS4='+ '
     7558     */
    36967559
    36977560#if ENABLE_FEATURE_EDITING
    3698     line_input_state = new_line_input_t(FOR_SHELL);
    3699 #endif
    3700     /* XXX what should these be while sourcing /etc/profile? */
    3701     global_argc = argc;
    3702     global_argv = argv;
     7561    G.line_input_state = new_line_input_t(FOR_SHELL);
     7562# if defined MAX_HISTORY && MAX_HISTORY > 0 && ENABLE_HUSH_SAVEHISTORY
     7563    {
     7564        const char *hp = get_local_var_value("HISTFILE");
     7565        if (!hp) {
     7566            hp = get_local_var_value("HOME");
     7567            if (hp) {
     7568                G.line_input_state->hist_file = concat_path_file(hp, ".hush_history");
     7569                //set_local_var(xasprintf("HISTFILE=%s", ...));
     7570            }
     7571        }
     7572    }
     7573# endif
     7574#endif
     7575
     7576    G.global_argc = argc;
     7577    G.global_argv = argv;
    37037578    /* Initialize some more globals to non-zero values */
    3704     set_cwd();
    3705 #if ENABLE_HUSH_INTERACTIVE
    3706 #if ENABLE_FEATURE_EDITING
    3707     cmdedit_set_initial_prompt();
    3708 #endif
    3709     PS2 = "> ";
    3710 #endif
    3711 
    3712     if (EXIT_SUCCESS) /* otherwise is already done */
    3713         last_return_code = EXIT_SUCCESS;
    3714 
    3715     if (argv[0] && argv[0][0] == '-') {
    3716         debug_printf("sourcing /etc/profile\n");
    3717         input = fopen("/etc/profile", "r");
    3718         if (input != NULL) {
    3719             mark_open(fileno(input));
    3720             parse_and_run_file(input);
    3721             mark_closed(fileno(input));
    3722             fclose(input);
    3723         }
    3724     }
    3725     input = stdin;
    3726 
    3727     while ((opt = getopt(argc, argv, "c:xif")) > 0) {
     7579    cmdedit_update_prompt();
     7580
     7581    if (setjmp(die_jmp)) {
     7582        /* xfunc has failed! die die die */
     7583        /* no EXIT traps, this is an escape hatch! */
     7584        G.exiting = 1;
     7585        hush_exit(xfunc_error_retval);
     7586    }
     7587
     7588    /* Shell is non-interactive at first. We need to call
     7589     * init_sigmasks() if we are going to execute "sh <script>",
     7590     * "sh -c <cmds>" or login shell's /etc/profile and friends.
     7591     * If we later decide that we are interactive, we run init_sigmasks()
     7592     * in order to intercept (more) signals.
     7593     */
     7594
     7595    /* Parse options */
     7596    /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */
     7597    builtin_argc = 0;
     7598    while (1) {
     7599        opt = getopt(argc, argv, "+c:xins"
     7600#if !BB_MMU
     7601                "<:$:R:V:"
     7602# if ENABLE_HUSH_FUNCTIONS
     7603                "F:"
     7604# endif
     7605#endif
     7606        );
     7607        if (opt <= 0)
     7608            break;
    37287609        switch (opt) {
    37297610        case 'c':
    3730             global_argv = argv + optind;
    3731             global_argc = argc - optind;
    3732             opt = parse_and_run_string(optarg, PARSEFLAG_SEMICOLON);
     7611            /* Possibilities:
     7612             * sh ... -c 'script'
     7613             * sh ... -c 'script' ARG0 [ARG1...]
     7614             * On NOMMU, if builtin_argc != 0,
     7615             * sh ... -c 'builtin' BARGV... "" ARG0 [ARG1...]
     7616             * "" needs to be replaced with NULL
     7617             * and BARGV vector fed to builtin function.
     7618             * Note: the form without ARG0 never happens:
     7619             * sh ... -c 'builtin' BARGV... ""
     7620             */
     7621            if (!G.root_pid) {
     7622                G.root_pid = getpid();
     7623                G.root_ppid = getppid();
     7624            }
     7625            G.global_argv = argv + optind;
     7626            G.global_argc = argc - optind;
     7627            if (builtin_argc) {
     7628                /* -c 'builtin' [BARGV...] "" ARG0 [ARG1...] */
     7629                const struct built_in_command *x;
     7630
     7631                init_sigmasks();
     7632                x = find_builtin(optarg);
     7633                if (x) { /* paranoia */
     7634                    G.global_argc -= builtin_argc; /* skip [BARGV...] "" */
     7635                    G.global_argv += builtin_argc;
     7636                    G.global_argv[-1] = NULL; /* replace "" */
     7637                    G.last_exitcode = x->b_function(argv + optind - 1);
     7638                }
     7639                goto final_return;
     7640            }
     7641            if (!G.global_argv[0]) {
     7642                /* -c 'script' (no params): prevent empty $0 */
     7643                G.global_argv--; /* points to argv[i] of 'script' */
     7644                G.global_argv[0] = argv[0];
     7645                G.global_argc++;
     7646            } /* else -c 'script' ARG0 [ARG1...]: $0 is ARG0 */
     7647            init_sigmasks();
     7648            parse_and_run_string(optarg);
    37337649            goto final_return;
    37347650        case 'i':
    37357651            /* Well, we cannot just declare interactiveness,
    37367652             * we have to have some stuff (ctty, etc) */
    3737             /* interactive_fd++; */
     7653            /* G_interactive_fd++; */
    37387654            break;
    3739         case 'f':
    3740             fake_mode = 1;
     7655        case 's':
     7656            /* "-s" means "read from stdin", but this is how we always
     7657             * operate, so simply do nothing here. */
    37417658            break;
     7659#if !BB_MMU
     7660        case '<': /* "big heredoc" support */
     7661            full_write1_str(optarg);
     7662            _exit(0);
     7663        case '$': {
     7664            unsigned long long empty_trap_mask;
     7665
     7666            G.root_pid = bb_strtou(optarg, &optarg, 16);
     7667            optarg++;
     7668            G.root_ppid = bb_strtou(optarg, &optarg, 16);
     7669            optarg++;
     7670            G.last_bg_pid = bb_strtou(optarg, &optarg, 16);
     7671            optarg++;
     7672            G.last_exitcode = bb_strtou(optarg, &optarg, 16);
     7673            optarg++;
     7674            builtin_argc = bb_strtou(optarg, &optarg, 16);
     7675            optarg++;
     7676            empty_trap_mask = bb_strtoull(optarg, &optarg, 16);
     7677            if (empty_trap_mask != 0) {
     7678                int sig;
     7679                init_sigmasks();
     7680                G.traps = xzalloc(sizeof(G.traps[0]) * NSIG);
     7681                for (sig = 1; sig < NSIG; sig++) {
     7682                    if (empty_trap_mask & (1LL << sig)) {
     7683                        G.traps[sig] = xzalloc(1); /* == xstrdup(""); */
     7684                        sigaddset(&G.blocked_set, sig);
     7685                    }
     7686                }
     7687                sigprocmask(SIG_SETMASK, &G.blocked_set, NULL);
     7688            }
     7689# if ENABLE_HUSH_LOOPS
     7690            optarg++;
     7691            G.depth_of_loop = bb_strtou(optarg, &optarg, 16);
     7692# endif
     7693            break;
     7694        }
     7695        case 'R':
     7696        case 'V':
     7697            set_local_var(xstrdup(optarg), /*exp:*/ 0, /*lvl:*/ 0, /*ro:*/ opt == 'R');
     7698            break;
     7699# if ENABLE_HUSH_FUNCTIONS
     7700        case 'F': {
     7701            struct function *funcp = new_function(optarg);
     7702            /* funcp->name is already set to optarg */
     7703            /* funcp->body is set to NULL. It's a special case. */
     7704            funcp->body_as_string = argv[optind];
     7705            optind++;
     7706            break;
     7707        }
     7708# endif
     7709#endif
     7710        case 'n':
     7711        case 'x':
     7712            if (set_mode(1, opt, NULL) == 0) /* no error */
     7713                break;
    37427714        default:
    37437715#ifndef BB_VER
     
    37497721#endif
    37507722        }
    3751     }
    3752 #if ENABLE_HUSH_JOB
    3753     /* A shell is interactive if the '-i' flag was given, or if all of
    3754      * the following conditions are met:
     7723    } /* option parsing loop */
     7724
     7725    if (!G.root_pid) {
     7726        G.root_pid = getpid();
     7727        G.root_ppid = getppid();
     7728    }
     7729
     7730    /* If we are login shell... */
     7731    if (argv[0] && argv[0][0] == '-') {
     7732        FILE *input;
     7733        debug_printf("sourcing /etc/profile\n");
     7734        input = fopen_for_read("/etc/profile");
     7735        if (input != NULL) {
     7736            close_on_exec_on(fileno(input));
     7737            init_sigmasks();
     7738            parse_and_run_file(input);
     7739            fclose(input);
     7740        }
     7741        /* bash: after sourcing /etc/profile,
     7742         * tries to source (in the given order):
     7743         * ~/.bash_profile, ~/.bash_login, ~/.profile,
     7744         * stopping on first found. --noprofile turns this off.
     7745         * bash also sources ~/.bash_logout on exit.
     7746         * If called as sh, skips .bash_XXX files.
     7747         */
     7748    }
     7749
     7750    if (argv[optind]) {
     7751        FILE *input;
     7752        /*
     7753         * "bash <script>" (which is never interactive (unless -i?))
     7754         * sources $BASH_ENV here (without scanning $PATH).
     7755         * If called as sh, does the same but with $ENV.
     7756         */
     7757        debug_printf("running script '%s'\n", argv[optind]);
     7758        G.global_argv = argv + optind;
     7759        G.global_argc = argc - optind;
     7760        input = xfopen_for_read(argv[optind]);
     7761        close_on_exec_on(fileno(input));
     7762        init_sigmasks();
     7763        parse_and_run_file(input);
     7764#if ENABLE_FEATURE_CLEAN_UP
     7765        fclose(input);
     7766#endif
     7767        goto final_return;
     7768    }
     7769
     7770    /* Up to here, shell was non-interactive. Now it may become one.
     7771     * NB: don't forget to (re)run init_sigmasks() as needed.
     7772     */
     7773
     7774    /* A shell is interactive if the '-i' flag was given,
     7775     * or if all of the following conditions are met:
    37557776     *    no -c command
    37567777     *    no arguments remaining or the -s flag given
    37577778     *    standard input is a terminal
    37587779     *    standard output is a terminal
    3759      *    Refer to Posix.2, the description of the 'sh' utility. */
    3760     if (argv[optind] == NULL && input == stdin
    3761      && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)
    3762     ) {
    3763         saved_tty_pgrp = tcgetpgrp(STDIN_FILENO);
    3764         debug_printf("saved_tty_pgrp=%d\n", saved_tty_pgrp);
    3765         if (saved_tty_pgrp >= 0) {
    3766             /* try to dup to high fd#, >= 255 */
    3767             interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255);
    3768             if (interactive_fd < 0) {
    3769                 /* try to dup to any fd */
    3770                 interactive_fd = dup(STDIN_FILENO);
    3771                 if (interactive_fd < 0)
    3772                     /* give up */
    3773                     interactive_fd = 0;
    3774             }
    3775             // TODO: track & disallow any attempts of user
    3776             // to (inadvertently) close/redirect it
    3777         }
    3778     }
    3779     debug_printf("interactive_fd=%d\n", interactive_fd);
    3780     if (interactive_fd) {
    3781         /* Looks like they want an interactive shell */
    3782         setup_job_control();
    3783         /* Make xfuncs do cleanup on exit */
    3784         die_sleep = -1; /* flag */
    3785 // FIXME: should we reset die_sleep = 0 whereever we fork?
    3786         if (setjmp(die_jmp)) {
    3787             /* xfunc has failed! die die die */
    3788             hush_exit(xfunc_error_retval);
    3789         }
    3790 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
    3791         printf("\n\n%s hush - the humble shell v"HUSH_VER_STR"\n", bb_banner);
    3792         printf("Enter 'help' for a list of built-in commands.\n\n");
    3793 #endif
     7780     * Refer to Posix.2, the description of the 'sh' utility.
     7781     */
     7782#if ENABLE_HUSH_JOB
     7783    if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
     7784        G_saved_tty_pgrp = tcgetpgrp(STDIN_FILENO);
     7785        debug_printf("saved_tty_pgrp:%d\n", G_saved_tty_pgrp);
     7786        if (G_saved_tty_pgrp < 0)
     7787            G_saved_tty_pgrp = 0;
     7788
     7789        /* try to dup stdin to high fd#, >= 255 */
     7790        G_interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255);
     7791        if (G_interactive_fd < 0) {
     7792            /* try to dup to any fd */
     7793            G_interactive_fd = dup(STDIN_FILENO);
     7794            if (G_interactive_fd < 0) {
     7795                /* give up */
     7796                G_interactive_fd = 0;
     7797                G_saved_tty_pgrp = 0;
     7798            }
     7799        }
     7800// TODO: track & disallow any attempts of user
     7801// to (inadvertently) close/redirect G_interactive_fd
     7802    }
     7803    debug_printf("interactive_fd:%d\n", G_interactive_fd);
     7804    if (G_interactive_fd) {
     7805        close_on_exec_on(G_interactive_fd);
     7806
     7807        if (G_saved_tty_pgrp) {
     7808            /* If we were run as 'hush &', sleep until we are
     7809             * in the foreground (tty pgrp == our pgrp).
     7810             * If we get started under a job aware app (like bash),
     7811             * make sure we are now in charge so we don't fight over
     7812             * who gets the foreground */
     7813            while (1) {
     7814                pid_t shell_pgrp = getpgrp();
     7815                G_saved_tty_pgrp = tcgetpgrp(G_interactive_fd);
     7816                if (G_saved_tty_pgrp == shell_pgrp)
     7817                    break;
     7818                /* send TTIN to ourself (should stop us) */
     7819                kill(- shell_pgrp, SIGTTIN);
     7820            }
     7821        }
     7822
     7823        /* Block some signals */
     7824        init_sigmasks();
     7825
     7826        if (G_saved_tty_pgrp) {
     7827            /* Set other signals to restore saved_tty_pgrp */
     7828            set_fatal_handlers();
     7829            /* Put ourselves in our own process group
     7830             * (bash, too, does this only if ctty is available) */
     7831            bb_setpgrp(); /* is the same as setpgid(our_pid, our_pid); */
     7832            /* Grab control of the terminal */
     7833            tcsetpgrp(G_interactive_fd, getpid());
     7834        }
     7835        /* -1 is special - makes xfuncs longjmp, not exit
     7836         * (we reset die_sleep = 0 whereever we [v]fork) */
     7837        enable_restore_tty_pgrp_on_exit(); /* sets die_sleep = -1 */
     7838    } else {
     7839        init_sigmasks();
    37947840    }
    37957841#elif ENABLE_HUSH_INTERACTIVE
    3796 /* no job control compiled, only prompt/line editing */
    3797     if (argv[optind] == NULL && input == stdin
    3798      && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)
    3799     ) {
    3800         interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255);
    3801         if (interactive_fd < 0) {
     7842    /* No job control compiled in, only prompt/line editing */
     7843    if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
     7844        G_interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255);
     7845        if (G_interactive_fd < 0) {
    38027846            /* try to dup to any fd */
    3803             interactive_fd = dup(STDIN_FILENO);
    3804             if (interactive_fd < 0)
     7847            G_interactive_fd = dup(STDIN_FILENO);
     7848            if (G_interactive_fd < 0)
    38057849                /* give up */
    3806                 interactive_fd = 0;
    3807         }
    3808     }
    3809 
    3810 #endif
    3811 
    3812     if (argv[optind] == NULL) {
    3813         opt = parse_and_run_file(stdin);
    3814         goto final_return;
    3815     }
    3816 
    3817     debug_printf("\nrunning script '%s'\n", argv[optind]);
    3818     global_argv = argv + optind;
    3819     global_argc = argc - optind;
    3820     input = xfopen(argv[optind], "r");
    3821     opt = parse_and_run_file(input);
     7850                G_interactive_fd = 0;
     7851        }
     7852    }
     7853    if (G_interactive_fd) {
     7854        close_on_exec_on(G_interactive_fd);
     7855    }
     7856    init_sigmasks();
     7857#else
     7858    /* We have interactiveness code disabled */
     7859    init_sigmasks();
     7860#endif
     7861    /* bash:
     7862     * if interactive but not a login shell, sources ~/.bashrc
     7863     * (--norc turns this off, --rcfile <file> overrides)
     7864     */
     7865
     7866    if (!ENABLE_FEATURE_SH_EXTRA_QUIET && G_interactive_fd) {
     7867        /* note: ash and hush share this string */
     7868        printf("\n\n%s %s\n"
     7869            IF_HUSH_HELP("Enter 'help' for a list of built-in commands.\n")
     7870            "\n",
     7871            bb_banner,
     7872            "hush - the humble shell"
     7873        );
     7874    }
     7875
     7876    parse_and_run_file(stdin);
    38227877
    38237878 final_return:
    3824 
    3825 #if ENABLE_FEATURE_CLEAN_UP
     7879    hush_exit(G.last_exitcode);
     7880}
     7881
     7882
     7883#if ENABLE_MSH
     7884int msh_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     7885int msh_main(int argc, char **argv)
     7886{
     7887    //bb_error_msg("msh is deprecated, please use hush instead");
     7888    return hush_main(argc, argv);
     7889}
     7890#endif
     7891
     7892
     7893/*
     7894 * Built-ins
     7895 */
     7896static int FAST_FUNC builtin_true(char **argv UNUSED_PARAM)
     7897{
     7898    return 0;
     7899}
     7900
     7901static int run_applet_main(char **argv, int (*applet_main_func)(int argc, char **argv))
     7902{
     7903    int argc = 0;
     7904    while (*argv) {
     7905        argc++;
     7906        argv++;
     7907    }
     7908    return applet_main_func(argc, argv - argc);
     7909}
     7910
     7911static int FAST_FUNC builtin_test(char **argv)
     7912{
     7913    return run_applet_main(argv, test_main);
     7914}
     7915
     7916static int FAST_FUNC builtin_echo(char **argv)
     7917{
     7918    return run_applet_main(argv, echo_main);
     7919}
     7920
     7921#if ENABLE_PRINTF
     7922static int FAST_FUNC builtin_printf(char **argv)
     7923{
     7924    return run_applet_main(argv, printf_main);
     7925}
     7926#endif
     7927
     7928static char **skip_dash_dash(char **argv)
     7929{
     7930    argv++;
     7931    if (argv[0] && argv[0][0] == '-' && argv[0][1] == '-' && argv[0][2] == '\0')
     7932        argv++;
     7933    return argv;
     7934}
     7935
     7936static int FAST_FUNC builtin_eval(char **argv)
     7937{
     7938    int rcode = EXIT_SUCCESS;
     7939
     7940    argv = skip_dash_dash(argv);
     7941    if (*argv) {
     7942        char *str = expand_strvec_to_string(argv);
     7943        /* bash:
     7944         * eval "echo Hi; done" ("done" is syntax error):
     7945         * "echo Hi" will not execute too.
     7946         */
     7947        parse_and_run_string(str);
     7948        free(str);
     7949        rcode = G.last_exitcode;
     7950    }
     7951    return rcode;
     7952}
     7953
     7954static int FAST_FUNC builtin_cd(char **argv)
     7955{
     7956    const char *newdir;
     7957
     7958    argv = skip_dash_dash(argv);
     7959    newdir = argv[0];
     7960    if (newdir == NULL) {
     7961        /* bash does nothing (exitcode 0) if HOME is ""; if it's unset,
     7962         * bash says "bash: cd: HOME not set" and does nothing
     7963         * (exitcode 1)
     7964         */
     7965        const char *home = get_local_var_value("HOME");
     7966        newdir = home ? home : "/";
     7967    }
     7968    if (chdir(newdir)) {
     7969        /* Mimic bash message exactly */
     7970        bb_perror_msg("cd: %s", newdir);
     7971        return EXIT_FAILURE;
     7972    }
     7973    /* Read current dir (get_cwd(1) is inside) and set PWD.
     7974     * Note: do not enforce exporting. If PWD was unset or unexported,
     7975     * set it again, but do not export. bash does the same.
     7976     */
     7977    set_pwd_var(/*exp:*/ 0);
     7978    return EXIT_SUCCESS;
     7979}
     7980
     7981static int FAST_FUNC builtin_exec(char **argv)
     7982{
     7983    argv = skip_dash_dash(argv);
     7984    if (argv[0] == NULL)
     7985        return EXIT_SUCCESS; /* bash does this */
     7986
     7987    /* Careful: we can end up here after [v]fork. Do not restore
     7988     * tty pgrp then, only top-level shell process does that */
     7989    if (G_saved_tty_pgrp && getpid() == G.root_pid)
     7990        tcsetpgrp(G_interactive_fd, G_saved_tty_pgrp);
     7991
     7992    /* TODO: if exec fails, bash does NOT exit! We do.
     7993     * We'll need to undo sigprocmask (it's inside execvp_or_die)
     7994     * and tcsetpgrp, and this is inherently racy.
     7995     */
     7996    execvp_or_die(argv);
     7997}
     7998
     7999static int FAST_FUNC builtin_exit(char **argv)
     8000{
     8001    debug_printf_exec("%s()\n", __func__);
     8002
     8003    /* interactive bash:
     8004     * # trap "echo EEE" EXIT
     8005     * # exit
     8006     * exit
     8007     * There are stopped jobs.
     8008     * (if there are _stopped_ jobs, running ones don't count)
     8009     * # exit
     8010     * exit
     8011     # EEE (then bash exits)
     8012     *
     8013     * TODO: we can use G.exiting = -1 as indicator "last cmd was exit"
     8014     */
     8015
     8016    /* note: EXIT trap is run by hush_exit */
     8017    argv = skip_dash_dash(argv);
     8018    if (argv[0] == NULL)
     8019        hush_exit(G.last_exitcode);
     8020    /* mimic bash: exit 123abc == exit 255 + error msg */
     8021    xfunc_error_retval = 255;
     8022    /* bash: exit -2 == exit 254, no error msg */
     8023    hush_exit(xatoi(argv[0]) & 0xff);
     8024}
     8025
     8026static void print_escaped(const char *s)
     8027{
     8028    if (*s == '\'')
     8029        goto squote;
     8030    do {
     8031        const char *p = strchrnul(s, '\'');
     8032        /* print 'xxxx', possibly just '' */
     8033        printf("'%.*s'", (int)(p - s), s);
     8034        if (*p == '\0')
     8035            break;
     8036        s = p;
     8037 squote:
     8038        /* s points to '; print "'''...'''" */
     8039        putchar('"');
     8040        do putchar('\''); while (*++s == '\'');
     8041        putchar('"');
     8042    } while (*s);
     8043}
     8044
     8045#if !ENABLE_HUSH_LOCAL
     8046#define helper_export_local(argv, exp, lvl) \
     8047    helper_export_local(argv, exp)
     8048#endif
     8049static void helper_export_local(char **argv, int exp, int lvl)
     8050{
     8051    do {
     8052        char *name = *argv;
     8053        char *name_end = strchrnul(name, '=');
     8054
     8055        /* So far we do not check that name is valid (TODO?) */
     8056
     8057        if (*name_end == '\0') {
     8058            struct variable *var, **vpp;
     8059
     8060            vpp = get_ptr_to_local_var(name, name_end - name);
     8061            var = vpp ? *vpp : NULL;
     8062
     8063            if (exp == -1) { /* unexporting? */
     8064                /* export -n NAME (without =VALUE) */
     8065                if (var) {
     8066                    var->flg_export = 0;
     8067                    debug_printf_env("%s: unsetenv '%s'\n", __func__, name);
     8068                    unsetenv(name);
     8069                } /* else: export -n NOT_EXISTING_VAR: no-op */
     8070                continue;
     8071            }
     8072            if (exp == 1) { /* exporting? */
     8073                /* export NAME (without =VALUE) */
     8074                if (var) {
     8075                    var->flg_export = 1;
     8076                    debug_printf_env("%s: putenv '%s'\n", __func__, var->varstr);
     8077                    putenv(var->varstr);
     8078                    continue;
     8079                }
     8080            }
     8081            /* Exporting non-existing variable.
     8082             * bash does not put it in environment,
     8083             * but remembers that it is exported,
     8084             * and does put it in env when it is set later.
     8085             * We just set it to "" and export. */
     8086            /* Or, it's "local NAME" (without =VALUE).
     8087             * bash sets the value to "". */
     8088            name = xasprintf("%s=", name);
     8089        } else {
     8090            /* (Un)exporting/making local NAME=VALUE */
     8091            name = xstrdup(name);
     8092        }
     8093        set_local_var(name, /*exp:*/ exp, /*lvl:*/ lvl, /*ro:*/ 0);
     8094    } while (*++argv);
     8095}
     8096
     8097static int FAST_FUNC builtin_export(char **argv)
     8098{
     8099    unsigned opt_unexport;
     8100
     8101#if ENABLE_HUSH_EXPORT_N
     8102    /* "!": do not abort on errors */
     8103    opt_unexport = getopt32(argv, "!n");
     8104    if (opt_unexport == (uint32_t)-1)
     8105        return EXIT_FAILURE;
     8106    argv += optind;
     8107#else
     8108    opt_unexport = 0;
     8109    argv++;
     8110#endif
     8111
     8112    if (argv[0] == NULL) {
     8113        char **e = environ;
     8114        if (e) {
     8115            while (*e) {
     8116#if 0
     8117                puts(*e++);
     8118#else
     8119                /* ash emits: export VAR='VAL'
     8120                 * bash: declare -x VAR="VAL"
     8121                 * we follow ash example */
     8122                const char *s = *e++;
     8123                const char *p = strchr(s, '=');
     8124
     8125                if (!p) /* wtf? take next variable */
     8126                    continue;
     8127                /* export var= */
     8128                printf("export %.*s", (int)(p - s) + 1, s);
     8129                print_escaped(p + 1);
     8130                putchar('\n');
     8131#endif
     8132            }
     8133            /*fflush_all(); - done after each builtin anyway */
     8134        }
     8135        return EXIT_SUCCESS;
     8136    }
     8137
     8138    helper_export_local(argv, (opt_unexport ? -1 : 1), 0);
     8139
     8140    return EXIT_SUCCESS;
     8141}
     8142
     8143#if ENABLE_HUSH_LOCAL
     8144static int FAST_FUNC builtin_local(char **argv)
     8145{
     8146    if (G.func_nest_level == 0) {
     8147        bb_error_msg("%s: not in a function", argv[0]);
     8148        return EXIT_FAILURE; /* bash compat */
     8149    }
     8150    helper_export_local(argv, 0, G.func_nest_level);
     8151    return EXIT_SUCCESS;
     8152}
     8153#endif
     8154
     8155static int FAST_FUNC builtin_trap(char **argv)
     8156{
     8157    int sig;
     8158    char *new_cmd;
     8159
     8160    if (!G.traps)
     8161        G.traps = xzalloc(sizeof(G.traps[0]) * NSIG);
     8162
     8163    argv++;
     8164    if (!*argv) {
     8165        int i;
     8166        /* No args: print all trapped */
     8167        for (i = 0; i < NSIG; ++i) {
     8168            if (G.traps[i]) {
     8169                printf("trap -- ");
     8170                print_escaped(G.traps[i]);
     8171                /* note: bash adds "SIG", but only if invoked
     8172                 * as "bash". If called as "sh", or if set -o posix,
     8173                 * then it prints short signal names.
     8174                 * We are printing short names: */
     8175                printf(" %s\n", get_signame(i));
     8176            }
     8177        }
     8178        /*fflush_all(); - done after each builtin anyway */
     8179        return EXIT_SUCCESS;
     8180    }
     8181
     8182    new_cmd = NULL;
     8183    /* If first arg is a number: reset all specified signals */
     8184    sig = bb_strtou(*argv, NULL, 10);
     8185    if (errno == 0) {
     8186        int ret;
     8187 process_sig_list:
     8188        ret = EXIT_SUCCESS;
     8189        while (*argv) {
     8190            sig = get_signum(*argv++);
     8191            if (sig < 0 || sig >= NSIG) {
     8192                ret = EXIT_FAILURE;
     8193                /* Mimic bash message exactly */
     8194                bb_perror_msg("trap: %s: invalid signal specification", argv[-1]);
     8195                continue;
     8196            }
     8197
     8198            free(G.traps[sig]);
     8199            G.traps[sig] = xstrdup(new_cmd);
     8200
     8201            debug_printf("trap: setting SIG%s (%i) to '%s'\n",
     8202                get_signame(sig), sig, G.traps[sig]);
     8203
     8204            /* There is no signal for 0 (EXIT) */
     8205            if (sig == 0)
     8206                continue;
     8207
     8208            if (new_cmd) {
     8209                sigaddset(&G.blocked_set, sig);
     8210            } else {
     8211                /* There was a trap handler, we are removing it
     8212                 * (if sig has non-DFL handling,
     8213                 * we don't need to do anything) */
     8214                if (sig < 32 && (G.non_DFL_mask & (1 << sig)))
     8215                    continue;
     8216                sigdelset(&G.blocked_set, sig);
     8217            }
     8218        }
     8219        sigprocmask(SIG_SETMASK, &G.blocked_set, NULL);
     8220        return ret;
     8221    }
     8222
     8223    if (!argv[1]) { /* no second arg */
     8224        bb_error_msg("trap: invalid arguments");
     8225        return EXIT_FAILURE;
     8226    }
     8227
     8228    /* First arg is "-": reset all specified to default */
     8229    /* First arg is "--": skip it, the rest is "handler SIGs..." */
     8230    /* Everything else: set arg as signal handler
     8231     * (includes "" case, which ignores signal) */
     8232    if (argv[0][0] == '-') {
     8233        if (argv[0][1] == '\0') { /* "-" */
     8234            /* new_cmd remains NULL: "reset these sigs" */
     8235            goto reset_traps;
     8236        }
     8237        if (argv[0][1] == '-' && argv[0][2] == '\0') { /* "--" */
     8238            argv++;
     8239        }
     8240        /* else: "-something", no special meaning */
     8241    }
     8242    new_cmd = *argv;
     8243 reset_traps:
     8244    argv++;
     8245    goto process_sig_list;
     8246}
     8247
     8248/* http://www.opengroup.org/onlinepubs/9699919799/utilities/type.html */
     8249static int FAST_FUNC builtin_type(char **argv)
     8250{
     8251    int ret = EXIT_SUCCESS;
     8252
     8253    while (*++argv) {
     8254        const char *type;
     8255        char *path = NULL;
     8256
     8257        if (0) {} /* make conditional compile easier below */
     8258        /*else if (find_alias(*argv))
     8259            type = "an alias";*/
     8260#if ENABLE_HUSH_FUNCTIONS
     8261        else if (find_function(*argv))
     8262            type = "a function";
     8263#endif
     8264        else if (find_builtin(*argv))
     8265            type = "a shell builtin";
     8266        else if ((path = find_in_path(*argv)) != NULL)
     8267            type = path;
     8268        else {
     8269            bb_error_msg("type: %s: not found", *argv);
     8270            ret = EXIT_FAILURE;
     8271            continue;
     8272        }
     8273
     8274        printf("%s is %s\n", *argv, type);
     8275        free(path);
     8276    }
     8277
     8278    return ret;
     8279}
     8280
     8281#if ENABLE_HUSH_JOB
     8282/* built-in 'fg' and 'bg' handler */
     8283static int FAST_FUNC builtin_fg_bg(char **argv)
     8284{
     8285    int i, jobnum;
     8286    struct pipe *pi;
     8287
     8288    if (!G_interactive_fd)
     8289        return EXIT_FAILURE;
     8290
     8291    /* If they gave us no args, assume they want the last backgrounded task */
     8292    if (!argv[1]) {
     8293        for (pi = G.job_list; pi; pi = pi->next) {
     8294            if (pi->jobid == G.last_jobid) {
     8295                goto found;
     8296            }
     8297        }
     8298        bb_error_msg("%s: no current job", argv[0]);
     8299        return EXIT_FAILURE;
     8300    }
     8301    if (sscanf(argv[1], "%%%d", &jobnum) != 1) {
     8302        bb_error_msg("%s: bad argument '%s'", argv[0], argv[1]);
     8303        return EXIT_FAILURE;
     8304    }
     8305    for (pi = G.job_list; pi; pi = pi->next) {
     8306        if (pi->jobid == jobnum) {
     8307            goto found;
     8308        }
     8309    }
     8310    bb_error_msg("%s: %d: no such job", argv[0], jobnum);
     8311    return EXIT_FAILURE;
     8312 found:
     8313    /* TODO: bash prints a string representation
     8314     * of job being foregrounded (like "sleep 1 | cat") */
     8315    if (argv[0][0] == 'f' && G_saved_tty_pgrp) {
     8316        /* Put the job into the foreground.  */
     8317        tcsetpgrp(G_interactive_fd, pi->pgrp);
     8318    }
     8319
     8320    /* Restart the processes in the job */
     8321    debug_printf_jobs("reviving %d procs, pgrp %d\n", pi->num_cmds, pi->pgrp);
     8322    for (i = 0; i < pi->num_cmds; i++) {
     8323        debug_printf_jobs("reviving pid %d\n", pi->cmds[i].pid);
     8324        pi->cmds[i].is_stopped = 0;
     8325    }
     8326    pi->stopped_cmds = 0;
     8327
     8328    i = kill(- pi->pgrp, SIGCONT);
     8329    if (i < 0) {
     8330        if (errno == ESRCH) {
     8331            delete_finished_bg_job(pi);
     8332            return EXIT_SUCCESS;
     8333        }
     8334        bb_perror_msg("kill (SIGCONT)");
     8335    }
     8336
     8337    if (argv[0][0] == 'f') {
     8338        remove_bg_job(pi);
     8339        return checkjobs_and_fg_shell(pi);
     8340    }
     8341    return EXIT_SUCCESS;
     8342}
     8343#endif
     8344
     8345#if ENABLE_HUSH_HELP
     8346static int FAST_FUNC builtin_help(char **argv UNUSED_PARAM)
     8347{
     8348    const struct built_in_command *x;
     8349
     8350    printf(
     8351        "Built-in commands:\n"
     8352        "------------------\n");
     8353    for (x = bltins1; x != &bltins1[ARRAY_SIZE(bltins1)]; x++) {
     8354        if (x->b_descr)
     8355            printf("%-10s%s\n", x->b_cmd, x->b_descr);
     8356    }
     8357    bb_putchar('\n');
     8358    return EXIT_SUCCESS;
     8359}
     8360#endif
     8361
     8362#if ENABLE_HUSH_JOB
     8363static int FAST_FUNC builtin_jobs(char **argv UNUSED_PARAM)
     8364{
     8365    struct pipe *job;
     8366    const char *status_string;
     8367
     8368    for (job = G.job_list; job; job = job->next) {
     8369        if (job->alive_cmds == job->stopped_cmds)
     8370            status_string = "Stopped";
     8371        else
     8372            status_string = "Running";
     8373
     8374        printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->cmdtext);
     8375    }
     8376    return EXIT_SUCCESS;
     8377}
     8378#endif
     8379
     8380#if HUSH_DEBUG
     8381static int FAST_FUNC builtin_memleak(char **argv UNUSED_PARAM)
     8382{
     8383    void *p;
     8384    unsigned long l;
     8385
     8386# ifdef M_TRIM_THRESHOLD
     8387    /* Optional. Reduces probability of false positives */
     8388    malloc_trim(0);
     8389# endif
     8390    /* Crude attempt to find where "free memory" starts,
     8391     * sans fragmentation. */
     8392    p = malloc(240);
     8393    l = (unsigned long)p;
     8394    free(p);
     8395    p = malloc(3400);
     8396    if (l < (unsigned long)p) l = (unsigned long)p;
     8397    free(p);
     8398
     8399    if (!G.memleak_value)
     8400        G.memleak_value = l;
     8401
     8402    l -= G.memleak_value;
     8403    if ((long)l < 0)
     8404        l = 0;
     8405    l /= 1024;
     8406    if (l > 127)
     8407        l = 127;
     8408
     8409    /* Exitcode is "how many kilobytes we leaked since 1st call" */
     8410    return l;
     8411}
     8412#endif
     8413
     8414static int FAST_FUNC builtin_pwd(char **argv UNUSED_PARAM)
     8415{
     8416    puts(get_cwd(0));
     8417    return EXIT_SUCCESS;
     8418}
     8419
     8420static int FAST_FUNC builtin_read(char **argv)
     8421{
     8422    const char *r;
     8423    char *opt_n = NULL;
     8424    char *opt_p = NULL;
     8425    char *opt_t = NULL;
     8426    char *opt_u = NULL;
     8427    int read_flags;
     8428
     8429    /* "!": do not abort on errors.
     8430     * Option string must start with "sr" to match BUILTIN_READ_xxx
     8431     */
     8432    read_flags = getopt32(argv, "!srn:p:t:u:", &opt_n, &opt_p, &opt_t, &opt_u);
     8433    if (read_flags == (uint32_t)-1)
     8434        return EXIT_FAILURE;
     8435    argv += optind;
     8436
     8437    r = shell_builtin_read(set_local_var_from_halves,
     8438        argv,
     8439        get_local_var_value("IFS"), /* can be NULL */
     8440        read_flags,
     8441        opt_n,
     8442        opt_p,
     8443        opt_t,
     8444        opt_u
     8445    );
     8446
     8447    if ((uintptr_t)r > 1) {
     8448        bb_error_msg("%s", r);
     8449        r = (char*)(uintptr_t)1;
     8450    }
     8451
     8452    return (uintptr_t)r;
     8453}
     8454
     8455/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set
     8456 * built-in 'set' handler
     8457 * SUSv3 says:
     8458 * set [-abCefhmnuvx] [-o option] [argument...]
     8459 * set [+abCefhmnuvx] [+o option] [argument...]
     8460 * set -- [argument...]
     8461 * set -o
     8462 * set +o
     8463 * Implementations shall support the options in both their hyphen and
     8464 * plus-sign forms. These options can also be specified as options to sh.
     8465 * Examples:
     8466 * Write out all variables and their values: set
     8467 * Set $1, $2, and $3 and set "$#" to 3: set c a b
     8468 * Turn on the -x and -v options: set -xv
     8469 * Unset all positional parameters: set --
     8470 * Set $1 to the value of x, even if it begins with '-' or '+': set -- "$x"
     8471 * Set the positional parameters to the expansion of x, even if x expands
     8472 * with a leading '-' or '+': set -- $x
     8473 *
     8474 * So far, we only support "set -- [argument...]" and some of the short names.
     8475 */
     8476static int FAST_FUNC builtin_set(char **argv)
     8477{
     8478    int n;
     8479    char **pp, **g_argv;
     8480    char *arg = *++argv;
     8481
     8482    if (arg == NULL) {
     8483        struct variable *e;
     8484        for (e = G.top_var; e; e = e->next)
     8485            puts(e->varstr);
     8486        return EXIT_SUCCESS;
     8487    }
     8488
     8489    do {
     8490        if (strcmp(arg, "--") == 0) {
     8491            ++argv;
     8492            goto set_argv;
     8493        }
     8494        if (arg[0] != '+' && arg[0] != '-')
     8495            break;
     8496        for (n = 1; arg[n]; ++n) {
     8497            if (set_mode((arg[0] == '-'), arg[n], argv[1]))
     8498                goto error;
     8499            if (arg[n] == 'o' && argv[1])
     8500                argv++;
     8501        }
     8502    } while ((arg = *++argv) != NULL);
     8503    /* Now argv[0] is 1st argument */
     8504
     8505    if (arg == NULL)
     8506        return EXIT_SUCCESS;
     8507 set_argv:
     8508
     8509    /* NB: G.global_argv[0] ($0) is never freed/changed */
     8510    g_argv = G.global_argv;
     8511    if (G.global_args_malloced) {
     8512        pp = g_argv;
     8513        while (*++pp)
     8514            free(*pp);
     8515        g_argv[1] = NULL;
     8516    } else {
     8517        G.global_args_malloced = 1;
     8518        pp = xzalloc(sizeof(pp[0]) * 2);
     8519        pp[0] = g_argv[0]; /* retain $0 */
     8520        g_argv = pp;
     8521    }
     8522    /* This realloc's G.global_argv */
     8523    G.global_argv = pp = add_strings_to_strings(g_argv, argv, /*dup:*/ 1);
     8524
     8525    n = 1;
     8526    while (*++pp)
     8527        n++;
     8528    G.global_argc = n;
     8529
     8530    return EXIT_SUCCESS;
     8531
     8532    /* Nothing known, so abort */
     8533 error:
     8534    bb_error_msg("set: %s: invalid option", arg);
     8535    return EXIT_FAILURE;
     8536}
     8537
     8538static int FAST_FUNC builtin_shift(char **argv)
     8539{
     8540    int n = 1;
     8541    argv = skip_dash_dash(argv);
     8542    if (argv[0]) {
     8543        n = atoi(argv[0]);
     8544    }
     8545    if (n >= 0 && n < G.global_argc) {
     8546        if (G.global_args_malloced) {
     8547            int m = 1;
     8548            while (m <= n)
     8549                free(G.global_argv[m++]);
     8550        }
     8551        G.global_argc -= n;
     8552        memmove(&G.global_argv[1], &G.global_argv[n+1],
     8553                G.global_argc * sizeof(G.global_argv[0]));
     8554        return EXIT_SUCCESS;
     8555    }
     8556    return EXIT_FAILURE;
     8557}
     8558
     8559static int FAST_FUNC builtin_source(char **argv)
     8560{
     8561    char *arg_path, *filename;
     8562    FILE *input;
     8563    save_arg_t sv;
     8564#if ENABLE_HUSH_FUNCTIONS
     8565    smallint sv_flg;
     8566#endif
     8567
     8568    argv = skip_dash_dash(argv);
     8569    filename = argv[0];
     8570    if (!filename) {
     8571        /* bash says: "bash: .: filename argument required" */
     8572        return 2; /* bash compat */
     8573    }
     8574    arg_path = NULL;
     8575    if (!strchr(filename, '/')) {
     8576        arg_path = find_in_path(filename);
     8577        if (arg_path)
     8578            filename = arg_path;
     8579    }
     8580    input = fopen_or_warn(filename, "r");
     8581    free(arg_path);
     8582    if (!input) {
     8583        /* bb_perror_msg("%s", *argv); - done by fopen_or_warn */
     8584        return EXIT_FAILURE;
     8585    }
     8586    close_on_exec_on(fileno(input));
     8587
     8588#if ENABLE_HUSH_FUNCTIONS
     8589    sv_flg = G.flag_return_in_progress;
     8590    /* "we are inside sourced file, ok to use return" */
     8591    G.flag_return_in_progress = -1;
     8592#endif
     8593    save_and_replace_G_args(&sv, argv);
     8594
     8595    parse_and_run_file(input);
    38268596    fclose(input);
    3827     if (cwd != bb_msg_unknown)
    3828         free((char*)cwd);
    3829     cur_var = top_var->next;
    3830     while (cur_var) {
    3831         struct variable *tmp = cur_var;
    3832         if (!cur_var->max_len)
    3833             free(cur_var->varstr);
    3834         cur_var = cur_var->next;
    3835         free(tmp);
    3836     }
    3837 #endif
    3838     hush_exit(opt ? opt : last_return_code);
    3839 }
     8597
     8598    restore_G_args(&sv, argv);
     8599#if ENABLE_HUSH_FUNCTIONS
     8600    G.flag_return_in_progress = sv_flg;
     8601#endif
     8602
     8603    return G.last_exitcode;
     8604}
     8605
     8606static int FAST_FUNC builtin_umask(char **argv)
     8607{
     8608    int rc;
     8609    mode_t mask;
     8610
     8611    mask = umask(0);
     8612    argv = skip_dash_dash(argv);
     8613    if (argv[0]) {
     8614        mode_t old_mask = mask;
     8615
     8616        mask ^= 0777;
     8617        rc = bb_parse_mode(argv[0], &mask);
     8618        mask ^= 0777;
     8619        if (rc == 0) {
     8620            mask = old_mask;
     8621            /* bash messages:
     8622             * bash: umask: 'q': invalid symbolic mode operator
     8623             * bash: umask: 999: octal number out of range
     8624             */
     8625            bb_error_msg("%s: invalid mode '%s'", "umask", argv[0]);
     8626        }
     8627    } else {
     8628        rc = 1;
     8629        /* Mimic bash */
     8630        printf("%04o\n", (unsigned) mask);
     8631        /* fall through and restore mask which we set to 0 */
     8632    }
     8633    umask(mask);
     8634
     8635    return !rc; /* rc != 0 - success */
     8636}
     8637
     8638/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#unset */
     8639static int FAST_FUNC builtin_unset(char **argv)
     8640{
     8641    int ret;
     8642    unsigned opts;
     8643
     8644    /* "!": do not abort on errors */
     8645    /* "+": stop at 1st non-option */
     8646    opts = getopt32(argv, "!+vf");
     8647    if (opts == (unsigned)-1)
     8648        return EXIT_FAILURE;
     8649    if (opts == 3) {
     8650        bb_error_msg("unset: -v and -f are exclusive");
     8651        return EXIT_FAILURE;
     8652    }
     8653    argv += optind;
     8654
     8655    ret = EXIT_SUCCESS;
     8656    while (*argv) {
     8657        if (!(opts & 2)) { /* not -f */
     8658            if (unset_local_var(*argv)) {
     8659                /* unset <nonexistent_var> doesn't fail.
     8660                 * Error is when one tries to unset RO var.
     8661                 * Message was printed by unset_local_var. */
     8662                ret = EXIT_FAILURE;
     8663            }
     8664        }
     8665#if ENABLE_HUSH_FUNCTIONS
     8666        else {
     8667            unset_func(*argv);
     8668        }
     8669#endif
     8670        argv++;
     8671    }
     8672    return ret;
     8673}
     8674
     8675/* http://www.opengroup.org/onlinepubs/9699919799/utilities/wait.html */
     8676static int FAST_FUNC builtin_wait(char **argv)
     8677{
     8678    int ret = EXIT_SUCCESS;
     8679    int status, sig;
     8680
     8681    argv = skip_dash_dash(argv);
     8682    if (argv[0] == NULL) {
     8683        /* Don't care about wait results */
     8684        /* Note 1: must wait until there are no more children */
     8685        /* Note 2: must be interruptible */
     8686        /* Examples:
     8687         * $ sleep 3 & sleep 6 & wait
     8688         * [1] 30934 sleep 3
     8689         * [2] 30935 sleep 6
     8690         * [1] Done                   sleep 3
     8691         * [2] Done                   sleep 6
     8692         * $ sleep 3 & sleep 6 & wait
     8693         * [1] 30936 sleep 3
     8694         * [2] 30937 sleep 6
     8695         * [1] Done                   sleep 3
     8696         * ^C <-- after ~4 sec from keyboard
     8697         * $
     8698         */
     8699        sigaddset(&G.blocked_set, SIGCHLD);
     8700        sigprocmask(SIG_SETMASK, &G.blocked_set, NULL);
     8701        while (1) {
     8702            checkjobs(NULL);
     8703            if (errno == ECHILD)
     8704                break;
     8705            /* Wait for SIGCHLD or any other signal of interest */
     8706            /* sigtimedwait with infinite timeout: */
     8707            sig = sigwaitinfo(&G.blocked_set, NULL);
     8708            if (sig > 0) {
     8709                sig = check_and_run_traps(sig);
     8710                if (sig && sig != SIGCHLD) { /* see note 2 */
     8711                    ret = 128 + sig;
     8712                    break;
     8713                }
     8714            }
     8715        }
     8716        sigdelset(&G.blocked_set, SIGCHLD);
     8717        sigprocmask(SIG_SETMASK, &G.blocked_set, NULL);
     8718        return ret;
     8719    }
     8720
     8721    /* This is probably buggy wrt interruptible-ness */
     8722    while (*argv) {
     8723        pid_t pid = bb_strtou(*argv, NULL, 10);
     8724        if (errno) {
     8725            /* mimic bash message */
     8726            bb_error_msg("wait: '%s': not a pid or valid job spec", *argv);
     8727            return EXIT_FAILURE;
     8728        }
     8729        if (waitpid(pid, &status, 0) == pid) {
     8730            if (WIFSIGNALED(status))
     8731                ret = 128 + WTERMSIG(status);
     8732            else if (WIFEXITED(status))
     8733                ret = WEXITSTATUS(status);
     8734            else /* wtf? */
     8735                ret = EXIT_FAILURE;
     8736        } else {
     8737            bb_perror_msg("wait %s", *argv);
     8738            ret = 127;
     8739        }
     8740        argv++;
     8741    }
     8742
     8743    return ret;
     8744}
     8745
     8746#if ENABLE_HUSH_LOOPS || ENABLE_HUSH_FUNCTIONS
     8747static unsigned parse_numeric_argv1(char **argv, unsigned def, unsigned def_min)
     8748{
     8749    if (argv[1]) {
     8750        def = bb_strtou(argv[1], NULL, 10);
     8751        if (errno || def < def_min || argv[2]) {
     8752            bb_error_msg("%s: bad arguments", argv[0]);
     8753            def = UINT_MAX;
     8754        }
     8755    }
     8756    return def;
     8757}
     8758#endif
     8759
     8760#if ENABLE_HUSH_LOOPS
     8761static int FAST_FUNC builtin_break(char **argv)
     8762{
     8763    unsigned depth;
     8764    if (G.depth_of_loop == 0) {
     8765        bb_error_msg("%s: only meaningful in a loop", argv[0]);
     8766        return EXIT_SUCCESS; /* bash compat */
     8767    }
     8768    G.flag_break_continue++; /* BC_BREAK = 1 */
     8769
     8770    G.depth_break_continue = depth = parse_numeric_argv1(argv, 1, 1);
     8771    if (depth == UINT_MAX)
     8772        G.flag_break_continue = BC_BREAK;
     8773    if (G.depth_of_loop < depth)
     8774        G.depth_break_continue = G.depth_of_loop;
     8775
     8776    return EXIT_SUCCESS;
     8777}
     8778
     8779static int FAST_FUNC builtin_continue(char **argv)
     8780{
     8781    G.flag_break_continue = 1; /* BC_CONTINUE = 2 = 1+1 */
     8782    return builtin_break(argv);
     8783}
     8784#endif
     8785
     8786#if ENABLE_HUSH_FUNCTIONS
     8787static int FAST_FUNC builtin_return(char **argv)
     8788{
     8789    int rc;
     8790
     8791    if (G.flag_return_in_progress != -1) {
     8792        bb_error_msg("%s: not in a function or sourced script", argv[0]);
     8793        return EXIT_FAILURE; /* bash compat */
     8794    }
     8795
     8796    G.flag_return_in_progress = 1;
     8797
     8798    /* bash:
     8799     * out of range: wraps around at 256, does not error out
     8800     * non-numeric param:
     8801     * f() { false; return qwe; }; f; echo $?
     8802     * bash: return: qwe: numeric argument required  <== we do this
     8803     * 255  <== we also do this
     8804     */
     8805    rc = parse_numeric_argv1(argv, G.last_exitcode, 0);
     8806    return rc;
     8807}
     8808#endif
Note: See TracChangeset for help on using the changeset viewer.