busybox/shell/hush.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   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.
   7 *
   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.
  12 *
  13 * Credits:
  14 *      The parser routines proper are all original material, first
  15 *      written Dec 2000 and Jan 2001 by Larry Doolittle.  The
  16 *      execution engine, the builtins, and much of the underlying
  17 *      support has been adapted from busybox-0.49pre's lash, which is
  18 *      Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
  19 *      written by Erik Andersen <andersen@codepoet.org>.  That, in turn,
  20 *      is based in part on ladsh.c, by Michael K. Johnson and Erik W.
  21 *      Troan, which they placed in the public domain.  I don't know
  22 *      how much of the Johnson/Troan code has survived the repeated
  23 *      rewrites.
  24 *
  25 * Other credits:
  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.
  30 *
  31 * There are two big (and related) architecture differences between
  32 * this parser and the lash parser.  One is that this version is
  33 * actually designed from the ground up to understand nearly all
  34 * of the Bourne grammar.  The second, consequential change is that
  35 * the parser and input reader have been turned inside out.  Now,
  36 * the parser is in control, and asks for input as needed.  The old
  37 * way had the input reader in control, and it asked for parsing to
  38 * take place as needed.  The new way makes it much easier to properly
  39 * handle the recursion implicit in the various substitutions, especially
  40 * across continuation lines.
  41 *
  42 * TODOs:
  43 *      grep for "TODO" and fix (some of them are easy)
  44 *      make complex ${var%...} constructs support optional
  45 *      make here documents optional
  46 *      special variables (done: PWD, PPID, RANDOM)
  47 *      follow IFS rules more precisely, including update semantics
  48 *      tilde expansion
  49 *      aliases
  50 *      "command" missing features:
  51 *          command -p CMD: run CMD using default $PATH
  52 *              (can use this to override standalone shell as well?)
  53 *          command BLTIN: disables special-ness (e.g. errors do not abort)
  54 *          command -V CMD1 CMD2 CMD3 (multiple args) (not in standard)
  55 *      builtins mandated by standards we don't support:
  56 *          [un]alias, fc:
  57 *          fc -l[nr] [BEG] [END]: list range of commands in history
  58 *          fc [-e EDITOR] [BEG] [END]: edit/rerun range of commands
  59 *          fc -s [PAT=REP] [CMD]: rerun CMD, replacing PAT with REP
  60 *
  61 * Bash compat TODO:
  62 *      redirection of stdout+stderr: &> and >&
  63 *      reserved words: function select
  64 *      advanced test: [[ ]]
  65 *      process substitution: <(list) and >(list)
  66 *      let EXPR [EXPR...]
  67 *          Each EXPR is an arithmetic expression (ARITHMETIC EVALUATION)
  68 *          If the last arg evaluates to 0, let returns 1; 0 otherwise.
  69 *          NB: let `echo 'a=a + 1'` - error (IOW: multi-word expansion is used)
  70 *      ((EXPR))
  71 *          The EXPR is evaluated according to ARITHMETIC EVALUATION.
  72 *          This is exactly equivalent to let "EXPR".
  73 *      $[EXPR]: synonym for $((EXPR))
  74 *      indirect expansion: ${!VAR}
  75 *      substring op on @: ${@:n:m}
  76 *
  77 * Won't do:
  78 *      Some builtins mandated by standards:
  79 *          newgrp [GRP]: not a builtin in bash but a suid binary
  80 *              which spawns a new shell with new group ID
  81 *
  82 * Status of [[ support:
  83 * [[ args ]] are CMD_SINGLEWORD_NOGLOB:
  84 *   v='a b'; [[ $v = 'a b' ]]; echo 0:$?
  85 *   [[ /bin/n* ]]; echo 0:$?
  86 *   = is glob match operator, not equality operator: STR = GLOB
  87 *   == same as =
  88 *   =~ is regex match operator: STR =~ REGEX
  89 * TODO:
  90 * quoting needs to be considered (-f is an operator, "-f" and ""-f are not; etc)
  91 * in word = GLOB, quoting should be significant on char-by-char basis: a*cd"*"
  92 */
  93//config:config HUSH
  94//config:       bool "hush (68 kb)"
  95//config:       default y
  96//config:       select SHELL_HUSH
  97//config:       help
  98//config:       hush is a small shell. It handles the normal flow control
  99//config:       constructs such as if/then/elif/else/fi, for/in/do/done, while loops,
 100//config:       case/esac. Redirections, here documents, $((arithmetic))
 101//config:       and functions are supported.
 102//config:
 103//config:       It will compile and work on no-mmu systems.
 104//config:
 105//config:       It does not handle select, aliases, tilde expansion,
 106//config:       &>file and >&file redirection of stdout+stderr.
 107//config:
 108// This option is visible (has a description) to make it possible to select
 109// a "scripted" applet (such as NOLOGIN) but avoid selecting any shells:
 110//config:config SHELL_HUSH
 111//config:       bool "Internal shell for embedded script support"
 112//config:       default n
 113//config:
 114//config:# hush options
 115//config:# It's only needed to get "nice" menuconfig indenting.
 116//config:if SHELL_HUSH || HUSH || SH_IS_HUSH || BASH_IS_HUSH
 117//config:
 118//config:config HUSH_BASH_COMPAT
 119//config:       bool "bash-compatible extensions"
 120//config:       default y
 121//config:       depends on SHELL_HUSH
 122//config:
 123//config:config HUSH_BRACE_EXPANSION
 124//config:       bool "Brace expansion"
 125//config:       default y
 126//config:       depends on HUSH_BASH_COMPAT
 127//config:       help
 128//config:       Enable {abc,def} extension.
 129//config:
 130//config:config HUSH_BASH_SOURCE_CURDIR
 131//config:       bool "'source' and '.' builtins search current directory after $PATH"
 132//config:       default n   # do not encourage non-standard behavior
 133//config:       depends on HUSH_BASH_COMPAT
 134//config:       help
 135//config:       This is not compliant with standards. Avoid if possible.
 136//config:
 137//config:config HUSH_LINENO_VAR
 138//config:       bool "$LINENO variable (bashism)"
 139//config:       default y
 140//config:       depends on SHELL_HUSH
 141//config:
 142//config:config HUSH_INTERACTIVE
 143//config:       bool "Interactive mode"
 144//config:       default y
 145//config:       depends on SHELL_HUSH
 146//config:       help
 147//config:       Enable interactive mode (prompt and command editing).
 148//config:       Without this, hush simply reads and executes commands
 149//config:       from stdin just like a shell script from a file.
 150//config:       No prompt, no PS1/PS2 magic shell variables.
 151//config:
 152//config:config HUSH_SAVEHISTORY
 153//config:       bool "Save command history to .hush_history"
 154//config:       default y
 155//config:       depends on HUSH_INTERACTIVE && FEATURE_EDITING_SAVEHISTORY
 156//config:
 157//config:config HUSH_JOB
 158//config:       bool "Job control"
 159//config:       default y
 160//config:       depends on HUSH_INTERACTIVE
 161//config:       help
 162//config:       Enable job control: Ctrl-Z backgrounds, Ctrl-C interrupts current
 163//config:       command (not entire shell), fg/bg builtins work. Without this option,
 164//config:       "cmd &" still works by simply spawning a process and immediately
 165//config:       prompting for next command (or executing next command in a script),
 166//config:       but no separate process group is formed.
 167//config:
 168//config:config HUSH_TICK
 169//config:       bool "Support command substitution"
 170//config:       default y
 171//config:       depends on SHELL_HUSH
 172//config:       help
 173//config:       Enable `command` and $(command).
 174//config:
 175//config:config HUSH_IF
 176//config:       bool "Support if/then/elif/else/fi"
 177//config:       default y
 178//config:       depends on SHELL_HUSH
 179//config:
 180//config:config HUSH_LOOPS
 181//config:       bool "Support for, while and until loops"
 182//config:       default y
 183//config:       depends on SHELL_HUSH
 184//config:
 185//config:config HUSH_CASE
 186//config:       bool "Support case ... esac statement"
 187//config:       default y
 188//config:       depends on SHELL_HUSH
 189//config:       help
 190//config:       Enable case ... esac statement. +400 bytes.
 191//config:
 192//config:config HUSH_FUNCTIONS
 193//config:       bool "Support funcname() { commands; } syntax"
 194//config:       default y
 195//config:       depends on SHELL_HUSH
 196//config:       help
 197//config:       Enable support for shell functions. +800 bytes.
 198//config:
 199//config:config HUSH_LOCAL
 200//config:       bool "local builtin"
 201//config:       default y
 202//config:       depends on HUSH_FUNCTIONS
 203//config:       help
 204//config:       Enable support for local variables in functions.
 205//config:
 206//config:config HUSH_RANDOM_SUPPORT
 207//config:       bool "Pseudorandom generator and $RANDOM variable"
 208//config:       default y
 209//config:       depends on SHELL_HUSH
 210//config:       help
 211//config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
 212//config:       Each read of "$RANDOM" will generate a new pseudorandom value.
 213//config:
 214//config:config HUSH_MODE_X
 215//config:       bool "Support 'hush -x' option and 'set -x' command"
 216//config:       default y
 217//config:       depends on SHELL_HUSH
 218//config:       help
 219//config:       This instructs hush to print commands before execution.
 220//config:       Adds ~300 bytes.
 221//config:
 222//config:config HUSH_ECHO
 223//config:       bool "echo builtin"
 224//config:       default y
 225//config:       depends on SHELL_HUSH
 226//config:
 227//config:config HUSH_PRINTF
 228//config:       bool "printf builtin"
 229//config:       default y
 230//config:       depends on SHELL_HUSH
 231//config:
 232//config:config HUSH_TEST
 233//config:       bool "test builtin"
 234//config:       default y
 235//config:       depends on SHELL_HUSH
 236//config:
 237//config:config HUSH_HELP
 238//config:       bool "help builtin"
 239//config:       default y
 240//config:       depends on SHELL_HUSH
 241//config:
 242//config:config HUSH_EXPORT
 243//config:       bool "export builtin"
 244//config:       default y
 245//config:       depends on SHELL_HUSH
 246//config:
 247//config:config HUSH_EXPORT_N
 248//config:       bool "Support 'export -n' option"
 249//config:       default y
 250//config:       depends on HUSH_EXPORT
 251//config:       help
 252//config:       export -n unexports variables. It is a bash extension.
 253//config:
 254//config:config HUSH_READONLY
 255//config:       bool "readonly builtin"
 256//config:       default y
 257//config:       depends on SHELL_HUSH
 258//config:       help
 259//config:       Enable support for read-only variables.
 260//config:
 261//config:config HUSH_KILL
 262//config:       bool "kill builtin (supports kill %jobspec)"
 263//config:       default y
 264//config:       depends on SHELL_HUSH
 265//config:
 266//config:config HUSH_WAIT
 267//config:       bool "wait builtin"
 268//config:       default y
 269//config:       depends on SHELL_HUSH
 270//config:
 271//config:config HUSH_COMMAND
 272//config:       bool "command builtin"
 273//config:       default y
 274//config:       depends on SHELL_HUSH
 275//config:
 276//config:config HUSH_TRAP
 277//config:       bool "trap builtin"
 278//config:       default y
 279//config:       depends on SHELL_HUSH
 280//config:
 281//config:config HUSH_TYPE
 282//config:       bool "type builtin"
 283//config:       default y
 284//config:       depends on SHELL_HUSH
 285//config:
 286//config:config HUSH_TIMES
 287//config:       bool "times builtin"
 288//config:       default y
 289//config:       depends on SHELL_HUSH
 290//config:
 291//config:config HUSH_READ
 292//config:       bool "read builtin"
 293//config:       default y
 294//config:       depends on SHELL_HUSH
 295//config:
 296//config:config HUSH_SET
 297//config:       bool "set builtin"
 298//config:       default y
 299//config:       depends on SHELL_HUSH
 300//config:
 301//config:config HUSH_UNSET
 302//config:       bool "unset builtin"
 303//config:       default y
 304//config:       depends on SHELL_HUSH
 305//config:
 306//config:config HUSH_ULIMIT
 307//config:       bool "ulimit builtin"
 308//config:       default y
 309//config:       depends on SHELL_HUSH
 310//config:
 311//config:config HUSH_UMASK
 312//config:       bool "umask builtin"
 313//config:       default y
 314//config:       depends on SHELL_HUSH
 315//config:
 316//config:config HUSH_GETOPTS
 317//config:       bool "getopts builtin"
 318//config:       default y
 319//config:       depends on SHELL_HUSH
 320//config:
 321//config:config HUSH_MEMLEAK
 322//config:       bool "memleak builtin (debugging)"
 323//config:       default n
 324//config:       depends on SHELL_HUSH
 325//config:
 326//config:endif # hush options
 327
 328//applet:IF_HUSH(APPLET(hush, BB_DIR_BIN, BB_SUID_DROP))
 329//                       APPLET_ODDNAME:name  main  location    suid_type     help
 330//applet:IF_SH_IS_HUSH(  APPLET_ODDNAME(sh,   hush, BB_DIR_BIN, BB_SUID_DROP, hush))
 331//applet:IF_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, BB_DIR_BIN, BB_SUID_DROP, hush))
 332
 333//kbuild:lib-$(CONFIG_SHELL_HUSH) += hush.o match.o shell_common.o
 334//kbuild:lib-$(CONFIG_HUSH_RANDOM_SUPPORT) += random.o
 335
 336/* -i (interactive) is also accepted,
 337 * but does nothing, therefore not shown in help.
 338 * NOMMU-specific options are not meant to be used by users,
 339 * therefore we don't show them either.
 340 */
 341//usage:#define hush_trivial_usage
 342//usage:        "[-enxl] [-c 'SCRIPT' [ARG0 ARGS] | FILE [ARGS] | -s [ARGS]]"
 343//usage:#define hush_full_usage "\n\n"
 344//usage:        "Unix shell interpreter"
 345
 346#if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \
 347        || defined(__APPLE__) \
 348    )
 349# include <malloc.h>   /* for malloc_trim */
 350#endif
 351#include <glob.h>
 352/* #include <dmalloc.h> */
 353#if ENABLE_HUSH_CASE
 354# include <fnmatch.h>
 355#endif
 356#include <sys/times.h>
 357#include <sys/utsname.h> /* for setting $HOSTNAME */
 358
 359#include "busybox.h"  /* for APPLET_IS_NOFORK/NOEXEC */
 360#include "unicode.h"
 361#include "shell_common.h"
 362#include "math.h"
 363#include "match.h"
 364#if ENABLE_HUSH_RANDOM_SUPPORT
 365# include "random.h"
 366#else
 367# define CLEAR_RANDOM_T(rnd) ((void)0)
 368#endif
 369#ifndef O_CLOEXEC
 370# define O_CLOEXEC 0
 371#endif
 372#ifndef F_DUPFD_CLOEXEC
 373# define F_DUPFD_CLOEXEC F_DUPFD
 374#endif
 375
 376#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS && !(ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH)
 377# include "embedded_scripts.h"
 378#else
 379# define NUM_SCRIPTS 0
 380#endif
 381
 382/* So far, all bash compat is controlled by one config option */
 383/* Separate defines document which part of code implements what */
 384#define BASH_PATTERN_SUBST ENABLE_HUSH_BASH_COMPAT
 385#define BASH_SUBSTR        ENABLE_HUSH_BASH_COMPAT
 386#define BASH_SOURCE        ENABLE_HUSH_BASH_COMPAT
 387#define BASH_DOLLAR_SQUOTE ENABLE_HUSH_BASH_COMPAT
 388#define BASH_HOSTNAME_VAR  ENABLE_HUSH_BASH_COMPAT
 389#define BASH_EPOCH_VARS    ENABLE_HUSH_BASH_COMPAT
 390#define BASH_TEST2         (ENABLE_HUSH_BASH_COMPAT && ENABLE_HUSH_TEST)
 391#define BASH_READ_D        ENABLE_HUSH_BASH_COMPAT
 392
 393
 394/* Build knobs */
 395#define LEAK_HUNTING 0
 396#define BUILD_AS_NOMMU 0
 397/* Enable/disable sanity checks. Ok to enable in production,
 398 * only adds a bit of bloat. Set to >1 to get non-production level verbosity.
 399 * Keeping 1 for now even in released versions.
 400 */
 401#define HUSH_DEBUG 1
 402/* Slightly bigger (+200 bytes), but faster hush.
 403 * So far it only enables a trick with counting SIGCHLDs and forks,
 404 * which allows us to do fewer waitpid's.
 405 * (we can detect a case where neither forks were done nor SIGCHLDs happened
 406 * and therefore waitpid will return the same result as last time)
 407 */
 408#define ENABLE_HUSH_FAST 0
 409/* TODO: implement simplified code for users which do not need ${var%...} ops
 410 * So far ${var%...} ops are always enabled:
 411 */
 412#define ENABLE_HUSH_DOLLAR_OPS 1
 413
 414
 415#if BUILD_AS_NOMMU
 416# undef BB_MMU
 417# undef USE_FOR_NOMMU
 418# undef USE_FOR_MMU
 419# define BB_MMU 0
 420# define USE_FOR_NOMMU(...) __VA_ARGS__
 421# define USE_FOR_MMU(...)
 422#endif
 423
 424#include "NUM_APPLETS.h"
 425#if NUM_APPLETS == 1
 426/* STANDALONE does not make sense, and won't compile */
 427# undef CONFIG_FEATURE_SH_STANDALONE
 428# undef ENABLE_FEATURE_SH_STANDALONE
 429# undef IF_FEATURE_SH_STANDALONE
 430# undef IF_NOT_FEATURE_SH_STANDALONE
 431# define ENABLE_FEATURE_SH_STANDALONE 0
 432# define IF_FEATURE_SH_STANDALONE(...)
 433# define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
 434#endif
 435
 436#if !ENABLE_HUSH_INTERACTIVE
 437# undef ENABLE_FEATURE_EDITING
 438# define ENABLE_FEATURE_EDITING 0
 439# undef ENABLE_FEATURE_EDITING_FANCY_PROMPT
 440# define ENABLE_FEATURE_EDITING_FANCY_PROMPT 0
 441# undef ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
 442# define ENABLE_FEATURE_EDITING_SAVE_ON_EXIT 0
 443#endif
 444
 445/* Do we support ANY keywords? */
 446#if ENABLE_HUSH_IF || ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
 447# define HAS_KEYWORDS 1
 448# define IF_HAS_KEYWORDS(...) __VA_ARGS__
 449# define IF_HAS_NO_KEYWORDS(...)
 450#else
 451# define HAS_KEYWORDS 0
 452# define IF_HAS_KEYWORDS(...)
 453# define IF_HAS_NO_KEYWORDS(...) __VA_ARGS__
 454#endif
 455
 456/* If you comment out one of these below, it will be #defined later
 457 * to perform debug printfs to stderr: */
 458#define debug_printf(...)         do {} while (0)
 459/* Finer-grained debug switches */
 460#define debug_printf_parse(...)   do {} while (0)
 461#define debug_printf_heredoc(...) do {} while (0)
 462#define debug_print_tree(a, b)    do {} while (0)
 463#define debug_printf_exec(...)    do {} while (0)
 464#define debug_printf_env(...)     do {} while (0)
 465#define debug_printf_jobs(...)    do {} while (0)
 466#define debug_printf_expand(...)  do {} while (0)
 467#define debug_printf_varexp(...)  do {} while (0)
 468#define debug_printf_glob(...)    do {} while (0)
 469#define debug_printf_redir(...)   do {} while (0)
 470#define debug_printf_list(...)    do {} while (0)
 471#define debug_printf_subst(...)   do {} while (0)
 472#define debug_printf_prompt(...)  do {} while (0)
 473#define debug_printf_clean(...)   do {} while (0)
 474
 475#define ERR_PTR ((void*)(long)1)
 476
 477#define JOB_STATUS_FORMAT    "[%u] %-22s %.40s\n"
 478
 479#define _SPECIAL_VARS_STR     "_*@$!?#-"
 480#define SPECIAL_VARS_STR     ("_*@$!?#-" + 1)
 481#define NUMERIC_SPECVARS_STR ("_*@$!?#-" + 3)
 482#if BASH_PATTERN_SUBST
 483/* Support / and // replace ops */
 484/* Note that // is stored as \ in "encoded" string representation */
 485# define VAR_ENCODED_SUBST_OPS      "\\/%#:-=+?"
 486# define VAR_SUBST_OPS             ("\\/%#:-=+?" + 1)
 487# define MINUS_PLUS_EQUAL_QUESTION ("\\/%#:-=+?" + 5)
 488#else
 489# define VAR_ENCODED_SUBST_OPS      "%#:-=+?"
 490# define VAR_SUBST_OPS              "%#:-=+?"
 491# define MINUS_PLUS_EQUAL_QUESTION ("%#:-=+?" + 3)
 492#endif
 493
 494#define SPECIAL_VAR_SYMBOL_STR "\3"
 495#define SPECIAL_VAR_SYMBOL       3
 496/* The "variable" with name "\1" emits string "\3". Testcase: "echo ^C" */
 497#define SPECIAL_VAR_QUOTED_SVS   1
 498
 499struct variable;
 500
 501static const char hush_version_str[] ALIGN1 = "HUSH_VERSION="BB_VER;
 502
 503/* This supports saving pointers malloced in vfork child,
 504 * to be freed in the parent.
 505 */
 506#if !BB_MMU
 507typedef struct nommu_save_t {
 508        struct variable *old_vars;
 509        char **argv;
 510        char **argv_from_re_execing;
 511} nommu_save_t;
 512#endif
 513
 514enum {
 515        RES_NONE  = 0,
 516#if ENABLE_HUSH_IF
 517        RES_IF    ,
 518        RES_THEN  ,
 519        RES_ELIF  ,
 520        RES_ELSE  ,
 521        RES_FI    ,
 522#endif
 523#if ENABLE_HUSH_LOOPS
 524        RES_FOR   ,
 525        RES_WHILE ,
 526        RES_UNTIL ,
 527        RES_DO    ,
 528        RES_DONE  ,
 529#endif
 530#if ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
 531        RES_IN    ,
 532#endif
 533#if ENABLE_HUSH_CASE
 534        RES_CASE  ,
 535        /* three pseudo-keywords support contrived "case" syntax: */
 536        RES_CASE_IN,   /* "case ... IN", turns into RES_MATCH when IN is observed */
 537        RES_MATCH ,    /* "word)" */
 538        RES_CASE_BODY, /* "this command is inside CASE" */
 539        RES_ESAC  ,
 540#endif
 541        RES_XXXX  ,
 542        RES_SNTX
 543};
 544
 545typedef struct o_string {
 546        char *data;
 547        int length; /* position where data is appended */
 548        int maxlen;
 549        int o_expflags;
 550        /* At least some part of the string was inside '' or "",
 551         * possibly empty one: word"", wo''rd etc. */
 552        smallint has_quoted_part;
 553        smallint has_empty_slot;
 554        smallint ended_in_ifs;
 555} o_string;
 556enum {
 557        EXP_FLAG_SINGLEWORD     = 0x80, /* must be 0x80 */
 558        EXP_FLAG_GLOB           = 0x2,
 559        /* Protect newly added chars against globbing
 560         * by prepending \ to *, ?, [, \ */
 561        EXP_FLAG_ESC_GLOB_CHARS = 0x1,
 562};
 563/* Used for initialization: o_string foo = NULL_O_STRING; */
 564#define NULL_O_STRING { NULL }
 565
 566#ifndef debug_printf_parse
 567static const char *const assignment_flag[] = {
 568        "MAYBE_ASSIGNMENT",
 569        "DEFINITELY_ASSIGNMENT",
 570        "NOT_ASSIGNMENT",
 571        "WORD_IS_KEYWORD",
 572};
 573#endif
 574
 575/* We almost can use standard FILE api, but we need an ability to move
 576 * its fd when redirects coincide with it. No api exists for that
 577 * (RFE for it at https://sourceware.org/bugzilla/show_bug.cgi?id=21902).
 578 * HFILE is our internal alternative. Only supports reading.
 579 * Since we now can, we incorporate linked list of all opened HFILEs
 580 * into the struct (used to be a separate mini-list).
 581 */
 582typedef struct HFILE {
 583        char *cur;
 584        char *end;
 585        struct HFILE *next_hfile;
 586        int fd;
 587        char buf[1024];
 588} HFILE;
 589
 590typedef struct in_str {
 591        const char *p;
 592        int peek_buf[2];
 593        int last_char;
 594        HFILE *file;
 595} in_str;
 596
 597/* The descrip member of this structure is only used to make
 598 * debugging output pretty */
 599static const struct {
 600        int32_t mode;
 601        signed char default_fd;
 602        char descrip[3];
 603} redir_table[] ALIGN4 = {
 604        { O_RDONLY,                  0, "<"  },
 605        { O_CREAT|O_TRUNC|O_WRONLY,  1, ">"  },
 606        { O_CREAT|O_APPEND|O_WRONLY, 1, ">>" },
 607        { O_CREAT|O_RDWR,            1, "<>" },
 608        { O_RDONLY,                  0, "<<" },
 609/* Should not be needed. Bogus default_fd helps in debugging */
 610/*      { O_RDONLY,                 77, "<<" }, */
 611};
 612
 613struct redir_struct {
 614        struct redir_struct *next;
 615        char *rd_filename;          /* filename */
 616        int rd_fd;                  /* fd to redirect */
 617        /* fd to redirect to, or -3 if rd_fd is to be closed (n>&-) */
 618        int rd_dup;
 619        smallint rd_type;           /* (enum redir_type) */
 620        /* note: for heredocs, rd_filename contains heredoc delimiter,
 621         * and subsequently heredoc itself; and rd_dup is a bitmask:
 622         * bit 0: do we need to trim leading tabs?
 623         * bit 1: is heredoc quoted (<<'delim' syntax) ?
 624         */
 625};
 626typedef enum redir_type {
 627        REDIRECT_INPUT     = 0,
 628        REDIRECT_OVERWRITE = 1,
 629        REDIRECT_APPEND    = 2,
 630        REDIRECT_IO        = 3,
 631        REDIRECT_HEREDOC   = 4,
 632        REDIRECT_HEREDOC2  = 5, /* REDIRECT_HEREDOC after heredoc is loaded */
 633
 634        REDIRFD_CLOSE      = -3,
 635        REDIRFD_SYNTAX_ERR = -2,
 636        REDIRFD_TO_FILE    = -1,
 637        /* otherwise, rd_fd is redirected to rd_dup */
 638
 639        HEREDOC_SKIPTABS = 1,
 640        HEREDOC_QUOTED   = 2,
 641} redir_type;
 642
 643
 644struct command {
 645        pid_t pid;                  /* 0 if exited */
 646        unsigned assignment_cnt;    /* how many argv[i] are assignments? */
 647#if ENABLE_HUSH_LINENO_VAR
 648        unsigned lineno;
 649#endif
 650        smallint cmd_type;          /* CMD_xxx */
 651#define CMD_NORMAL   0
 652#define CMD_SUBSHELL 1
 653#if BASH_TEST2
 654/* used for "[[ EXPR ]]" */
 655# define CMD_TEST2_SINGLEWORD_NOGLOB 2
 656#endif
 657#if BASH_TEST2 || ENABLE_HUSH_LOCAL || ENABLE_HUSH_EXPORT || ENABLE_HUSH_READONLY
 658/* used to prevent word splitting and globbing in "export v=t*" */
 659# define CMD_SINGLEWORD_NOGLOB 3
 660#endif
 661#if ENABLE_HUSH_FUNCTIONS
 662# define CMD_FUNCDEF 4
 663#endif
 664
 665        smalluint cmd_exitcode;
 666        /* if non-NULL, this "command" is { list }, ( list ), or a compound statement */
 667        struct pipe *group;
 668#if !BB_MMU
 669        char *group_as_string;
 670#endif
 671#if ENABLE_HUSH_FUNCTIONS
 672        struct function *child_func;
 673/* This field is used to prevent a bug here:
 674 * while...do f1() {a;}; f1; f1() {b;}; f1; done
 675 * When we execute "f1() {a;}" cmd, we create new function and clear
 676 * cmd->group, cmd->group_as_string, cmd->argv[0].
 677 * When we execute "f1() {b;}", we notice that f1 exists,
 678 * and that its "parent cmd" struct is still "alive",
 679 * we put those fields back into cmd->xxx
 680 * (struct function has ->parent_cmd ptr to facilitate that).
 681 * When we loop back, we can execute "f1() {a;}" again and set f1 correctly.
 682 * Without this trick, loop would execute a;b;b;b;...
 683 * instead of correct sequence a;b;a;b;...
 684 * When command is freed, it severs the link
 685 * (sets ->child_func->parent_cmd to NULL).
 686 */
 687#endif
 688        char **argv;                /* command name and arguments */
 689/* argv vector may contain variable references (^Cvar^C, ^C0^C etc)
 690 * and on execution these are substituted with their values.
 691 * Substitution can make _several_ words out of one argv[n]!
 692 * Example: argv[0]=='.^C*^C.' here: echo .$*.
 693 * References of the form ^C`cmd arg^C are `cmd arg` substitutions.
 694 */
 695        struct redir_struct *redirects; /* I/O redirections */
 696};
 697/* Is there anything in this command at all? */
 698#define IS_NULL_CMD(cmd) \
 699        (!(cmd)->group && !(cmd)->argv && !(cmd)->redirects)
 700
 701struct pipe {
 702        struct pipe *next;
 703        int num_cmds;               /* total number of commands in pipe */
 704        int alive_cmds;             /* number of commands running (not exited) */
 705        int stopped_cmds;           /* number of commands alive, but stopped */
 706#if ENABLE_HUSH_JOB
 707        unsigned jobid;             /* job number */
 708        pid_t pgrp;                 /* process group ID for the job */
 709        char *cmdtext;              /* name of job */
 710#endif
 711        struct command *cmds;       /* array of commands in pipe */
 712        smallint followup;          /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */
 713        IF_HAS_KEYWORDS(smallint pi_inverted;) /* "! cmd | cmd" */
 714        IF_HAS_KEYWORDS(smallint res_word;) /* needed for if, for, while, until... */
 715};
 716typedef enum pipe_style {
 717        PIPE_SEQ = 0,
 718        PIPE_AND = 1,
 719        PIPE_OR  = 2,
 720        PIPE_BG  = 3,
 721} pipe_style;
 722/* Is there anything in this pipe at all? */
 723#define IS_NULL_PIPE(pi) \
 724        ((pi)->num_cmds == 0 IF_HAS_KEYWORDS( && (pi)->res_word == RES_NONE))
 725
 726/* This holds pointers to the various results of parsing */
 727struct parse_context {
 728        /* linked list of pipes */
 729        struct pipe *list_head;
 730        /* last pipe (being constructed right now) */
 731        struct pipe *pipe;
 732        /* last command in pipe (being constructed right now) */
 733        struct command *command;
 734        /* last redirect in command->redirects list */
 735        struct redir_struct *pending_redirect;
 736        o_string word;
 737#if !BB_MMU
 738        o_string as_string;
 739#endif
 740        smallint is_assignment; /* 0:maybe, 1:yes, 2:no, 3:keyword */
 741#if HAS_KEYWORDS
 742        smallint ctx_res_w;
 743        smallint ctx_inverted; /* "! cmd | cmd" */
 744#if ENABLE_HUSH_CASE
 745        smallint ctx_dsemicolon; /* ";;" seen */
 746#endif
 747        /* bitmask of FLAG_xxx, for figuring out valid reserved words */
 748        int old_flag;
 749        /* group we are enclosed in:
 750         * example: "if pipe1; pipe2; then pipe3; fi"
 751         * when we see "if" or "then", we malloc and copy current context,
 752         * and make ->stack point to it. then we parse pipeN.
 753         * when closing "then" / fi" / whatever is found,
 754         * we move list_head into ->stack->command->group,
 755         * copy ->stack into current context, and delete ->stack.
 756         * (parsing of { list } and ( list ) doesn't use this method)
 757         */
 758        struct parse_context *stack;
 759#endif
 760};
 761enum {
 762        MAYBE_ASSIGNMENT      = 0,
 763        DEFINITELY_ASSIGNMENT = 1,
 764        NOT_ASSIGNMENT        = 2,
 765        /* Not an assignment, but next word may be: "if v=xyz cmd;" */
 766        WORD_IS_KEYWORD       = 3,
 767};
 768
 769/* On program start, environ points to initial environment.
 770 * putenv adds new pointers into it, unsetenv removes them.
 771 * Neither of these (de)allocates the strings.
 772 * setenv allocates new strings in malloc space and does putenv,
 773 * and thus setenv is unusable (leaky) for shell's purposes */
 774#define setenv(...) setenv_is_leaky_dont_use()
 775struct variable {
 776        struct variable *next;
 777        char *varstr;        /* points to "name=" portion */
 778        int max_len;         /* if > 0, name is part of initial env; else name is malloced */
 779        uint16_t var_nest_level;
 780        smallint flg_export; /* putenv should be done on this var */
 781        smallint flg_read_only;
 782};
 783
 784enum {
 785        BC_BREAK = 1,
 786        BC_CONTINUE = 2,
 787};
 788
 789#if ENABLE_HUSH_FUNCTIONS
 790struct function {
 791        struct function *next;
 792        char *name;
 793        struct command *parent_cmd;
 794        struct pipe *body;
 795# if !BB_MMU
 796        char *body_as_string;
 797# endif
 798};
 799#endif
 800
 801
 802/* set -/+o OPT support. (TODO: make it optional)
 803 * bash supports the following opts:
 804 * allexport       off
 805 * braceexpand     on
 806 * emacs           on
 807 * errexit         off
 808 * errtrace        off
 809 * functrace       off
 810 * hashall         on
 811 * histexpand      off
 812 * history         on
 813 * ignoreeof       off
 814 * interactive-comments    on
 815 * keyword         off
 816 * monitor         on
 817 * noclobber       off
 818 * noexec          off
 819 * noglob          off
 820 * nolog           off
 821 * notify          off
 822 * nounset         off
 823 * onecmd          off
 824 * physical        off
 825 * pipefail        off
 826 * posix           off
 827 * privileged      off
 828 * verbose         off
 829 * vi              off
 830 * xtrace          off
 831 */
 832static const char o_opt_strings[] ALIGN1 =
 833        "pipefail\0"
 834        "noexec\0"
 835        "errexit\0"
 836#if ENABLE_HUSH_MODE_X
 837        "xtrace\0"
 838#endif
 839        ;
 840enum {
 841        OPT_O_PIPEFAIL,
 842        OPT_O_NOEXEC,
 843        OPT_O_ERREXIT,
 844#if ENABLE_HUSH_MODE_X
 845        OPT_O_XTRACE,
 846#endif
 847        NUM_OPT_O
 848};
 849
 850/* "Globals" within this file */
 851/* Sorted roughly by size (smaller offsets == smaller code) */
 852struct globals {
 853        /* interactive_fd != 0 means we are an interactive shell.
 854         * If we are, then saved_tty_pgrp can also be != 0, meaning
 855         * that controlling tty is available. With saved_tty_pgrp == 0,
 856         * job control still works, but terminal signals
 857         * (^C, ^Z, ^Y, ^\) won't work at all, and background
 858         * process groups can only be created with "cmd &".
 859         * With saved_tty_pgrp != 0, hush will use tcsetpgrp()
 860         * to give tty to the foreground process group,
 861         * and will take it back when the group is stopped (^Z)
 862         * or killed (^C).
 863         */
 864#if ENABLE_HUSH_INTERACTIVE
 865        /* 'interactive_fd' is a fd# open to ctty, if we have one
 866         * _AND_ if we decided to act interactively */
 867        int interactive_fd;
 868        IF_NOT_FEATURE_EDITING_FANCY_PROMPT(char *PS1;)
 869# define G_interactive_fd (G.interactive_fd)
 870#else
 871# define G_interactive_fd 0
 872#endif
 873#if ENABLE_FEATURE_EDITING
 874        line_input_t *line_input_state;
 875#endif
 876        pid_t root_pid;
 877        pid_t root_ppid;
 878        pid_t last_bg_pid;
 879#if ENABLE_HUSH_RANDOM_SUPPORT
 880        random_t random_gen;
 881#endif
 882#if ENABLE_HUSH_JOB
 883        int run_list_level;
 884        unsigned last_jobid;
 885        pid_t saved_tty_pgrp;
 886        struct pipe *job_list;
 887# define G_saved_tty_pgrp (G.saved_tty_pgrp)
 888#else
 889# define G_saved_tty_pgrp 0
 890#endif
 891        /* How deeply are we in context where "set -e" is ignored */
 892        int errexit_depth;
 893        /* "set -e" rules (do we follow them correctly?):
 894         * Exit if pipe, list, or compound command exits with a non-zero status.
 895         * Shell does not exit if failed command is part of condition in
 896         * if/while, part of && or || list except the last command, any command
 897         * in a pipe but the last, or if the command's return value is being
 898         * inverted with !. If a compound command other than a subshell returns a
 899         * non-zero status because a command failed while -e was being ignored, the
 900         * shell does not exit. A trap on ERR, if set, is executed before the shell
 901         * exits [ERR is a bashism].
 902         *
 903         * If a compound command or function executes in a context where -e is
 904         * ignored, none of the commands executed within are affected by the -e
 905         * setting. If a compound command or function sets -e while executing in a
 906         * context where -e is ignored, that setting does not have any effect until
 907         * the compound command or the command containing the function call completes.
 908         */
 909
 910        char o_opt[NUM_OPT_O];
 911#if ENABLE_HUSH_MODE_X
 912# define G_x_mode (G.o_opt[OPT_O_XTRACE])
 913#else
 914# define G_x_mode 0
 915#endif
 916        char opt_s;
 917        char opt_c;
 918#if ENABLE_HUSH_INTERACTIVE
 919        smallint promptmode; /* 0: PS1, 1: PS2 */
 920#endif
 921        smallint flag_SIGINT;
 922#if ENABLE_HUSH_LOOPS
 923        smallint flag_break_continue;
 924#endif
 925#if ENABLE_HUSH_FUNCTIONS
 926        /* 0: outside of a function (or sourced file)
 927         * -1: inside of a function, ok to use return builtin
 928         * 1: return is invoked, skip all till end of func
 929         */
 930        smallint flag_return_in_progress;
 931# define G_flag_return_in_progress (G.flag_return_in_progress)
 932#else
 933# define G_flag_return_in_progress 0
 934#endif
 935        smallint exiting; /* used to prevent EXIT trap recursion */
 936        /* These support $? */
 937        smalluint last_exitcode;
 938        smalluint expand_exitcode;
 939        smalluint last_bg_pid_exitcode;
 940#if ENABLE_HUSH_SET
 941        /* are global_argv and global_argv[1..n] malloced? (note: not [0]) */
 942        smalluint global_args_malloced;
 943# define G_global_args_malloced (G.global_args_malloced)
 944#else
 945# define G_global_args_malloced 0
 946#endif
 947#if ENABLE_HUSH_BASH_COMPAT
 948        int dead_job_exitcode; /* for "wait -n" */
 949#endif
 950        /* how many non-NULL argv's we have. NB: $# + 1 */
 951        int global_argc;
 952        char **global_argv;
 953#if !BB_MMU
 954        char *argv0_for_re_execing;
 955#endif
 956#if ENABLE_HUSH_LOOPS
 957        unsigned depth_break_continue;
 958        unsigned depth_of_loop;
 959#endif
 960#if ENABLE_HUSH_GETOPTS
 961        unsigned getopt_count;
 962#endif
 963        const char *ifs;
 964        char *ifs_whitespace; /* = G.ifs or malloced */
 965        const char *cwd;
 966        struct variable *top_var;
 967        char **expanded_assignments;
 968        struct variable **shadowed_vars_pp;
 969        unsigned var_nest_level;
 970#if ENABLE_HUSH_FUNCTIONS
 971# if ENABLE_HUSH_LOCAL
 972        unsigned func_nest_level; /* solely to prevent "local v" in non-functions */
 973# endif
 974        struct function *top_func;
 975#endif
 976        /* Signal and trap handling */
 977#if ENABLE_HUSH_FAST
 978        unsigned count_SIGCHLD;
 979        unsigned handled_SIGCHLD;
 980        smallint we_have_children;
 981#endif
 982#if ENABLE_HUSH_LINENO_VAR
 983        unsigned parse_lineno;
 984        unsigned execute_lineno;
 985#endif
 986        HFILE *HFILE_list;
 987        HFILE *HFILE_stdin;
 988        /* Which signals have non-DFL handler (even with no traps set)?
 989         * Set at the start to:
 990         * (SIGQUIT + maybe SPECIAL_INTERACTIVE_SIGS + maybe SPECIAL_JOBSTOP_SIGS)
 991         * SPECIAL_INTERACTIVE_SIGS are cleared after fork.
 992         * The rest is cleared right before execv syscalls.
 993         * Other than these two times, never modified.
 994         */
 995        unsigned special_sig_mask;
 996#if ENABLE_HUSH_JOB
 997        unsigned fatal_sig_mask;
 998# define G_fatal_sig_mask (G.fatal_sig_mask)
 999#else
1000# define G_fatal_sig_mask 0
1001#endif
1002#if ENABLE_HUSH_TRAP
1003        int pre_trap_exitcode;
1004# if ENABLE_HUSH_FUNCTIONS
1005        int return_exitcode;
1006# endif
1007        char **traps; /* char *traps[NSIG] */
1008# define G_traps G.traps
1009#else
1010# define G_traps ((char**)NULL)
1011#endif
1012        sigset_t pending_set;
1013#if ENABLE_HUSH_MEMLEAK
1014        unsigned long memleak_value;
1015#endif
1016#if ENABLE_HUSH_MODE_X
1017        unsigned x_mode_depth;
1018        /* "set -x" output should not be redirectable with subsequent 2>FILE.
1019         * We dup fd#2 to x_mode_fd when "set -x" is executed, and use it
1020         * for all subsequent output.
1021         */
1022        int x_mode_fd;
1023        o_string x_mode_buf;
1024#endif
1025#if HUSH_DEBUG >= 2
1026        int debug_indent;
1027#endif
1028        struct sigaction sa;
1029        char optstring_buf[sizeof("eixcs")];
1030#if BASH_EPOCH_VARS
1031        char epoch_buf[sizeof("%llu.nnnnnn") + sizeof(long long)*3];
1032#endif
1033#if ENABLE_FEATURE_EDITING
1034        char user_input_buf[CONFIG_FEATURE_EDITING_MAX_LEN];
1035#endif
1036};
1037#define G (*ptr_to_globals)
1038/* Not #defining name to G.name - this quickly gets unwieldy
1039 * (too many defines). Also, I actually prefer to see when a variable
1040 * is global, thus "G." prefix is a useful hint */
1041#define INIT_G() do { \
1042        SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
1043        /* memset(&G.sa, 0, sizeof(G.sa)); */  \
1044        sigfillset(&G.sa.sa_mask); \
1045        G.sa.sa_flags = SA_RESTART; \
1046} while (0)
1047
1048
1049/* Function prototypes for builtins */
1050static int builtin_cd(char **argv) FAST_FUNC;
1051#if ENABLE_HUSH_ECHO
1052static int builtin_echo(char **argv) FAST_FUNC;
1053#endif
1054static int builtin_eval(char **argv) FAST_FUNC;
1055static int builtin_exec(char **argv) FAST_FUNC;
1056static int builtin_exit(char **argv) FAST_FUNC;
1057#if ENABLE_HUSH_EXPORT
1058static int builtin_export(char **argv) FAST_FUNC;
1059#endif
1060#if ENABLE_HUSH_READONLY
1061static int builtin_readonly(char **argv) FAST_FUNC;
1062#endif
1063#if ENABLE_HUSH_JOB
1064static int builtin_fg_bg(char **argv) FAST_FUNC;
1065static int builtin_jobs(char **argv) FAST_FUNC;
1066#endif
1067#if ENABLE_HUSH_GETOPTS
1068static int builtin_getopts(char **argv) FAST_FUNC;
1069#endif
1070#if ENABLE_HUSH_HELP
1071static int builtin_help(char **argv) FAST_FUNC;
1072#endif
1073#if MAX_HISTORY && ENABLE_FEATURE_EDITING
1074static int builtin_history(char **argv) FAST_FUNC;
1075#endif
1076#if ENABLE_HUSH_LOCAL
1077static int builtin_local(char **argv) FAST_FUNC;
1078#endif
1079#if ENABLE_HUSH_MEMLEAK
1080static int builtin_memleak(char **argv) FAST_FUNC;
1081#endif
1082#if ENABLE_HUSH_PRINTF
1083static int builtin_printf(char **argv) FAST_FUNC;
1084#endif
1085static int builtin_pwd(char **argv) FAST_FUNC;
1086#if ENABLE_HUSH_READ
1087static int builtin_read(char **argv) FAST_FUNC;
1088#endif
1089#if ENABLE_HUSH_SET
1090static int builtin_set(char **argv) FAST_FUNC;
1091#endif
1092static int builtin_shift(char **argv) FAST_FUNC;
1093static int builtin_source(char **argv) FAST_FUNC;
1094#if ENABLE_HUSH_TEST || BASH_TEST2
1095static int builtin_test(char **argv) FAST_FUNC;
1096#endif
1097#if ENABLE_HUSH_TRAP
1098static int builtin_trap(char **argv) FAST_FUNC;
1099#endif
1100#if ENABLE_HUSH_TYPE
1101static int builtin_type(char **argv) FAST_FUNC;
1102#endif
1103#if ENABLE_HUSH_TIMES
1104static int builtin_times(char **argv) FAST_FUNC;
1105#endif
1106static int builtin_true(char **argv) FAST_FUNC;
1107#if ENABLE_HUSH_UMASK
1108static int builtin_umask(char **argv) FAST_FUNC;
1109#endif
1110#if ENABLE_HUSH_UNSET
1111static int builtin_unset(char **argv) FAST_FUNC;
1112#endif
1113#if ENABLE_HUSH_KILL
1114static int builtin_kill(char **argv) FAST_FUNC;
1115#endif
1116#if ENABLE_HUSH_WAIT
1117static int builtin_wait(char **argv) FAST_FUNC;
1118#endif
1119#if ENABLE_HUSH_LOOPS
1120static int builtin_break(char **argv) FAST_FUNC;
1121static int builtin_continue(char **argv) FAST_FUNC;
1122#endif
1123#if ENABLE_HUSH_FUNCTIONS
1124static int builtin_return(char **argv) FAST_FUNC;
1125#endif
1126
1127/* Table of built-in functions.  They can be forked or not, depending on
1128 * context: within pipes, they fork.  As simple commands, they do not.
1129 * When used in non-forking context, they can change global variables
1130 * in the parent shell process.  If forked, of course they cannot.
1131 * For example, 'unset foo | whatever' will parse and run, but foo will
1132 * still be set at the end. */
1133struct built_in_command {
1134        const char *b_cmd;
1135        int (*b_function)(char **argv) FAST_FUNC;
1136#if ENABLE_HUSH_HELP
1137        const char *b_descr;
1138# define BLTIN(cmd, func, help) { cmd, func, help }
1139#else
1140# define BLTIN(cmd, func, help) { cmd, func }
1141#endif
1142};
1143
1144static const struct built_in_command bltins1[] ALIGN_PTR = {
1145        BLTIN("."        , builtin_source  , "Run commands in file"),
1146        BLTIN(":"        , builtin_true    , NULL),
1147#if ENABLE_HUSH_JOB
1148        BLTIN("bg"       , builtin_fg_bg   , "Resume job in background"),
1149#endif
1150#if ENABLE_HUSH_LOOPS
1151        BLTIN("break"    , builtin_break   , "Exit loop"),
1152#endif
1153        BLTIN("cd"       , builtin_cd      , "Change directory"),
1154#if ENABLE_HUSH_LOOPS
1155        BLTIN("continue" , builtin_continue, "Start new loop iteration"),
1156#endif
1157        BLTIN("eval"     , builtin_eval    , "Construct and run shell command"),
1158        BLTIN("exec"     , builtin_exec    , "Execute command, don't return to shell"),
1159        BLTIN("exit"     , builtin_exit    , NULL),
1160#if ENABLE_HUSH_EXPORT
1161        BLTIN("export"   , builtin_export  , "Set environment variables"),
1162#endif
1163#if ENABLE_HUSH_JOB
1164        BLTIN("fg"       , builtin_fg_bg   , "Bring job to foreground"),
1165#endif
1166#if ENABLE_HUSH_GETOPTS
1167        BLTIN("getopts"  , builtin_getopts , NULL),
1168#endif
1169#if ENABLE_HUSH_HELP
1170        BLTIN("help"     , builtin_help    , NULL),
1171#endif
1172#if MAX_HISTORY && ENABLE_FEATURE_EDITING
1173        BLTIN("history"  , builtin_history , "Show history"),
1174#endif
1175#if ENABLE_HUSH_JOB
1176        BLTIN("jobs"     , builtin_jobs    , "List jobs"),
1177#endif
1178#if ENABLE_HUSH_KILL
1179        BLTIN("kill"     , builtin_kill    , "Send signals to processes"),
1180#endif
1181#if ENABLE_HUSH_LOCAL
1182        BLTIN("local"    , builtin_local   , "Set local variables"),
1183#endif
1184#if ENABLE_HUSH_MEMLEAK
1185        BLTIN("memleak"  , builtin_memleak , NULL),
1186#endif
1187#if ENABLE_HUSH_READ
1188        BLTIN("read"     , builtin_read    , "Input into variable"),
1189#endif
1190#if ENABLE_HUSH_READONLY
1191        BLTIN("readonly" , builtin_readonly, "Make variables read-only"),
1192#endif
1193#if ENABLE_HUSH_FUNCTIONS
1194        BLTIN("return"   , builtin_return  , "Return from function"),
1195#endif
1196#if ENABLE_HUSH_SET
1197        BLTIN("set"      , builtin_set     , "Set positional parameters"),
1198#endif
1199        BLTIN("shift"    , builtin_shift   , "Shift positional parameters"),
1200#if BASH_SOURCE
1201        BLTIN("source"   , builtin_source  , NULL),
1202#endif
1203#if ENABLE_HUSH_TIMES
1204        BLTIN("times"    , builtin_times   , NULL),
1205#endif
1206#if ENABLE_HUSH_TRAP
1207        BLTIN("trap"     , builtin_trap    , "Trap signals"),
1208#endif
1209        BLTIN("true"     , builtin_true    , NULL),
1210#if ENABLE_HUSH_TYPE
1211        BLTIN("type"     , builtin_type    , "Show command type"),
1212#endif
1213#if ENABLE_HUSH_ULIMIT
1214        BLTIN("ulimit"   , shell_builtin_ulimit, "Control resource limits"),
1215#endif
1216#if ENABLE_HUSH_UMASK
1217        BLTIN("umask"    , builtin_umask   , "Set file creation mask"),
1218#endif
1219#if ENABLE_HUSH_UNSET
1220        BLTIN("unset"    , builtin_unset   , "Unset variables"),
1221#endif
1222#if ENABLE_HUSH_WAIT
1223        BLTIN("wait"     , builtin_wait    , "Wait for process to finish"),
1224#endif
1225};
1226/* These builtins won't be used if we are on NOMMU and need to re-exec
1227 * (it's cheaper to run an external program in this case):
1228 */
1229static const struct built_in_command bltins2[] ALIGN_PTR = {
1230#if ENABLE_HUSH_TEST
1231        BLTIN("["        , builtin_test    , NULL),
1232#endif
1233#if BASH_TEST2
1234        BLTIN("[["       , builtin_test    , NULL),
1235#endif
1236#if ENABLE_HUSH_ECHO
1237        BLTIN("echo"     , builtin_echo    , NULL),
1238#endif
1239#if ENABLE_HUSH_PRINTF
1240        BLTIN("printf"   , builtin_printf  , NULL),
1241#endif
1242        BLTIN("pwd"      , builtin_pwd     , NULL),
1243#if ENABLE_HUSH_TEST
1244        BLTIN("test"     , builtin_test    , NULL),
1245#endif
1246};
1247
1248
1249/* Debug printouts.
1250 */
1251#if HUSH_DEBUG >= 2
1252/* prevent disasters with G.debug_indent < 0 */
1253# define indent() fdprintf(2, "%*s", (G.debug_indent * 2) & 0xff, "")
1254# define debug_enter() (G.debug_indent++)
1255# define debug_leave() (G.debug_indent--)
1256#else
1257# define indent()      ((void)0)
1258# define debug_enter() ((void)0)
1259# define debug_leave() ((void)0)
1260#endif
1261
1262#ifndef debug_printf
1263# define debug_printf(...) (indent(), fdprintf(2, __VA_ARGS__))
1264#endif
1265
1266#ifndef debug_printf_parse
1267# define debug_printf_parse(...) (indent(), fdprintf(2, __VA_ARGS__))
1268#endif
1269
1270#ifndef debug_printf_heredoc
1271# define debug_printf_heredoc(...) (indent(), fdprintf(2, __VA_ARGS__))
1272#endif
1273
1274#ifndef debug_printf_exec
1275#define debug_printf_exec(...) (indent(), fdprintf(2, __VA_ARGS__))
1276#endif
1277
1278#ifndef debug_printf_env
1279# define debug_printf_env(...) (indent(), fdprintf(2, __VA_ARGS__))
1280#endif
1281
1282#ifndef debug_printf_jobs
1283# define debug_printf_jobs(...) (indent(), fdprintf(2, __VA_ARGS__))
1284# define DEBUG_JOBS 1
1285#else
1286# define DEBUG_JOBS 0
1287#endif
1288
1289#ifndef debug_printf_expand
1290# define debug_printf_expand(...) (indent(), fdprintf(2, __VA_ARGS__))
1291# define DEBUG_EXPAND 1
1292#else
1293# define DEBUG_EXPAND 0
1294#endif
1295
1296#ifndef debug_printf_varexp
1297# define debug_printf_varexp(...) (indent(), fdprintf(2, __VA_ARGS__))
1298#endif
1299
1300#ifndef debug_printf_glob
1301# define debug_printf_glob(...) (indent(), fdprintf(2, __VA_ARGS__))
1302# define DEBUG_GLOB 1
1303#else
1304# define DEBUG_GLOB 0
1305#endif
1306
1307#ifndef debug_printf_redir
1308# define debug_printf_redir(...) (indent(), fdprintf(2, __VA_ARGS__))
1309#endif
1310
1311#ifndef debug_printf_list
1312# define debug_printf_list(...) (indent(), fdprintf(2, __VA_ARGS__))
1313#endif
1314
1315#ifndef debug_printf_subst
1316# define debug_printf_subst(...) (indent(), fdprintf(2, __VA_ARGS__))
1317#endif
1318
1319#ifndef debug_printf_prompt
1320# define debug_printf_prompt(...) (indent(), fdprintf(2, __VA_ARGS__))
1321#endif
1322
1323#ifndef debug_printf_clean
1324# define debug_printf_clean(...) (indent(), fdprintf(2, __VA_ARGS__))
1325# define DEBUG_CLEAN 1
1326#else
1327# define DEBUG_CLEAN 0
1328#endif
1329
1330#if DEBUG_EXPAND
1331static void debug_print_strings(const char *prefix, char **vv)
1332{
1333        indent();
1334        fdprintf(2, "%s:\n", prefix);
1335        while (*vv)
1336                fdprintf(2, " '%s'\n", *vv++);
1337}
1338#else
1339# define debug_print_strings(prefix, vv) ((void)0)
1340#endif
1341
1342
1343/* Leak hunting. Use hush_leaktool.sh for post-processing.
1344 */
1345#if LEAK_HUNTING
1346static void *xxmalloc(int lineno, size_t size)
1347{
1348        void *ptr = xmalloc((size + 0xff) & ~0xff);
1349        fdprintf(2, "line %d: malloc %p\n", lineno, ptr);
1350        return ptr;
1351}
1352static void *xxrealloc(int lineno, void *ptr, size_t size)
1353{
1354        ptr = xrealloc(ptr, (size + 0xff) & ~0xff);
1355        fdprintf(2, "line %d: realloc %p\n", lineno, ptr);
1356        return ptr;
1357}
1358static char *xxstrdup(int lineno, const char *str)
1359{
1360        char *ptr = xstrdup(str);
1361        fdprintf(2, "line %d: strdup %p\n", lineno, ptr);
1362        return ptr;
1363}
1364static void xxfree(void *ptr)
1365{
1366        fdprintf(2, "free %p\n", ptr);
1367        free(ptr);
1368}
1369# define xmalloc(s)     xxmalloc(__LINE__, s)
1370# define xrealloc(p, s) xxrealloc(__LINE__, p, s)
1371# define xstrdup(s)     xxstrdup(__LINE__, s)
1372# define free(p)        xxfree(p)
1373#endif
1374
1375
1376/* Syntax and runtime errors. They always abort scripts.
1377 * In interactive use they usually discard unparsed and/or unexecuted commands
1378 * and return to the prompt.
1379 * HUSH_DEBUG >= 2 prints line number in this file where it was detected.
1380 */
1381#if HUSH_DEBUG < 2
1382# define msg_and_die_if_script(lineno, ...)     msg_and_die_if_script(__VA_ARGS__)
1383# define syntax_error(lineno, msg)              syntax_error(msg)
1384# define syntax_error_at(lineno, msg)           syntax_error_at(msg)
1385# define syntax_error_unterm_ch(lineno, ch)     syntax_error_unterm_ch(ch)
1386# define syntax_error_unterm_str(lineno, s)     syntax_error_unterm_str(s)
1387# define syntax_error_unexpected_ch(lineno, ch) syntax_error_unexpected_ch(ch)
1388#endif
1389
1390static void die_if_script(void)
1391{
1392        if (!G_interactive_fd) {
1393                if (G.last_exitcode) /* sometines it's 2, not 1 (bash compat) */
1394                        xfunc_error_retval = G.last_exitcode;
1395                xfunc_die();
1396        }
1397}
1398
1399static void msg_and_die_if_script(unsigned lineno, const char *fmt, ...)
1400{
1401        va_list p;
1402
1403#if HUSH_DEBUG >= 2
1404        bb_error_msg("hush.c:%u", lineno);
1405#endif
1406        va_start(p, fmt);
1407        bb_verror_msg(fmt, p, NULL);
1408        va_end(p);
1409        die_if_script();
1410}
1411
1412static void syntax_error(unsigned lineno UNUSED_PARAM, const char *msg)
1413{
1414        if (msg)
1415                bb_error_msg("syntax error: %s", msg);
1416        else
1417                bb_simple_error_msg("syntax error");
1418        die_if_script();
1419}
1420
1421static void syntax_error_at(unsigned lineno UNUSED_PARAM, const char *msg)
1422{
1423        bb_error_msg("syntax error at '%s'", msg);
1424        die_if_script();
1425}
1426
1427static void syntax_error_unterm_str(unsigned lineno UNUSED_PARAM, const char *s)
1428{
1429        bb_error_msg("syntax error: unterminated %s", s);
1430//? source4.tests fails: in bash, echo ${^} in script does not terminate the script
1431//      die_if_script();
1432}
1433
1434static void syntax_error_unterm_ch(unsigned lineno, char ch)
1435{
1436        char msg[2] = { ch, '\0' };
1437        syntax_error_unterm_str(lineno, msg);
1438}
1439
1440static void syntax_error_unexpected_ch(unsigned lineno UNUSED_PARAM, int ch)
1441{
1442        char msg[2];
1443        msg[0] = ch;
1444        msg[1] = '\0';
1445#if HUSH_DEBUG >= 2
1446        bb_error_msg("hush.c:%u", lineno);
1447#endif
1448        bb_error_msg("syntax error: unexpected %s", ch == EOF ? "EOF" : msg);
1449        die_if_script();
1450}
1451
1452#if HUSH_DEBUG < 2
1453# undef msg_and_die_if_script
1454# undef syntax_error
1455# undef syntax_error_at
1456# undef syntax_error_unterm_ch
1457# undef syntax_error_unterm_str
1458# undef syntax_error_unexpected_ch
1459#else
1460# define msg_and_die_if_script(...)     msg_and_die_if_script(__LINE__, __VA_ARGS__)
1461# define syntax_error(msg)              syntax_error(__LINE__, msg)
1462# define syntax_error_at(msg)           syntax_error_at(__LINE__, msg)
1463# define syntax_error_unterm_ch(ch)     syntax_error_unterm_ch(__LINE__, ch)
1464# define syntax_error_unterm_str(s)     syntax_error_unterm_str(__LINE__, s)
1465# define syntax_error_unexpected_ch(ch) syntax_error_unexpected_ch(__LINE__, ch)
1466#endif
1467
1468
1469/* Utility functions
1470 */
1471/* Replace each \x with x in place, return ptr past NUL. */
1472static char *unbackslash(char *src)
1473{
1474        char *dst = src = strchrnul(src, '\\');
1475        while (1) {
1476                if (*src == '\\') {
1477                        src++;
1478                        if (*src != '\0') {
1479                                /* \x -> x */
1480                                *dst++ = *src++;
1481                                continue;
1482                        }
1483                        /* else: "\<nul>". Do not delete this backslash.
1484                         * Testcase: eval 'echo ok\'
1485                         */
1486                        *dst++ = '\\';
1487                        /* fallthrough */
1488                }
1489                if ((*dst++ = *src++) == '\0')
1490                        break;
1491        }
1492        return dst;
1493}
1494
1495static char **add_strings_to_strings(char **strings, char **add, int need_to_dup)
1496{
1497        int i;
1498        unsigned count1;
1499        unsigned count2;
1500        char **v;
1501
1502        v = strings;
1503        count1 = 0;
1504        if (v) {
1505                while (*v) {
1506                        count1++;
1507                        v++;
1508                }
1509        }
1510        count2 = 0;
1511        v = add;
1512        while (*v) {
1513                count2++;
1514                v++;
1515        }
1516        v = xrealloc(strings, (count1 + count2 + 1) * sizeof(char*));
1517        v[count1 + count2] = NULL;
1518        i = count2;
1519        while (--i >= 0)
1520                v[count1 + i] = (need_to_dup ? xstrdup(add[i]) : add[i]);
1521        return v;
1522}
1523#if LEAK_HUNTING
1524static char **xx_add_strings_to_strings(int lineno, char **strings, char **add, int need_to_dup)
1525{
1526        char **ptr = add_strings_to_strings(strings, add, need_to_dup);
1527        fdprintf(2, "line %d: add_strings_to_strings %p\n", lineno, ptr);
1528        return ptr;
1529}
1530#define add_strings_to_strings(strings, add, need_to_dup) \
1531        xx_add_strings_to_strings(__LINE__, strings, add, need_to_dup)
1532#endif
1533
1534/* Note: takes ownership of "add" ptr (it is not strdup'ed) */
1535static char **add_string_to_strings(char **strings, char *add)
1536{
1537        char *v[2];
1538        v[0] = add;
1539        v[1] = NULL;
1540        return add_strings_to_strings(strings, v, /*dup:*/ 0);
1541}
1542#if LEAK_HUNTING
1543static char **xx_add_string_to_strings(int lineno, char **strings, char *add)
1544{
1545        char **ptr = add_string_to_strings(strings, add);
1546        fdprintf(2, "line %d: add_string_to_strings %p\n", lineno, ptr);
1547        return ptr;
1548}
1549#define add_string_to_strings(strings, add) \
1550        xx_add_string_to_strings(__LINE__, strings, add)
1551#endif
1552
1553static void free_strings(char **strings)
1554{
1555        char **v;
1556
1557        if (!strings)
1558                return;
1559        v = strings;
1560        while (*v) {
1561                free(*v);
1562                v++;
1563        }
1564        free(strings);
1565}
1566
1567static int dup_CLOEXEC(int fd, int avoid_fd)
1568{
1569        int newfd;
1570 repeat:
1571        newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
1572        if (newfd >= 0) {
1573                if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
1574                        fcntl(newfd, F_SETFD, FD_CLOEXEC);
1575        } else { /* newfd < 0 */
1576                if (errno == EBUSY)
1577                        goto repeat;
1578                if (errno == EINTR)
1579                        goto repeat;
1580        }
1581        return newfd;
1582}
1583
1584static int xdup_CLOEXEC_and_close(int fd, int avoid_fd)
1585{
1586        int newfd;
1587 repeat:
1588        newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
1589        if (newfd < 0) {
1590                if (errno == EBUSY)
1591                        goto repeat;
1592                if (errno == EINTR)
1593                        goto repeat;
1594                /* fd was not open? */
1595                if (errno == EBADF)
1596                        return fd;
1597                xfunc_die();
1598        }
1599        if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
1600                fcntl(newfd, F_SETFD, FD_CLOEXEC);
1601        close(fd);
1602        return newfd;
1603}
1604
1605
1606/* Manipulating HFILEs */
1607static HFILE *hfopen(const char *name)
1608{
1609        HFILE *fp;
1610        int fd;
1611
1612        fd = STDIN_FILENO;
1613        if (name) {
1614                fd = open(name, O_RDONLY | O_CLOEXEC);
1615                if (fd < 0)
1616                        return NULL;
1617                if (O_CLOEXEC == 0) /* ancient libc */
1618                        close_on_exec_on(fd);
1619        }
1620
1621        fp = xmalloc(sizeof(*fp));
1622        if (name == NULL)
1623                G.HFILE_stdin = fp;
1624        fp->fd = fd;
1625        fp->cur = fp->end = fp->buf;
1626        fp->next_hfile = G.HFILE_list;
1627        G.HFILE_list = fp;
1628        return fp;
1629}
1630static void hfclose(HFILE *fp)
1631{
1632        HFILE **pp = &G.HFILE_list;
1633        while (*pp) {
1634                HFILE *cur = *pp;
1635                if (cur == fp) {
1636                        *pp = cur->next_hfile;
1637                        break;
1638                }
1639                pp = &cur->next_hfile;
1640        }
1641        if (fp->fd >= 0)
1642                close(fp->fd);
1643        free(fp);
1644}
1645static int refill_HFILE_and_getc(HFILE *fp)
1646{
1647        int n;
1648
1649        if (fp->fd < 0) {
1650                /* Already saw EOF */
1651                return EOF;
1652        }
1653#if ENABLE_HUSH_INTERACTIVE && !ENABLE_FEATURE_EDITING
1654        /* If user presses ^C, read() restarts after SIGINT (we use SA_RESTART).
1655         * IOW: ^C will not immediately stop line input.
1656         * But poll() is different: it does NOT restart after signals.
1657         */
1658        if (fp == G.HFILE_stdin) {
1659                struct pollfd pfd[1];
1660                pfd[0].fd = fp->fd;
1661                pfd[0].events = POLLIN;
1662                n = poll(pfd, 1, -1);
1663                if (n < 0
1664                 /*&& errno == EINTR - assumed true */
1665                 && sigismember(&G.pending_set, SIGINT)
1666                ) {
1667                        return '\0';
1668                }
1669        }
1670#else
1671/* if FEATURE_EDITING=y, we do not use this routine for interactive input */
1672#endif
1673        /* Try to buffer more input */
1674        n = safe_read(fp->fd, fp->buf, sizeof(fp->buf));
1675        if (n < 0) {
1676                bb_simple_perror_msg("read error");
1677                n = 0;
1678        }
1679        fp->cur = fp->buf;
1680        fp->end = fp->buf + n;
1681        if (n == 0) {
1682                /* EOF/error */
1683                close(fp->fd);
1684                fp->fd = -1;
1685                return EOF;
1686        }
1687        return (unsigned char)(*fp->cur++);
1688}
1689/* Inlined for common case of non-empty buffer.
1690 */
1691static ALWAYS_INLINE int hfgetc(HFILE *fp)
1692{
1693        if (fp->cur < fp->end)
1694                return (unsigned char)(*fp->cur++);
1695        /* Buffer empty */
1696        return refill_HFILE_and_getc(fp);
1697}
1698static int move_HFILEs_on_redirect(int fd, int avoid_fd)
1699{
1700        HFILE *fl = G.HFILE_list;
1701        while (fl) {
1702                if (fd == fl->fd) {
1703                        /* We use it only on script files, they are all CLOEXEC */
1704                        fl->fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
1705                        debug_printf_redir("redirect_fd %d: matches a script fd, moving it to %d\n", fd, fl->fd);
1706                        return 1; /* "found and moved" */
1707                }
1708                fl = fl->next_hfile;
1709        }
1710#if ENABLE_HUSH_MODE_X
1711        if (G.x_mode_fd > 0 && fd == G.x_mode_fd) {
1712                G.x_mode_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
1713                return 1; /* "found and moved" */
1714        }
1715#endif
1716        return 0; /* "not in the list" */
1717}
1718#if ENABLE_FEATURE_SH_STANDALONE && BB_MMU
1719static void close_all_HFILE_list(void)
1720{
1721        HFILE *fl = G.HFILE_list;
1722        while (fl) {
1723                /* hfclose would also free HFILE object.
1724                 * It is disastrous if we share memory with a vforked parent.
1725                 * I'm not sure we never come here after vfork.
1726                 * Therefore just close fd, nothing more.
1727                 *
1728                 * ">" instead of ">=": we don't close fd#0,
1729                 * interactive shell uses hfopen(NULL) as stdin input
1730                 * which has fl->fd == 0, but fd#0 gets redirected in pipes.
1731                 * If we'd close it here, then e.g. interactive "set | sort"
1732                 * with NOFORKed sort, would have sort's input fd closed.
1733                 */
1734                if (fl->fd > 0)
1735                        /*hfclose(fl); - unsafe */
1736                        close(fl->fd);
1737                fl = fl->next_hfile;
1738        }
1739}
1740#endif
1741static int fd_in_HFILEs(int fd)
1742{
1743        HFILE *fl = G.HFILE_list;
1744        while (fl) {
1745                if (fl->fd == fd)
1746                        return 1;
1747                fl = fl->next_hfile;
1748        }
1749        return 0;
1750}
1751
1752
1753/* Helpers for setting new $n and restoring them back
1754 */
1755typedef struct save_arg_t {
1756        char *sv_argv0;
1757        char **sv_g_argv;
1758        int sv_g_argc;
1759        IF_HUSH_SET(smallint sv_g_malloced;)
1760} save_arg_t;
1761
1762static void save_and_replace_G_args(save_arg_t *sv, char **argv)
1763{
1764        sv->sv_argv0 = argv[0];
1765        sv->sv_g_argv = G.global_argv;
1766        sv->sv_g_argc = G.global_argc;
1767        IF_HUSH_SET(sv->sv_g_malloced = G.global_args_malloced;)
1768
1769        argv[0] = G.global_argv[0]; /* retain $0 */
1770        G.global_argv = argv;
1771        IF_HUSH_SET(G.global_args_malloced = 0;)
1772
1773        G.global_argc = 1 + string_array_len(argv + 1);
1774}
1775
1776static void restore_G_args(save_arg_t *sv, char **argv)
1777{
1778#if ENABLE_HUSH_SET
1779        if (G.global_args_malloced) {
1780                /* someone ran "set -- arg1 arg2 ...", undo */
1781                char **pp = G.global_argv;
1782                while (*++pp) /* note: does not free $0 */
1783                        free(*pp);
1784                free(G.global_argv);
1785        }
1786#endif
1787        argv[0] = sv->sv_argv0;
1788        G.global_argv = sv->sv_g_argv;
1789        G.global_argc = sv->sv_g_argc;
1790        IF_HUSH_SET(G.global_args_malloced = sv->sv_g_malloced;)
1791}
1792
1793
1794/* Basic theory of signal handling in shell
1795 * ========================================
1796 * This does not describe what hush does, rather, it is current understanding
1797 * what it _should_ do. If it doesn't, it's a bug.
1798 * http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#trap
1799 *
1800 * Signals are handled only after each pipe ("cmd | cmd | cmd" thing)
1801 * is finished or backgrounded. It is the same in interactive and
1802 * non-interactive shells, and is the same regardless of whether
1803 * a user trap handler is installed or a shell special one is in effect.
1804 * ^C or ^Z from keyboard seems to execute "at once" because it usually
1805 * backgrounds (i.e. stops) or kills all members of currently running
1806 * pipe.
1807 *
1808 * Wait builtin is interruptible by signals for which user trap is set
1809 * or by SIGINT in interactive shell.
1810 *
1811 * Trap handlers will execute even within trap handlers. (right?)
1812 *
1813 * User trap handlers are forgotten when subshell ("(cmd)") is entered,
1814 * except for handlers set to '' (empty string).
1815 *
1816 * If job control is off, backgrounded commands ("cmd &")
1817 * have SIGINT, SIGQUIT set to SIG_IGN.
1818 *
1819 * Commands which are run in command substitution ("`cmd`")
1820 * have SIGTTIN, SIGTTOU, SIGTSTP set to SIG_IGN.
1821 *
1822 * Ordinary commands have signals set to SIG_IGN/DFL as inherited
1823 * by the shell from its parent.
1824 *
1825 * Signals which differ from SIG_DFL action
1826 * (note: child (i.e., [v]forked) shell is not an interactive shell):
1827 *
1828 * SIGQUIT: ignore
1829 * SIGTERM (interactive): ignore
1830 * SIGHUP (interactive):
1831 *    send SIGCONT to stopped jobs, send SIGHUP to all jobs and exit
1832 * SIGTTIN, SIGTTOU, SIGTSTP (if job control is on): ignore
1833 *    Note that ^Z is handled not by trapping SIGTSTP, but by seeing
1834 *    that all pipe members are stopped. Try this in bash:
1835 *    while :; do :; done - ^Z does not background it
1836 *    (while :; do :; done) - ^Z backgrounds it
1837 * SIGINT (interactive): wait for last pipe, ignore the rest
1838 *    of the command line, show prompt. NB: ^C does not send SIGINT
1839 *    to interactive shell while shell is waiting for a pipe,
1840 *    since shell is bg'ed (is not in foreground process group).
1841 *    Example 1: this waits 5 sec, but does not execute ls:
1842 *    "echo $$; sleep 5; ls -l" + "kill -INT <pid>"
1843 *    Example 2: this does not wait and does not execute ls:
1844 *    "echo $$; sleep 5 & wait; ls -l" + "kill -INT <pid>"
1845 *    Example 3: this does not wait 5 sec, but executes ls:
1846 *    "sleep 5; ls -l" + press ^C
1847 *    Example 4: this does not wait and does not execute ls:
1848 *    "sleep 5 & wait; ls -l" + press ^C
1849 *
1850 * (What happens to signals which are IGN on shell start?)
1851 * (What happens with signal mask on shell start?)
1852 *
1853 * Old implementation
1854 * ==================
1855 * We use in-kernel pending signal mask to determine which signals were sent.
1856 * We block all signals which we don't want to take action immediately,
1857 * i.e. we block all signals which need to have special handling as described
1858 * above, and all signals which have traps set.
1859 * After each pipe execution, we extract any pending signals via sigtimedwait()
1860 * and act on them.
1861 *
1862 * unsigned special_sig_mask: a mask of such "special" signals
1863 * sigset_t blocked_set:  current blocked signal set
1864 *
1865 * "trap - SIGxxx":
1866 *    clear bit in blocked_set unless it is also in special_sig_mask
1867 * "trap 'cmd' SIGxxx":
1868 *    set bit in blocked_set (even if 'cmd' is '')
1869 * after [v]fork, if we plan to be a shell:
1870 *    unblock signals with special interactive handling
1871 *    (child shell is not interactive),
1872 *    unset all traps except '' (note: regardless of child shell's type - {}, (), etc)
1873 * after [v]fork, if we plan to exec:
1874 *    POSIX says fork clears pending signal mask in child - no need to clear it.
1875 *    Restore blocked signal set to one inherited by shell just prior to exec.
1876 *
1877 * Note: as a result, we do not use signal handlers much. The only uses
1878 * are to count SIGCHLDs
1879 * and to restore tty pgrp on signal-induced exit.
1880 *
1881 * Note 2 (compat):
1882 * Standard says "When a subshell is entered, traps that are not being ignored
1883 * are set to the default actions". bash interprets it so that traps which
1884 * are set to '' (ignore) are NOT reset to defaults. We do the same.
1885 *
1886 * Problem: the above approach makes it unwieldy to catch signals while
1887 * we are in read builtin, or while we read commands from stdin:
1888 * masked signals are not visible!
1889 *
1890 * New implementation
1891 * ==================
1892 * We record each signal we are interested in by installing signal handler
1893 * for them - a bit like emulating kernel pending signal mask in userspace.
1894 * We are interested in: signals which need to have special handling
1895 * as described above, and all signals which have traps set.
1896 * Signals are recorded in pending_set.
1897 * After each pipe execution, we extract any pending signals
1898 * and act on them.
1899 *
1900 * unsigned special_sig_mask: a mask of shell-special signals.
1901 * unsigned fatal_sig_mask: a mask of signals on which we restore tty pgrp.
1902 * char *traps[sig] if trap for sig is set (even if it's '').
1903 * sigset_t pending_set: set of sigs we received.
1904 *
1905 * "trap - SIGxxx":
1906 *    if sig is in special_sig_mask, set handler back to:
1907 *        record_pending_signo, or to IGN if it's a tty stop signal
1908 *    if sig is in fatal_sig_mask, set handler back to sigexit.
1909 *    else: set handler back to SIG_DFL
1910 * "trap 'cmd' SIGxxx":
1911 *    set handler to record_pending_signo.
1912 * "trap '' SIGxxx":
1913 *    set handler to SIG_IGN.
1914 * after [v]fork, if we plan to be a shell:
1915 *    set signals with special interactive handling to SIG_DFL
1916 *    (because child shell is not interactive),
1917 *    unset all traps except '' (note: regardless of child shell's type - {}, (), etc)
1918 * after [v]fork, if we plan to exec:
1919 *    POSIX says fork clears pending signal mask in child - no need to clear it.
1920 *
1921 * To make wait builtin interruptible, we handle SIGCHLD as special signal,
1922 * otherwise (if we leave it SIG_DFL) sigsuspend in wait builtin will not wake up on it.
1923 *
1924 * Note (compat):
1925 * Standard says "When a subshell is entered, traps that are not being ignored
1926 * are set to the default actions". bash interprets it so that traps which
1927 * are set to '' (ignore) are NOT reset to defaults. We do the same.
1928 */
1929enum {
1930        SPECIAL_INTERACTIVE_SIGS = 0
1931                | (1 << SIGTERM)
1932                | (1 << SIGINT)
1933                | (1 << SIGHUP)
1934                ,
1935        SPECIAL_JOBSTOP_SIGS = 0
1936#if ENABLE_HUSH_JOB
1937                | (1 << SIGTTIN)
1938                | (1 << SIGTTOU)
1939                | (1 << SIGTSTP)
1940#endif
1941                ,
1942};
1943
1944static void record_pending_signo(int sig)
1945{
1946        sigaddset(&G.pending_set, sig);
1947#if ENABLE_HUSH_FAST
1948        if (sig == SIGCHLD) {
1949                G.count_SIGCHLD++;
1950//bb_error_msg("[%d] SIGCHLD_handler: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
1951        }
1952#endif
1953}
1954
1955static sighandler_t install_sighandler(int sig, sighandler_t handler)
1956{
1957        struct sigaction old_sa;
1958
1959        /* We could use signal() to install handlers... almost:
1960         * except that we need to mask ALL signals while handlers run.
1961         * I saw signal nesting in strace, race window isn't small.
1962         * SA_RESTART is also needed, but in Linux, signal()
1963         * sets SA_RESTART too.
1964         */
1965        /* memset(&G.sa, 0, sizeof(G.sa)); - already done */
1966        /* sigfillset(&G.sa.sa_mask);      - already done */
1967        /* G.sa.sa_flags = SA_RESTART;     - already done */
1968        G.sa.sa_handler = handler;
1969        sigaction(sig, &G.sa, &old_sa);
1970        return old_sa.sa_handler;
1971}
1972
1973static void hush_exit(int exitcode) NORETURN;
1974
1975static void restore_ttypgrp_and__exit(void) NORETURN;
1976static void restore_ttypgrp_and__exit(void)
1977{
1978        /* xfunc has failed! die die die */
1979        /* no EXIT traps, this is an escape hatch! */
1980        G.exiting = 1;
1981        hush_exit(xfunc_error_retval);
1982}
1983
1984#if ENABLE_HUSH_JOB
1985
1986/* Needed only on some libc:
1987 * It was observed that on exit(), fgetc'ed buffered data
1988 * gets "unwound" via lseek(fd, -NUM, SEEK_CUR).
1989 * With the net effect that even after fork(), not vfork(),
1990 * exit() in NOEXECed applet in "sh SCRIPT":
1991 *      noexec_applet_here
1992 *      echo END_OF_SCRIPT
1993 * lseeks fd in input FILE object from EOF to "e" in "echo END_OF_SCRIPT".
1994 * This makes "echo END_OF_SCRIPT" executed twice.
1995 * Similar problems can be seen with msg_and_die_if_script() -> xfunc_die()
1996 * and in `cmd` handling.
1997 * If set as die_func(), this makes xfunc_die() exit via _exit(), not exit():
1998 */
1999static void fflush_and__exit(void) NORETURN;
2000static void fflush_and__exit(void)
2001{
2002        fflush_all();
2003        _exit(xfunc_error_retval);
2004}
2005
2006/* After [v]fork, in child: do not restore tty pgrp on xfunc death */
2007# define disable_restore_tty_pgrp_on_exit() (die_func = fflush_and__exit)
2008/* After [v]fork, in parent: restore tty pgrp on xfunc death */
2009# define enable_restore_tty_pgrp_on_exit()  (die_func = restore_ttypgrp_and__exit)
2010
2011/* Restores tty foreground process group, and exits.
2012 * May be called as signal handler for fatal signal
2013 * (will resend signal to itself, producing correct exit state)
2014 * or called directly with -EXITCODE.
2015 * We also call it if xfunc is exiting.
2016 */
2017static void sigexit(int sig) NORETURN;
2018static void sigexit(int sig)
2019{
2020        /* Careful: we can end up here after [v]fork. Do not restore
2021         * tty pgrp then, only top-level shell process does that */
2022        if (G_saved_tty_pgrp && getpid() == G.root_pid) {
2023                /* Disable all signals: job control, SIGPIPE, etc.
2024                 * Mostly paranoid measure, to prevent infinite SIGTTOU.
2025                 */
2026                sigprocmask_allsigs(SIG_BLOCK);
2027                tcsetpgrp(G_interactive_fd, G_saved_tty_pgrp);
2028        }
2029
2030        /* Not a signal, just exit */
2031        if (sig <= 0)
2032                _exit(- sig);
2033
2034        kill_myself_with_sig(sig); /* does not return */
2035}
2036#else
2037
2038# define disable_restore_tty_pgrp_on_exit() ((void)0)
2039# define enable_restore_tty_pgrp_on_exit()  ((void)0)
2040
2041#endif
2042
2043static sighandler_t pick_sighandler(unsigned sig)
2044{
2045        sighandler_t handler = SIG_DFL;
2046        if (sig < sizeof(unsigned)*8) {
2047                unsigned sigmask = (1 << sig);
2048
2049#if ENABLE_HUSH_JOB
2050                /* is sig fatal? */
2051                if (G_fatal_sig_mask & sigmask)
2052                        handler = sigexit;
2053                else
2054#endif
2055                /* sig has special handling? */
2056                if (G.special_sig_mask & sigmask) {
2057                        handler = record_pending_signo;
2058                        /* TTIN/TTOU/TSTP can't be set to record_pending_signo
2059                         * in order to ignore them: they will be raised
2060                         * in an endless loop when we try to do some
2061                         * terminal ioctls! We do have to _ignore_ these.
2062                         */
2063                        if (SPECIAL_JOBSTOP_SIGS & sigmask)
2064                                handler = SIG_IGN;
2065                }
2066        }
2067        return handler;
2068}
2069
2070/* Restores tty foreground process group, and exits. */
2071static void hush_exit(int exitcode)
2072{
2073#if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
2074        save_history(G.line_input_state); /* may be NULL */
2075#endif
2076
2077        fflush_all();
2078        if (G.exiting <= 0 && G_traps && G_traps[0] && G_traps[0][0]) {
2079                char *argv[3];
2080                /* argv[0] is unused */
2081                argv[1] = xstrdup(G_traps[0]); /* copy, since EXIT trap handler may modify G_traps[0] */
2082                argv[2] = NULL;
2083                G.exiting = 1; /* prevent EXIT trap recursion */
2084                /* Note: G_traps[0] is not cleared!
2085                 * "trap" will still show it, if executed
2086                 * in the handler */
2087                builtin_eval(argv);
2088        }
2089
2090#if ENABLE_FEATURE_CLEAN_UP
2091        {
2092                struct variable *cur_var;
2093                if (G.cwd != bb_msg_unknown)
2094                        free((char*)G.cwd);
2095                cur_var = G.top_var;
2096                while (cur_var) {
2097                        struct variable *tmp = cur_var;
2098                        if (!cur_var->max_len)
2099                                free(cur_var->varstr);
2100                        cur_var = cur_var->next;
2101                        free(tmp);
2102                }
2103        }
2104#endif
2105
2106        fflush_all();
2107#if ENABLE_HUSH_JOB
2108        sigexit(- (exitcode & 0xff));
2109#else
2110        _exit(exitcode);
2111#endif
2112}
2113
2114//TODO: return a mask of ALL handled sigs?
2115static int check_and_run_traps(void)
2116{
2117        int last_sig = 0;
2118
2119        while (1) {
2120                int sig;
2121
2122                if (sigisemptyset(&G.pending_set))
2123                        break;
2124                sig = 0;
2125                do {
2126                        sig++;
2127                        if (sigismember(&G.pending_set, sig)) {
2128                                sigdelset(&G.pending_set, sig);
2129                                goto got_sig;
2130                        }
2131                } while (sig < NSIG);
2132                break;
2133 got_sig:
2134#if ENABLE_HUSH_TRAP
2135                if (G_traps && G_traps[sig]) {
2136                        debug_printf_exec("%s: sig:%d handler:'%s'\n", __func__, sig, G.traps[sig]);
2137                        if (G_traps[sig][0]) {
2138                                /* We have user-defined handler */
2139                                smalluint save_rcode;
2140                                int save_pre;
2141                                char *argv[3];
2142                                /* argv[0] is unused */
2143                                argv[1] = xstrdup(G_traps[sig]);
2144                                /* why strdup? trap can modify itself: trap 'trap "echo oops" INT' INT */
2145                                argv[2] = NULL;
2146                                save_pre = G.pre_trap_exitcode;
2147                                G.pre_trap_exitcode = save_rcode = G.last_exitcode;
2148                                builtin_eval(argv);
2149                                free(argv[1]);
2150                                G.pre_trap_exitcode = save_pre;
2151                                G.last_exitcode = save_rcode;
2152# if ENABLE_HUSH_FUNCTIONS
2153                                if (G.return_exitcode >= 0) {
2154                                        debug_printf_exec("trap exitcode:%d\n", G.return_exitcode);
2155                                        G.last_exitcode = G.return_exitcode;
2156                                }
2157# endif
2158                                last_sig = sig;
2159                        } /* else: "" trap, ignoring signal */
2160                        continue;
2161                }
2162#endif
2163                /* not a trap: special action */
2164                switch (sig) {
2165                case SIGINT:
2166                        debug_printf_exec("%s: sig:%d default SIGINT handler\n", __func__, sig);
2167                        G.flag_SIGINT = 1;
2168                        last_sig = sig;
2169                        break;
2170#if ENABLE_HUSH_JOB
2171                case SIGHUP: {
2172//TODO: why are we doing this? ash and dash don't do this,
2173//they have no handler for SIGHUP at all,
2174//they rely on kernel to send SIGHUP+SIGCONT to orphaned process groups
2175                        struct pipe *job;
2176                        debug_printf_exec("%s: sig:%d default SIGHUP handler\n", __func__, sig);
2177                        /* bash is observed to signal whole process groups,
2178                         * not individual processes */
2179                        for (job = G.job_list; job; job = job->next) {
2180                                if (job->pgrp <= 0)
2181                                        continue;
2182                                debug_printf_exec("HUPing pgrp %d\n", job->pgrp);
2183                                if (kill(- job->pgrp, SIGHUP) == 0)
2184                                        kill(- job->pgrp, SIGCONT);
2185                        }
2186                        sigexit(SIGHUP);
2187                }
2188#endif
2189#if ENABLE_HUSH_FAST
2190                case SIGCHLD:
2191                        debug_printf_exec("%s: sig:%d default SIGCHLD handler\n", __func__, sig);
2192                        G.count_SIGCHLD++;
2193//bb_error_msg("[%d] check_and_run_traps: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
2194                        /* Note:
2195                         * We don't do 'last_sig = sig' here -> NOT returning this sig.
2196                         * This simplifies wait builtin a bit.
2197                         */
2198                        break;
2199#endif
2200                default: /* ignored: */
2201                        debug_printf_exec("%s: sig:%d default handling is to ignore\n", __func__, sig);
2202                        /* SIGTERM, SIGQUIT, SIGTTIN, SIGTTOU, SIGTSTP */
2203                        /* Note:
2204                         * We don't do 'last_sig = sig' here -> NOT returning this sig.
2205                         * Example: wait is not interrupted by TERM
2206                         * in interactive shell, because TERM is ignored.
2207                         */
2208                        break;
2209                }
2210        }
2211        return last_sig;
2212}
2213
2214
2215static const char *get_cwd(int force)
2216{
2217        if (force || G.cwd == NULL) {
2218                /* xrealloc_getcwd_or_warn(arg) calls free(arg),
2219                 * we must not try to free(bb_msg_unknown) */
2220                if (G.cwd == bb_msg_unknown)
2221                        G.cwd = NULL;
2222                G.cwd = xrealloc_getcwd_or_warn((char *)G.cwd);
2223                if (!G.cwd)
2224                        G.cwd = bb_msg_unknown;
2225        }
2226        return G.cwd;
2227}
2228
2229
2230/*
2231 * Shell and environment variable support
2232 */
2233static struct variable **get_ptr_to_local_var(const char *name, unsigned len)
2234{
2235        struct variable **pp;
2236        struct variable *cur;
2237
2238        pp = &G.top_var;
2239        while ((cur = *pp) != NULL) {
2240                if (strncmp(cur->varstr, name, len) == 0 && cur->varstr[len] == '=')
2241                        return pp;
2242                pp = &cur->next;
2243        }
2244        return NULL;
2245}
2246
2247static const char* FAST_FUNC get_local_var_value(const char *name)
2248{
2249        struct variable **vpp;
2250        unsigned len = strlen(name);
2251
2252        if (G.expanded_assignments) {
2253                char **cpp = G.expanded_assignments;
2254                while (*cpp) {
2255                        char *cp = *cpp;
2256                        if (strncmp(cp, name, len) == 0 && cp[len] == '=')
2257                                return cp + len + 1;
2258                        cpp++;
2259                }
2260        }
2261
2262        vpp = get_ptr_to_local_var(name, len);
2263        if (vpp)
2264                return (*vpp)->varstr + len + 1;
2265
2266        if (strcmp(name, "PPID") == 0)
2267                return utoa(G.root_ppid);
2268        // bash compat: UID? EUID?
2269#if ENABLE_HUSH_RANDOM_SUPPORT
2270        if (strcmp(name, "RANDOM") == 0)
2271                return utoa(next_random(&G.random_gen));
2272#endif
2273#if ENABLE_HUSH_LINENO_VAR
2274        if (strcmp(name, "LINENO") == 0)
2275                return utoa(G.execute_lineno);
2276#endif
2277#if BASH_EPOCH_VARS
2278        {
2279                const char *fmt = NULL;
2280                if (strcmp(name, "EPOCHSECONDS") == 0)
2281                        fmt = "%llu";
2282                else if (strcmp(name, "EPOCHREALTIME") == 0)
2283                        fmt = "%llu.%06u";
2284                if (fmt) {
2285                        struct timeval tv;
2286                        xgettimeofday(&tv);
2287                        sprintf(G.epoch_buf, fmt, (unsigned long long)tv.tv_sec,
2288                                        (unsigned)tv.tv_usec);
2289                        return G.epoch_buf;
2290                }
2291        }
2292#endif
2293        return NULL;
2294}
2295
2296#if ENABLE_HUSH_GETOPTS
2297static void handle_changed_special_names(const char *name, unsigned name_len)
2298{
2299        if (name_len == 6) {
2300                if (strncmp(name, "OPTIND", 6) == 0) {
2301                        G.getopt_count = 0;
2302                        return;
2303                }
2304        }
2305}
2306#else
2307/* Do not even bother evaluating arguments */
2308# define handle_changed_special_names(...) ((void)0)
2309#endif
2310
2311/* str holds "NAME=VAL" and is expected to be malloced.
2312 * We take ownership of it.
2313 */
2314#define SETFLAG_EXPORT   (1 << 0)
2315#define SETFLAG_UNEXPORT (1 << 1)
2316#define SETFLAG_MAKE_RO  (1 << 2)
2317#define SETFLAG_VARLVL_SHIFT   3
2318static int set_local_var(char *str, unsigned flags)
2319{
2320        struct variable **cur_pp;
2321        struct variable *cur;
2322        char *free_me = NULL;
2323        char *eq_sign;
2324        int name_len;
2325        int retval;
2326        unsigned local_lvl = (flags >> SETFLAG_VARLVL_SHIFT);
2327
2328        eq_sign = strchr(str, '=');
2329        if (HUSH_DEBUG && !eq_sign)
2330                bb_simple_error_msg_and_die("BUG in setvar");
2331
2332        name_len = eq_sign - str + 1; /* including '=' */
2333        cur_pp = &G.top_var;
2334        while ((cur = *cur_pp) != NULL) {
2335                if (strncmp(cur->varstr, str, name_len) != 0) {
2336                        cur_pp = &cur->next;
2337                        continue;
2338                }
2339
2340                /* We found an existing var with this name */
2341                if (cur->flg_read_only) {
2342                        bb_error_msg("%s: readonly variable", str);
2343                        free(str);
2344//NOTE: in bash, assignment in "export READONLY_VAR=Z" fails, and sets $?=1,
2345//but export per se succeeds (does put the var in env). We don't mimic that.
2346                        return -1;
2347                }
2348                if (flags & SETFLAG_UNEXPORT) { // && cur->flg_export ?
2349                        debug_printf_env("%s: unsetenv '%s'\n", __func__, str);
2350                        *eq_sign = '\0';
2351                        unsetenv(str);
2352                        *eq_sign = '=';
2353                }
2354                if (cur->var_nest_level < local_lvl) {
2355                        /* bash 3.2.33(1) and exported vars:
2356                         * # export z=z
2357                         * # f() { local z=a; env | grep ^z; }
2358                         * # f
2359                         * z=a
2360                         * # env | grep ^z
2361                         * z=z
2362                         */
2363                        if (cur->flg_export)
2364                                flags |= SETFLAG_EXPORT;
2365                        /* New variable is local ("local VAR=VAL" or
2366                         * "VAR=VAL cmd")
2367                         * and existing one is global, or local
2368                         * on a lower level that new one.
2369                         * Remove it from global variable list:
2370                         */
2371                        *cur_pp = cur->next;
2372                        if (G.shadowed_vars_pp) {
2373                                /* Save in "shadowed" list */
2374                                debug_printf_env("shadowing %s'%s'/%u by '%s'/%u\n",
2375                                        cur->flg_export ? "exported " : "",
2376                                        cur->varstr, cur->var_nest_level, str, local_lvl
2377                                );
2378                                cur->next = *G.shadowed_vars_pp;
2379                                *G.shadowed_vars_pp = cur;
2380                        } else {
2381                                /* Came from pseudo_exec_argv(), no need to save: delete it */
2382                                debug_printf_env("shadow-deleting %s'%s'/%u by '%s'/%u\n",
2383                                        cur->flg_export ? "exported " : "",
2384                                        cur->varstr, cur->var_nest_level, str, local_lvl
2385                                );
2386                                if (cur->max_len == 0) /* allocated "VAR=VAL"? */
2387                                        free_me = cur->varstr; /* then free it later */
2388                                free(cur);
2389                        }
2390                        break;
2391                }
2392
2393                if (strcmp(cur->varstr + name_len, eq_sign + 1) == 0) {
2394                        debug_printf_env("assignement '%s' does not change anything\n", str);
2395 free_and_exp:
2396                        free(str);
2397                        goto exp;
2398                }
2399
2400                /* Replace the value in the found "struct variable" */
2401                if (cur->max_len != 0) {
2402                        if (cur->max_len >= strnlen(str, cur->max_len + 1)) {
2403                                /* This one is from startup env, reuse space */
2404                                debug_printf_env("reusing startup env for '%s'\n", str);
2405                                strcpy(cur->varstr, str);
2406                                goto free_and_exp;
2407                        }
2408                        /* Can't reuse */
2409                        cur->max_len = 0;
2410                        goto set_str_and_exp;
2411                }
2412                /* max_len == 0 signifies "malloced" var, which we can
2413                 * (and have to) free. But we can't free(cur->varstr) here:
2414                 * if cur->flg_export is 1, it is in the environment.
2415                 * We should either unsetenv+free, or wait until putenv,
2416                 * then putenv(new)+free(old).
2417                 */
2418                free_me = cur->varstr;
2419                goto set_str_and_exp;
2420        }
2421
2422        /* Not found or shadowed - create new variable struct */
2423        debug_printf_env("%s: alloc new var '%s'/%u\n", __func__, str, local_lvl);
2424        cur = xzalloc(sizeof(*cur));
2425        cur->var_nest_level = local_lvl;
2426        cur->next = *cur_pp;
2427        *cur_pp = cur;
2428
2429 set_str_and_exp:
2430        cur->varstr = str;
2431 exp:
2432#if !BB_MMU || ENABLE_HUSH_READONLY
2433        if (flags & SETFLAG_MAKE_RO) {
2434                cur->flg_read_only = 1;
2435        }
2436#endif
2437        if (flags & SETFLAG_EXPORT)
2438                cur->flg_export = 1;
2439        retval = 0;
2440        if (cur->flg_export) {
2441                if (flags & SETFLAG_UNEXPORT) {
2442                        cur->flg_export = 0;
2443                        /* unsetenv was already done */
2444                } else {
2445                        debug_printf_env("%s: putenv '%s'/%u\n", __func__, cur->varstr, cur->var_nest_level);
2446                        retval = putenv(cur->varstr);
2447                        /* fall through to "free(free_me)" -
2448                         * only now we can free old exported malloced string
2449                         */
2450                }
2451        }
2452        free(free_me);
2453
2454        handle_changed_special_names(cur->varstr, name_len - 1);
2455
2456        return retval;
2457}
2458
2459static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val)
2460{
2461        char *var = xasprintf("%s=%s", name, val);
2462        set_local_var(var, /*flag:*/ 0);
2463}
2464
2465/* Used at startup and after each cd */
2466static void set_pwd_var(unsigned flag)
2467{
2468        set_local_var(xasprintf("PWD=%s", get_cwd(/*force:*/ 1)), flag);
2469}
2470
2471#if ENABLE_HUSH_UNSET || ENABLE_HUSH_GETOPTS
2472static int unset_local_var_len(const char *name, int name_len)
2473{
2474        struct variable *cur;
2475        struct variable **cur_pp;
2476
2477        cur_pp = &G.top_var;
2478        while ((cur = *cur_pp) != NULL) {
2479                if (strncmp(cur->varstr, name, name_len) == 0
2480                 && cur->varstr[name_len] == '='
2481                ) {
2482                        if (cur->flg_read_only) {
2483                                bb_error_msg("%s: readonly variable", name);
2484                                return EXIT_FAILURE;
2485                        }
2486
2487                        *cur_pp = cur->next;
2488                        debug_printf_env("%s: unsetenv '%s'\n", __func__, cur->varstr);
2489                        bb_unsetenv(cur->varstr);
2490                        if (!cur->max_len)
2491                                free(cur->varstr);
2492                        free(cur);
2493
2494                        break;
2495                }
2496                cur_pp = &cur->next;
2497        }
2498
2499        /* Handle "unset LINENO" et al even if did not find the variable to unset */
2500        handle_changed_special_names(name, name_len);
2501
2502        return EXIT_SUCCESS;
2503}
2504
2505static int unset_local_var(const char *name)
2506{
2507        return unset_local_var_len(name, strlen(name));
2508}
2509#endif
2510
2511
2512/*
2513 * Helpers for "var1=val1 var2=val2 cmd" feature
2514 */
2515static void add_vars(struct variable *var)
2516{
2517        struct variable *next;
2518
2519        while (var) {
2520                next = var->next;
2521                var->next = G.top_var;
2522                G.top_var = var;
2523                if (var->flg_export) {
2524                        debug_printf_env("%s: restoring exported '%s'/%u\n", __func__, var->varstr, var->var_nest_level);
2525                        putenv(var->varstr);
2526                } else {
2527                        debug_printf_env("%s: restoring variable '%s'/%u\n", __func__, var->varstr, var->var_nest_level);
2528                }
2529                var = next;
2530        }
2531}
2532
2533/* We put strings[i] into variable table and possibly putenv them.
2534 * If variable is read only, we can free the strings[i]
2535 * which attempts to overwrite it.
2536 * The strings[] vector itself is freed.
2537 */
2538static void set_vars_and_save_old(char **strings)
2539{
2540        char **s;
2541
2542        if (!strings)
2543                return;
2544
2545        s = strings;
2546        while (*s) {
2547                struct variable *var_p;
2548                struct variable **var_pp;
2549                char *eq;
2550
2551                eq = strchr(*s, '=');
2552                if (HUSH_DEBUG && !eq)
2553                        bb_simple_error_msg_and_die("BUG in varexp4");
2554                var_pp = get_ptr_to_local_var(*s, eq - *s);
2555                if (var_pp) {
2556                        var_p = *var_pp;
2557                        if (var_p->flg_read_only) {
2558                                char **p;
2559                                bb_error_msg("%s: readonly variable", *s);
2560                                /*
2561                                 * "VAR=V BLTIN" unsets VARs after BLTIN completes.
2562                                 * If VAR is readonly, leaving it in the list
2563                                 * after asssignment error (msg above)
2564                                 * causes doubled error message later, on unset.
2565                                 */
2566                                debug_printf_env("removing/freeing '%s' element\n", *s);
2567                                free(*s);
2568                                p = s;
2569                                do { *p = p[1]; p++; } while (*p);
2570                                goto next;
2571                        }
2572                        /* below, set_local_var() with nest level will
2573                         * "shadow" (remove) this variable from
2574                         * global linked list.
2575                         */
2576                }
2577                debug_printf_env("%s: env override '%s'/%u\n", __func__, *s, G.var_nest_level);
2578                set_local_var(*s, (G.var_nest_level << SETFLAG_VARLVL_SHIFT) | SETFLAG_EXPORT);
2579                s++;
2580 next: ;
2581        }
2582        free(strings);
2583}
2584
2585
2586/*
2587 * Unicode helper
2588 */
2589static void reinit_unicode_for_hush(void)
2590{
2591        /* Unicode support should be activated even if LANG is set
2592         * _during_ shell execution, not only if it was set when
2593         * shell was started. Therefore, re-check LANG every time:
2594         */
2595        if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2596         || ENABLE_UNICODE_USING_LOCALE
2597        ) {
2598                const char *s = get_local_var_value("LC_ALL");
2599                if (!s) s = get_local_var_value("LC_CTYPE");
2600                if (!s) s = get_local_var_value("LANG");
2601                reinit_unicode(s);
2602        }
2603}
2604
2605/*
2606 * in_str support (strings, and "strings" read from files).
2607 */
2608
2609#if ENABLE_HUSH_INTERACTIVE
2610/* To test correct lineedit/interactive behavior, type from command line:
2611 *      echo $P\
2612 *      \
2613 *      AT\
2614 *      H\
2615 *      \
2616 * It exercises a lot of corner cases.
2617 */
2618static const char *setup_prompt_string(void)
2619{
2620        const char *prompt_str;
2621
2622        debug_printf_prompt("%s promptmode:%d\n", __func__, G.promptmode);
2623
2624# if ENABLE_FEATURE_EDITING_FANCY_PROMPT
2625        prompt_str = get_local_var_value(G.promptmode == 0 ? "PS1" : "PS2");
2626        if (!prompt_str)
2627                prompt_str = "";
2628# else
2629        prompt_str = "> "; /* if PS2, else... */
2630        if (G.promptmode == 0) { /* PS1 */
2631                /* No fancy prompts supported, (re)generate "CURDIR $ " by hand */
2632                free(G.PS1);
2633                /* bash uses $PWD value, even if it is set by user.
2634                 * It uses current dir only if PWD is unset.
2635                 * We always use current dir. */
2636                prompt_str = G.PS1 = xasprintf("%s %c ", get_cwd(0), (geteuid() != 0) ? '$' : '#');
2637        }
2638# endif
2639        debug_printf("prompt_str '%s'\n", prompt_str);
2640        return prompt_str;
2641}
2642static int get_user_input(struct in_str *i)
2643{
2644# if ENABLE_FEATURE_EDITING
2645        /* In EDITING case, this function reads next input line,
2646         * saves it in i->p, then returns 1st char of it.
2647         */
2648        int r;
2649        const char *prompt_str;
2650
2651        prompt_str = setup_prompt_string();
2652        for (;;) {
2653                reinit_unicode_for_hush();
2654                G.flag_SIGINT = 0;
2655                /* buglet: SIGINT will not make new prompt to appear _at once_,
2656                 * only after <Enter>. (^C works immediately) */
2657                r = read_line_input(G.line_input_state, prompt_str,
2658                                G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1
2659                );
2660                /* read_line_input intercepts ^C, "convert" it to SIGINT */
2661                if (r == 0) {
2662                        raise(SIGINT);
2663                }
2664                check_and_run_traps();
2665                if (r != 0 && !G.flag_SIGINT)
2666                        break;
2667                /* ^C or SIGINT: repeat */
2668                /* bash prints ^C even on real SIGINT (non-kbd generated) */
2669                write(STDOUT_FILENO, "^C\n", 3);
2670                G.last_exitcode = 128 | SIGINT;
2671        }
2672        if (r < 0) {
2673                /* EOF/error detected */
2674                /* ^D on interactive input goes to next line before exiting: */
2675                write(STDOUT_FILENO, "\n", 1);
2676                i->p = NULL;
2677                i->peek_buf[0] = r = EOF;
2678                return r;
2679        }
2680        i->p = G.user_input_buf;
2681        return (unsigned char)*i->p++;
2682# else
2683        /* In !EDITING case, this function gets called for every char.
2684         * Buffering happens deeper in the call chain, in hfgetc(i->file).
2685         */
2686        int r;
2687
2688        for (;;) {
2689                G.flag_SIGINT = 0;
2690                if (i->last_char == '\0' || i->last_char == '\n') {
2691                        const char *prompt_str = setup_prompt_string();
2692                        /* Why check_and_run_traps here? Try this interactively:
2693                         * $ trap 'echo INT' INT; (sleep 2; kill -INT $$) &
2694                         * $ <[enter], repeatedly...>
2695                         * Without check_and_run_traps, handler never runs.
2696                         */
2697                        check_and_run_traps();
2698                        fputs_stdout(prompt_str);
2699                        fflush_all();
2700                }
2701                r = hfgetc(i->file);
2702                /* In !ENABLE_FEATURE_EDITING we don't use read_line_input,
2703                 * no ^C masking happens during fgetc, no special code for ^C:
2704                 * it generates SIGINT as usual.
2705                 */
2706                check_and_run_traps();
2707                if (r != '\0' && !G.flag_SIGINT)
2708                        break;
2709                if (G.flag_SIGINT) {
2710                        /* ^C or SIGINT: repeat */
2711                        /* bash prints ^C even on real SIGINT (non-kbd generated) */
2712                        /* kernel prints "^C" itself, just print newline: */
2713                        write(STDOUT_FILENO, "\n", 1);
2714                        G.last_exitcode = 128 | SIGINT;
2715                }
2716        }
2717        return r;
2718# endif
2719}
2720/* This is the magic location that prints prompts
2721 * and gets data back from the user */
2722static int fgetc_interactive(struct in_str *i)
2723{
2724        int ch;
2725        /* If it's interactive stdin, get new line. */
2726        if (G_interactive_fd && i->file == G.HFILE_stdin) {
2727                /* Returns first char (or EOF), the rest is in i->p[] */
2728                ch = get_user_input(i);
2729                G.promptmode = 1; /* PS2 */
2730                debug_printf_prompt("%s promptmode=%d\n", __func__, G.promptmode);
2731        } else {
2732                /* Not stdin: script file, sourced file, etc */
2733                do ch = hfgetc(i->file); while (ch == '\0');
2734        }
2735        return ch;
2736}
2737#else  /* !INTERACTIVE */
2738static ALWAYS_INLINE int fgetc_interactive(struct in_str *i)
2739{
2740        int ch;
2741        do ch = hfgetc(i->file); while (ch == '\0');
2742        return ch;
2743}
2744#endif  /* !INTERACTIVE */
2745
2746static int i_getch(struct in_str *i)
2747{
2748        int ch;
2749
2750        if (!i->file) {
2751                /* string-based in_str */
2752                ch = (unsigned char)*i->p;
2753                if (ch != '\0') {
2754                        i->p++;
2755                        i->last_char = ch;
2756                        return ch;
2757                }
2758                return EOF;
2759        }
2760
2761        /* FILE-based in_str */
2762
2763#if ENABLE_FEATURE_EDITING
2764        /* This can be stdin, check line editing char[] buffer */
2765        if (i->p && *i->p != '\0') {
2766                ch = (unsigned char)*i->p++;
2767                goto out;
2768        }
2769#endif
2770        /* peek_buf[] is an int array, not char. Can contain EOF. */
2771        ch = i->peek_buf[0];
2772        if (ch != 0) {
2773                int ch2 = i->peek_buf[1];
2774                i->peek_buf[0] = ch2;
2775                if (ch2 == 0) /* very likely, avoid redundant write */
2776                        goto out;
2777                i->peek_buf[1] = 0;
2778                goto out;
2779        }
2780
2781        ch = fgetc_interactive(i);
2782 out:
2783        debug_printf("file_get: got '%c' %d\n", ch, ch);
2784        i->last_char = ch;
2785#if ENABLE_HUSH_LINENO_VAR
2786        if (ch == '\n') {
2787                G.parse_lineno++;
2788                debug_printf_parse("G.parse_lineno++ = %u\n", G.parse_lineno);
2789        }
2790#endif
2791        return ch;
2792}
2793
2794static int i_peek(struct in_str *i)
2795{
2796        int ch;
2797
2798        if (!i->file) {
2799                /* string-based in_str */
2800                /* Doesn't report EOF on NUL. None of the callers care. */
2801                return (unsigned char)*i->p;
2802        }
2803
2804        /* FILE-based in_str */
2805
2806#if ENABLE_FEATURE_EDITING && ENABLE_HUSH_INTERACTIVE
2807        /* This can be stdin, check line editing char[] buffer */
2808        if (i->p && *i->p != '\0')
2809                return (unsigned char)*i->p;
2810#endif
2811        /* peek_buf[] is an int array, not char. Can contain EOF. */
2812        ch = i->peek_buf[0];
2813        if (ch != 0)
2814                return ch;
2815
2816        /* Need to get a new char */
2817        ch = fgetc_interactive(i);
2818        debug_printf("file_peek: got '%c' %d\n", ch, ch);
2819
2820        /* Save it by either rolling back line editing buffer, or in i->peek_buf[0] */
2821#if ENABLE_FEATURE_EDITING && ENABLE_HUSH_INTERACTIVE
2822        if (i->p) {
2823                i->p -= 1;
2824                return ch;
2825        }
2826#endif
2827        i->peek_buf[0] = ch;
2828        /*i->peek_buf[1] = 0; - already is */
2829        return ch;
2830}
2831
2832/* Only ever called if i_peek() was called, and did not return EOF.
2833 * IOW: we know the previous peek saw an ordinary char, not EOF, not NUL,
2834 * not end-of-line. Therefore we never need to read a new editing line here.
2835 */
2836static int i_peek2(struct in_str *i)
2837{
2838        int ch;
2839
2840        /* There are two cases when i->p[] buffer exists.
2841         * (1) it's a string in_str.
2842         * (2) It's a file, and we have a saved line editing buffer.
2843         * In both cases, we know that i->p[0] exists and not NUL, and
2844         * the peek2 result is in i->p[1].
2845         */
2846        if (i->p)
2847                return (unsigned char)i->p[1];
2848
2849        /* Now we know it is a file-based in_str. */
2850
2851        /* peek_buf[] is an int array, not char. Can contain EOF. */
2852        /* Is there 2nd char? */
2853        ch = i->peek_buf[1];
2854        if (ch == 0) {
2855                /* We did not read it yet, get it now */
2856                do ch = hfgetc(i->file); while (ch == '\0');
2857                i->peek_buf[1] = ch;
2858        }
2859
2860        debug_printf("file_peek2: got '%c' %d\n", ch, ch);
2861        return ch;
2862}
2863
2864static int i_getch_and_eat_bkslash_nl(struct in_str *input)
2865{
2866        for (;;) {
2867                int ch, ch2;
2868
2869                ch = i_getch(input);
2870                if (ch != '\\')
2871                        return ch;
2872                ch2 = i_peek(input);
2873                if (ch2 != '\n')
2874                        return ch;
2875                /* backslash+newline, skip it */
2876                i_getch(input);
2877        }
2878}
2879
2880/* Note: this function _eats_ \<newline> pairs, safe to use plain
2881 * i_getch() after it instead of i_getch_and_eat_bkslash_nl().
2882 */
2883static int i_peek_and_eat_bkslash_nl(struct in_str *input)
2884{
2885        for (;;) {
2886                int ch, ch2;
2887
2888                ch = i_peek(input);
2889                if (ch != '\\')
2890                        return ch;
2891                ch2 = i_peek2(input);
2892                if (ch2 != '\n')
2893                        return ch;
2894                /* backslash+newline, skip it */
2895                i_getch(input);
2896                i_getch(input);
2897        }
2898}
2899
2900static void setup_file_in_str(struct in_str *i, HFILE *fp)
2901{
2902        memset(i, 0, sizeof(*i));
2903        i->file = fp;
2904        /* i->p = NULL; */
2905}
2906
2907static void setup_string_in_str(struct in_str *i, const char *s)
2908{
2909        memset(i, 0, sizeof(*i));
2910        /*i->file = NULL */;
2911        i->p = s;
2912}
2913
2914
2915/*
2916 * o_string support
2917 */
2918#define B_CHUNK  (32 * sizeof(char*))
2919
2920static void o_reset_to_empty_unquoted(o_string *o)
2921{
2922        o->length = 0;
2923        o->has_quoted_part = 0;
2924        if (o->data)
2925                o->data[0] = '\0';
2926}
2927
2928static void o_free_and_set_NULL(o_string *o)
2929{
2930        free(o->data);
2931        memset(o, 0, sizeof(*o));
2932}
2933
2934static ALWAYS_INLINE void o_free(o_string *o)
2935{
2936        free(o->data);
2937}
2938
2939static void o_grow_by(o_string *o, int len)
2940{
2941        if (o->length + len > o->maxlen) {
2942                o->maxlen += (2 * len) | (B_CHUNK-1);
2943                o->data = xrealloc(o->data, 1 + o->maxlen);
2944        }
2945}
2946
2947static void o_addchr(o_string *o, int ch)
2948{
2949        debug_printf("o_addchr: '%c' o->length=%d o=%p\n", ch, o->length, o);
2950        if (o->length < o->maxlen) {
2951                /* likely. avoid o_grow_by() call */
2952 add:
2953                o->data[o->length] = ch;
2954                o->length++;
2955                o->data[o->length] = '\0';
2956                return;
2957        }
2958        o_grow_by(o, 1);
2959        goto add;
2960}
2961
2962#if 0
2963/* Valid only if we know o_string is not empty */
2964static void o_delchr(o_string *o)
2965{
2966        o->length--;
2967        o->data[o->length] = '\0';
2968}
2969#endif
2970
2971static void o_addblock(o_string *o, const char *str, int len)
2972{
2973        o_grow_by(o, len);
2974        ((char*)mempcpy(&o->data[o->length], str, len))[0] = '\0';
2975        o->length += len;
2976}
2977
2978static void o_addstr(o_string *o, const char *str)
2979{
2980        o_addblock(o, str, strlen(str));
2981}
2982
2983static void o_addstr_with_NUL(o_string *o, const char *str)
2984{
2985        o_addblock(o, str, strlen(str) + 1);
2986}
2987
2988#if !BB_MMU
2989static void nommu_addchr(o_string *o, int ch)
2990{
2991        if (o)
2992                o_addchr(o, ch);
2993}
2994#else
2995# define nommu_addchr(o, str) ((void)0)
2996#endif
2997
2998#if ENABLE_HUSH_MODE_X
2999static void x_mode_addchr(int ch)
3000{
3001        o_addchr(&G.x_mode_buf, ch);
3002}
3003static void x_mode_addstr(const char *str)
3004{
3005        o_addstr(&G.x_mode_buf, str);
3006}
3007static void x_mode_addblock(const char *str, int len)
3008{
3009        o_addblock(&G.x_mode_buf, str, len);
3010}
3011static void x_mode_prefix(void)
3012{
3013        int n = G.x_mode_depth;
3014        do x_mode_addchr('+'); while (--n >= 0);
3015}
3016static void x_mode_flush(void)
3017{
3018        int len = G.x_mode_buf.length;
3019        if (len <= 0)
3020                return;
3021        if (G.x_mode_fd > 0) {
3022                G.x_mode_buf.data[len] = '\n';
3023                full_write(G.x_mode_fd, G.x_mode_buf.data, len + 1);
3024        }
3025        G.x_mode_buf.length = 0;
3026}
3027#endif
3028
3029/*
3030 * HUSH_BRACE_EXPANSION code needs corresponding quoting on variable expansion side.
3031 * Currently, "v='{q,w}'; echo $v" erroneously expands braces in $v.
3032 * Apparently, on unquoted $v bash still does globbing
3033 * ("v='*.txt'; echo $v" prints all .txt files),
3034 * but NOT brace expansion! Thus, there should be TWO independent
3035 * quoting mechanisms on $v expansion side: one protects
3036 * $v from brace expansion, and other additionally protects "$v" against globbing.
3037 * We have only second one.
3038 */
3039
3040#if ENABLE_HUSH_BRACE_EXPANSION
3041# define MAYBE_BRACES "{}"
3042#else
3043# define MAYBE_BRACES ""
3044#endif
3045
3046/* My analysis of quoting semantics tells me that state information
3047 * is associated with a destination, not a source.
3048 */
3049static void o_addqchr(o_string *o, int ch)
3050{
3051        int sz = 1;
3052        /* '-' is included because of this case:
3053         * >filename0 >filename1 >filename9; v='-'; echo filename[0"$v"9]
3054         */
3055        char *found = strchr("*?[-\\" MAYBE_BRACES, ch);
3056        if (found)
3057                sz++;
3058        o_grow_by(o, sz);
3059        if (found) {
3060                o->data[o->length] = '\\';
3061                o->length++;
3062        }
3063        o->data[o->length] = ch;
3064        o->length++;
3065        o->data[o->length] = '\0';
3066}
3067
3068static void o_addQchr(o_string *o, int ch)
3069{
3070        int sz = 1;
3071        if ((o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)
3072         && strchr("*?[-\\" MAYBE_BRACES, ch)
3073        ) {
3074                sz++;
3075                o->data[o->length] = '\\';
3076                o->length++;
3077        }
3078        o_grow_by(o, sz);
3079        o->data[o->length] = ch;
3080        o->length++;
3081        o->data[o->length] = '\0';
3082}
3083
3084static void o_addqblock(o_string *o, const char *str, int len)
3085{
3086        while (len) {
3087                char ch;
3088                int sz;
3089                int ordinary_cnt = strcspn(str, "*?[-\\" MAYBE_BRACES);
3090                if (ordinary_cnt > len) /* paranoia */
3091                        ordinary_cnt = len;
3092                o_addblock(o, str, ordinary_cnt);
3093                if (ordinary_cnt == len)
3094                        return; /* NUL is already added by o_addblock */
3095                str += ordinary_cnt;
3096                len -= ordinary_cnt + 1; /* we are processing + 1 char below */
3097
3098                ch = *str++;
3099                sz = 1;
3100                if (ch) { /* it is necessarily one of "*?[-\\" MAYBE_BRACES */
3101                        sz++;
3102                        o->data[o->length] = '\\';
3103                        o->length++;
3104                }
3105                o_grow_by(o, sz);
3106                o->data[o->length] = ch;
3107                o->length++;
3108        }
3109        o->data[o->length] = '\0';
3110}
3111
3112static void o_addQblock(o_string *o, const char *str, int len)
3113{
3114        if (!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)) {
3115                o_addblock(o, str, len);
3116                return;
3117        }
3118        o_addqblock(o, str, len);
3119}
3120
3121static void o_addQstr(o_string *o, const char *str)
3122{
3123        o_addQblock(o, str, strlen(str));
3124}
3125
3126/* A special kind of o_string for $VAR and `cmd` expansion.
3127 * It contains char* list[] at the beginning, which is grown in 16 element
3128 * increments. Actual string data starts at the next multiple of 16 * (char*).
3129 * list[i] contains an INDEX (int!) into this string data.
3130 * It means that if list[] needs to grow, data needs to be moved higher up
3131 * but list[i]'s need not be modified.
3132 * NB: remembering how many list[i]'s you have there is crucial.
3133 * o_finalize_list() operation post-processes this structure - calculates
3134 * and stores actual char* ptrs in list[]. Oh, it NULL terminates it as well.
3135 */
3136#if DEBUG_EXPAND || DEBUG_GLOB
3137static void debug_print_list(const char *prefix, o_string *o, int n)
3138{
3139        char **list = (char**)o->data;
3140        int string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
3141        int i = 0;
3142
3143        indent();
3144        fdprintf(2, "%s: list:%p n:%d string_start:%d length:%d maxlen:%d glob:%d quoted:%d escape:%d\n",
3145                        prefix, list, n, string_start, o->length, o->maxlen,
3146                        !!(o->o_expflags & EXP_FLAG_GLOB),
3147                        o->has_quoted_part,
3148                        !!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
3149        while (i < n) {
3150                indent();
3151                fdprintf(2, " list[%d]=%d '%s' %p\n", i, (int)(uintptr_t)list[i],
3152                                o->data + (int)(uintptr_t)list[i] + string_start,
3153                                o->data + (int)(uintptr_t)list[i] + string_start);
3154                i++;
3155        }
3156        if (n) {
3157                const char *p = o->data + (int)(uintptr_t)list[n - 1] + string_start;
3158                indent();
3159                fdprintf(2, " total_sz:%ld\n", (long)((p + strlen(p) + 1) - o->data));
3160        }
3161}
3162#else
3163# define debug_print_list(prefix, o, n) ((void)0)
3164#endif
3165
3166/* n = o_save_ptr_helper(str, n) "starts new string" by storing an index value
3167 * in list[n] so that it points past last stored byte so far.
3168 * It returns n+1. */
3169static int o_save_ptr_helper(o_string *o, int n)
3170{
3171        char **list = (char**)o->data;
3172        int string_start;
3173        int string_len;
3174
3175        if (!o->has_empty_slot) {
3176                string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
3177                string_len = o->length - string_start;
3178                if (!(n & 0xf)) { /* 0, 0x10, 0x20...? */
3179                        debug_printf_list("list[%d]=%d string_start=%d (growing)\n", n, string_len, string_start);
3180                        /* list[n] points to string_start, make space for 16 more pointers */
3181                        o->maxlen += 0x10 * sizeof(list[0]);
3182                        o->data = xrealloc(o->data, o->maxlen + 1);
3183                        list = (char**)o->data;
3184                        memmove(list + n + 0x10, list + n, string_len);
3185                        /*
3186                         * expand_on_ifs() has a "previous argv[] ends in IFS?"
3187                         * check. (grep for -prev-ifs-check-).
3188                         * Ensure that argv[-1][last] is not garbage
3189                         * but zero bytes, to save index check there.
3190                         */
3191                        list[n + 0x10 - 1] = 0;
3192                        o->length += 0x10 * sizeof(list[0]);
3193                } else {
3194                        debug_printf_list("list[%d]=%d string_start=%d\n",
3195                                        n, string_len, string_start);
3196                }
3197        } else {
3198                /* We have empty slot at list[n], reuse without growth */
3199                string_start = ((n+1 + 0xf) & ~0xf) * sizeof(list[0]); /* NB: n+1! */
3200                string_len = o->length - string_start;
3201                debug_printf_list("list[%d]=%d string_start=%d (empty slot)\n",
3202                                n, string_len, string_start);
3203                o->has_empty_slot = 0;
3204        }
3205        o->has_quoted_part = 0;
3206        list[n] = (char*)(uintptr_t)string_len;
3207        return n + 1;
3208}
3209
3210/* "What was our last o_save_ptr'ed position (byte offset relative o->data)?" */
3211static int o_get_last_ptr(o_string *o, int n)
3212{
3213        char **list = (char**)o->data;
3214        int string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
3215
3216        return ((int)(uintptr_t)list[n-1]) + string_start;
3217}
3218
3219/*
3220 * Globbing routines.
3221 *
3222 * Most words in commands need to be globbed, even ones which are
3223 * (single or double) quoted. This stems from the possiblity of
3224 * constructs like "abc"* and 'abc'* - these should be globbed.
3225 * Having a different code path for fully-quoted strings ("abc",
3226 * 'abc') would only help performance-wise, but we still need
3227 * code for partially-quoted strings.
3228 *
3229 * Unfortunately, if we want to match bash and ash behavior in all cases,
3230 * the logic can't be "shell-syntax argument is first transformed
3231 * to a string, then globbed, and if globbing does not match anything,
3232 * it is used verbatim". Here are two examples where it fails:
3233 *
3234 *      echo 'b\*'?
3235 *
3236 * The globbing can't be avoided (because of '?' at the end).
3237 * The glob pattern is: b\\\*? - IOW, both \ and * are literals
3238 * and are glob-escaped. If this does not match, bash/ash print b\*?
3239 * - IOW: they "unbackslash" the glob pattern.
3240 * Now, look at this:
3241 *
3242 *      v='\\\*'; echo b$v?
3243 *
3244 * The glob pattern is the same here: b\\\*? - the unquoted $v expansion
3245 * should be used as glob pattern with no changes. However, if glob
3246 * does not match, bash/ash print b\\\*? - NOT THE SAME as first example!
3247 *
3248 * ash implements this by having an encoded representation of the word
3249 * to glob, which IS NOT THE SAME as the glob pattern - it has more data.
3250 * Glob pattern is derived from it. If glob fails, the decision what result
3251 * should be is made using that encoded representation. Not glob pattern.
3252 */
3253
3254#if ENABLE_HUSH_BRACE_EXPANSION
3255/* There in a GNU extension, GLOB_BRACE, but it is not usable:
3256 * first, it processes even {a} (no commas), second,
3257 * I didn't manage to make it return strings when they don't match
3258 * existing files. Need to re-implement it.
3259 */
3260
3261/* Helper */
3262static int glob_needed(const char *s)
3263{
3264        while (*s) {
3265                if (*s == '\\') {
3266                        if (!s[1])
3267                                return 0;
3268                        s += 2;
3269                        continue;
3270                }
3271                if (*s == '*' || *s == '[' || *s == '?' || *s == '{')
3272                        return 1;
3273                s++;
3274        }
3275        return 0;
3276}
3277/* Return pointer to next closing brace or to comma */
3278static const char *next_brace_sub(const char *cp)
3279{
3280        unsigned depth = 0;
3281        cp++;
3282        while (*cp != '\0') {
3283                if (*cp == '\\') {
3284                        if (*++cp == '\0')
3285                                break;
3286                        cp++;
3287                        continue;
3288                }
3289                if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0))
3290                        break;
3291                if (*cp++ == '{')
3292                        depth++;
3293        }
3294
3295        return *cp != '\0' ? cp : NULL;
3296}
3297/* Recursive brace globber. Note: may garble pattern[]. */
3298static int glob_brace(char *pattern, o_string *o, int n)
3299{
3300        char *new_pattern_buf;
3301        const char *begin;
3302        const char *next;
3303        const char *rest;
3304        const char *p;
3305        size_t rest_len;
3306
3307        debug_printf_glob("glob_brace('%s')\n", pattern);
3308
3309        begin = pattern;
3310        while (1) {
3311                if (*begin == '\0')
3312                        goto simple_glob;
3313                if (*begin == '{') {
3314                        /* Find the first sub-pattern and at the same time
3315                         * find the rest after the closing brace */
3316                        next = next_brace_sub(begin);
3317                        if (next == NULL) {
3318                                /* An illegal expression */
3319                                goto simple_glob;
3320                        }
3321                        if (*next == '}') {
3322                                /* "{abc}" with no commas - illegal
3323                                 * brace expr, disregard and skip it */
3324                                begin = next + 1;
3325                                continue;
3326                        }
3327                        break;
3328                }
3329                if (*begin == '\\' && begin[1] != '\0')
3330                        begin++;
3331                begin++;
3332        }
3333        debug_printf_glob("begin:%s\n", begin);
3334        debug_printf_glob("next:%s\n", next);
3335
3336        /* Now find the end of the whole brace expression */
3337        rest = next;
3338        while (*rest != '}') {
3339                rest = next_brace_sub(rest);
3340                if (rest == NULL) {
3341                        /* An illegal expression */
3342                        goto simple_glob;
3343                }
3344                debug_printf_glob("rest:%s\n", rest);
3345        }
3346        rest_len = strlen(++rest) + 1;
3347
3348        /* We are sure the brace expression is well-formed */
3349
3350        /* Allocate working buffer large enough for our work */
3351        new_pattern_buf = xmalloc(strlen(pattern));
3352
3353        /* We have a brace expression.  BEGIN points to the opening {,
3354         * NEXT points past the terminator of the first element, and REST
3355         * points past the final }.  We will accumulate result names from
3356         * recursive runs for each brace alternative in the buffer using
3357         * GLOB_APPEND.  */
3358
3359        p = begin + 1;
3360        while (1) {
3361                /* Construct the new glob expression */
3362                memcpy(
3363                        mempcpy(
3364                                mempcpy(new_pattern_buf,
3365                                        /* We know the prefix for all sub-patterns */
3366                                        pattern, begin - pattern),
3367                                p, next - p),
3368                        rest, rest_len);
3369
3370                /* Note: glob_brace() may garble new_pattern_buf[].
3371                 * That's why we re-copy prefix every time (1st memcpy above).
3372                 */
3373                n = glob_brace(new_pattern_buf, o, n);
3374                if (*next == '}') {
3375                        /* We saw the last entry */
3376                        break;
3377                }
3378                p = next + 1;
3379                next = next_brace_sub(next);
3380        }
3381        free(new_pattern_buf);
3382        return n;
3383
3384 simple_glob:
3385        {
3386                int gr;
3387                glob_t globdata;
3388
3389                memset(&globdata, 0, sizeof(globdata));
3390                gr = glob(pattern, 0, NULL, &globdata);
3391                debug_printf_glob("glob('%s'):%d\n", pattern, gr);
3392                if (gr != 0) {
3393                        if (gr == GLOB_NOMATCH) {
3394                                globfree(&globdata);
3395                                /* NB: garbles parameter */
3396                                unbackslash(pattern);
3397                                o_addstr_with_NUL(o, pattern);
3398                                debug_printf_glob("glob pattern '%s' is literal\n", pattern);
3399                                return o_save_ptr_helper(o, n);
3400                        }
3401                        if (gr == GLOB_NOSPACE)
3402                                bb_die_memory_exhausted();
3403                        /* GLOB_ABORTED? Only happens with GLOB_ERR flag,
3404                         * but we didn't specify it. Paranoia again. */
3405                        bb_error_msg_and_die("glob error %d on '%s'", gr, pattern);
3406                }
3407                if (globdata.gl_pathv && globdata.gl_pathv[0]) {
3408                        char **argv = globdata.gl_pathv;
3409                        while (1) {
3410                                o_addstr_with_NUL(o, *argv);
3411                                n = o_save_ptr_helper(o, n);
3412                                argv++;
3413                                if (!*argv)
3414                                        break;
3415                        }
3416                }
3417                globfree(&globdata);
3418        }
3419        return n;
3420}
3421/* Performs globbing on last list[],
3422 * saving each result as a new list[].
3423 */
3424static int perform_glob(o_string *o, int n)
3425{
3426        char *pattern, *copy;
3427
3428        debug_printf_glob("start perform_glob: n:%d o->data:%p\n", n, o->data);
3429        if (!o->data)
3430                return o_save_ptr_helper(o, n);
3431        pattern = o->data + o_get_last_ptr(o, n);
3432        debug_printf_glob("glob pattern '%s'\n", pattern);
3433        if (!glob_needed(pattern)) {
3434                /* unbackslash last string in o in place, fix length */
3435                o->length = unbackslash(pattern) - o->data;
3436                debug_printf_glob("glob pattern '%s' is literal\n", pattern);
3437                return o_save_ptr_helper(o, n);
3438        }
3439
3440        copy = xstrdup(pattern);
3441        /* "forget" pattern in o */
3442        o->length = pattern - o->data;
3443        n = glob_brace(copy, o, n);
3444        free(copy);
3445        if (DEBUG_GLOB)
3446                debug_print_list("perform_glob returning", o, n);
3447        return n;
3448}
3449
3450#else /* !HUSH_BRACE_EXPANSION */
3451
3452/* Helper */
3453static int glob_needed(const char *s)
3454{
3455        while (*s) {
3456                if (*s == '\\') {
3457                        if (!s[1])
3458                                return 0;
3459                        s += 2;
3460                        continue;
3461                }
3462                if (*s == '*' || *s == '[' || *s == '?')
3463                        return 1;
3464                s++;
3465        }
3466        return 0;
3467}
3468/* Performs globbing on last list[],
3469 * saving each result as a new list[].
3470 */
3471static int perform_glob(o_string *o, int n)
3472{
3473        glob_t globdata;
3474        int gr;
3475        char *pattern;
3476
3477        debug_printf_glob("start perform_glob: n:%d o->data:%p\n", n, o->data);
3478        if (!o->data)
3479                return o_save_ptr_helper(o, n);
3480        pattern = o->data + o_get_last_ptr(o, n);
3481        debug_printf_glob("glob pattern '%s'\n", pattern);
3482        if (!glob_needed(pattern)) {
3483 literal:
3484                /* unbackslash last string in o in place, fix length */
3485                o->length = unbackslash(pattern) - o->data;
3486                debug_printf_glob("glob pattern '%s' is literal\n", pattern);
3487                return o_save_ptr_helper(o, n);
3488        }
3489
3490        memset(&globdata, 0, sizeof(globdata));
3491        /* Can't use GLOB_NOCHECK: it does not unescape the string.
3492         * If we glob "*.\*" and don't find anything, we need
3493         * to fall back to using literal "*.*", but GLOB_NOCHECK
3494         * will return "*.\*"!
3495         */
3496        gr = glob(pattern, 0, NULL, &globdata);
3497        debug_printf_glob("glob('%s'):%d\n", pattern, gr);
3498        if (gr != 0) {
3499                if (gr == GLOB_NOMATCH) {
3500                        globfree(&globdata);
3501                        goto literal;
3502                }
3503                if (gr == GLOB_NOSPACE)
3504                        bb_die_memory_exhausted();
3505                /* GLOB_ABORTED? Only happens with GLOB_ERR flag,
3506                 * but we didn't specify it. Paranoia again. */
3507                bb_error_msg_and_die("glob error %d on '%s'", gr, pattern);
3508        }
3509        if (globdata.gl_pathv && globdata.gl_pathv[0]) {
3510                char **argv = globdata.gl_pathv;
3511                /* "forget" pattern in o */
3512                o->length = pattern - o->data;
3513                while (1) {
3514                        o_addstr_with_NUL(o, *argv);
3515                        n = o_save_ptr_helper(o, n);
3516                        argv++;
3517                        if (!*argv)
3518                                break;
3519                }
3520        }
3521        globfree(&globdata);
3522        if (DEBUG_GLOB)
3523                debug_print_list("perform_glob returning", o, n);
3524        return n;
3525}
3526
3527#endif /* !HUSH_BRACE_EXPANSION */
3528
3529/* If o->o_expflags & EXP_FLAG_GLOB, glob the string so far remembered.
3530 * Otherwise, just finish current list[] and start new */
3531static int o_save_ptr(o_string *o, int n)
3532{
3533        if (o->o_expflags & EXP_FLAG_GLOB) {
3534                /* If o->has_empty_slot, list[n] was already globbed
3535                 * (if it was requested back then when it was filled)
3536                 * so don't do that again! */
3537                if (!o->has_empty_slot)
3538                        return perform_glob(o, n); /* o_save_ptr_helper is inside */
3539        }
3540        return o_save_ptr_helper(o, n);
3541}
3542
3543/* "Please convert list[n] to real char* ptrs, and NULL terminate it." */
3544static char **o_finalize_list(o_string *o, int n)
3545{
3546        char **list;
3547        int string_start;
3548
3549        if (DEBUG_EXPAND)
3550                debug_print_list("finalized", o, n);
3551        debug_printf_expand("finalized n:%d\n", n);
3552        list = (char**)o->data;
3553        string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
3554        list[--n] = NULL;
3555        while (n) {
3556                n--;
3557                list[n] = o->data + (int)(uintptr_t)list[n] + string_start;
3558        }
3559        return list;
3560}
3561
3562static void free_pipe_list(struct pipe *pi);
3563
3564/* Returns pi->next - next pipe in the list */
3565static struct pipe *free_pipe(struct pipe *pi)
3566{
3567        struct pipe *next;
3568        int i;
3569
3570        debug_printf_clean("free_pipe (pid %d)\n", getpid());
3571        for (i = 0; i < pi->num_cmds; i++) {
3572                struct command *command;
3573                struct redir_struct *r, *rnext;
3574
3575                command = &pi->cmds[i];
3576                debug_printf_clean("  command %d:\n", i);
3577                if (command->argv) {
3578                        if (DEBUG_CLEAN) {
3579                                int a;
3580                                char **p;
3581                                for (a = 0, p = command->argv; *p; a++, p++) {
3582                                        debug_printf_clean("   argv[%d] = %s\n", a, *p);
3583                                }
3584                        }
3585                        free_strings(command->argv);
3586                        //command->argv = NULL;
3587                }
3588                /* not "else if": on syntax error, we may have both! */
3589                if (command->group) {
3590                        debug_printf_clean("   begin group (cmd_type:%d)\n",
3591                                        command->cmd_type);
3592                        free_pipe_list(command->group);
3593                        debug_printf_clean("   end group\n");
3594                        //command->group = NULL;
3595                }
3596                /* else is crucial here.
3597                 * If group != NULL, child_func is meaningless */
3598#if ENABLE_HUSH_FUNCTIONS
3599                else if (command->child_func) {
3600                        debug_printf_exec("cmd %p releases child func at %p\n", command, command->child_func);
3601                        command->child_func->parent_cmd = NULL;
3602                }
3603#endif
3604#if !BB_MMU
3605                free(command->group_as_string);
3606                //command->group_as_string = NULL;
3607#endif
3608                for (r = command->redirects; r; r = rnext) {
3609                        debug_printf_clean("   redirect %d%s",
3610                                        r->rd_fd, redir_table[r->rd_type].descrip);
3611                        /* guard against the case >$FOO, where foo is unset or blank */
3612                        if (r->rd_filename) {
3613                                debug_printf_clean(" fname:'%s'\n", r->rd_filename);
3614                                free(r->rd_filename);
3615                                //r->rd_filename = NULL;
3616                        }
3617                        debug_printf_clean(" rd_dup:%d\n", r->rd_dup);
3618                        rnext = r->next;
3619                        free(r);
3620                }
3621                //command->redirects = NULL;
3622        }
3623        free(pi->cmds);   /* children are an array, they get freed all at once */
3624        //pi->cmds = NULL;
3625#if ENABLE_HUSH_JOB
3626        free(pi->cmdtext);
3627        //pi->cmdtext = NULL;
3628#endif
3629
3630        next = pi->next;
3631        free(pi);
3632        return next;
3633}
3634
3635static void free_pipe_list(struct pipe *pi)
3636{
3637        while (pi) {
3638#if HAS_KEYWORDS
3639                debug_printf_clean("pipe reserved word %d\n", pi->res_word);
3640#endif
3641                debug_printf_clean("pipe followup code %d\n", pi->followup);
3642                pi = free_pipe(pi);
3643        }
3644}
3645
3646
3647/*** Parsing routines ***/
3648
3649#ifndef debug_print_tree
3650static void debug_print_tree(struct pipe *pi, int lvl)
3651{
3652        static const char *const PIPE[] = {
3653                [PIPE_SEQ] = "SEQ",
3654                [PIPE_AND] = "AND",
3655                [PIPE_OR ] = "OR" ,
3656                [PIPE_BG ] = "BG" ,
3657        };
3658        static const char *RES[] = {
3659                [RES_NONE ] = "NONE" ,
3660# if ENABLE_HUSH_IF
3661                [RES_IF   ] = "IF"   ,
3662                [RES_THEN ] = "THEN" ,
3663                [RES_ELIF ] = "ELIF" ,
3664                [RES_ELSE ] = "ELSE" ,
3665                [RES_FI   ] = "FI"   ,
3666# endif
3667# if ENABLE_HUSH_LOOPS
3668                [RES_FOR  ] = "FOR"  ,
3669                [RES_WHILE] = "WHILE",
3670                [RES_UNTIL] = "UNTIL",
3671                [RES_DO   ] = "DO"   ,
3672                [RES_DONE ] = "DONE" ,
3673# endif
3674# if ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
3675                [RES_IN   ] = "IN"   ,
3676# endif
3677# if ENABLE_HUSH_CASE
3678                [RES_CASE ] = "CASE" ,
3679                [RES_CASE_IN ] = "CASE_IN" ,
3680                [RES_MATCH] = "MATCH",
3681                [RES_CASE_BODY] = "CASE_BODY",
3682                [RES_ESAC ] = "ESAC" ,
3683# endif
3684                [RES_XXXX ] = "XXXX" ,
3685                [RES_SNTX ] = "SNTX" ,
3686        };
3687        static const char *const CMDTYPE[] = {
3688                "{}",
3689                "()",
3690                "[noglob]",
3691# if ENABLE_HUSH_FUNCTIONS
3692                "func()",
3693# endif
3694        };
3695
3696        int pin, prn;
3697
3698        pin = 0;
3699        while (pi) {
3700                fdprintf(2, "%*spipe %d #cmds:%d %sres_word=%s followup=%d %s\n",
3701                                lvl*2, "",
3702                                pin,
3703                                pi->num_cmds,
3704                                (IF_HAS_KEYWORDS(pi->pi_inverted ? "! " :) ""),
3705                                RES[pi->res_word],
3706                                pi->followup, PIPE[pi->followup]
3707                );
3708                prn = 0;
3709                while (prn < pi->num_cmds) {
3710                        struct command *command = &pi->cmds[prn];
3711                        char **argv = command->argv;
3712
3713                        fdprintf(2, "%*s cmd %d assignment_cnt:%d",
3714                                        lvl*2, "", prn,
3715                                        command->assignment_cnt);
3716# if ENABLE_HUSH_LINENO_VAR
3717                        fdprintf(2, " LINENO:%u", command->lineno);
3718# endif
3719                        if (command->group) {
3720                                fdprintf(2, " group %s: (argv=%p)%s%s\n",
3721                                                CMDTYPE[command->cmd_type],
3722                                                argv
3723# if !BB_MMU
3724                                                , " group_as_string:", command->group_as_string
3725# else
3726                                                , "", ""
3727# endif
3728                                );
3729                                debug_print_tree(command->group, lvl+1);
3730                                prn++;
3731                                continue;
3732                        }
3733                        if (argv) while (*argv) {
3734                                fdprintf(2, " '%s'", *argv);
3735                                argv++;
3736                        }
3737                        if (command->redirects)
3738                                fdprintf(2, " {redir}");
3739                        fdprintf(2, "\n");
3740                        prn++;
3741                }
3742                pi = pi->next;
3743                pin++;
3744        }
3745}
3746#endif /* debug_print_tree */
3747
3748static struct pipe *new_pipe(void)
3749{
3750        struct pipe *pi;
3751        pi = xzalloc(sizeof(struct pipe));
3752        /*pi->res_word = RES_NONE; - RES_NONE is 0 anyway */
3753        return pi;
3754}
3755
3756/* Command (member of a pipe) is complete, or we start a new pipe
3757 * if ctx->command is NULL.
3758 * No errors possible here.
3759 */
3760static int done_command(struct parse_context *ctx)
3761{
3762        /* The command is really already in the pipe structure, so
3763         * advance the pipe counter and make a new, null command. */
3764        struct pipe *pi = ctx->pipe;
3765        struct command *command = ctx->command;
3766
3767#if 0   /* Instead we emit error message at run time */
3768        if (ctx->pending_redirect) {
3769                /* For example, "cmd >" (no filename to redirect to) */
3770                syntax_error("invalid redirect");
3771                ctx->pending_redirect = NULL;
3772        }
3773#endif
3774
3775        if (command) {
3776                if (IS_NULL_CMD(command)) {
3777                        debug_printf_parse("done_command: skipping null cmd, num_cmds=%d\n", pi->num_cmds);
3778                        goto clear_and_ret;
3779                }
3780                pi->num_cmds++;
3781                debug_printf_parse("done_command: ++num_cmds=%d\n", pi->num_cmds);
3782                //debug_print_tree(ctx->list_head, 20);
3783        } else {
3784                debug_printf_parse("done_command: initializing, num_cmds=%d\n", pi->num_cmds);
3785        }
3786
3787        /* Only real trickiness here is that the uncommitted
3788         * command structure is not counted in pi->num_cmds. */
3789        pi->cmds = xrealloc(pi->cmds, sizeof(*pi->cmds) * (pi->num_cmds+1));
3790        ctx->command = command = &pi->cmds[pi->num_cmds];
3791 clear_and_ret:
3792        memset(command, 0, sizeof(*command));
3793#if ENABLE_HUSH_LINENO_VAR
3794        command->lineno = G.parse_lineno;
3795        debug_printf_parse("command->lineno = G.parse_lineno (%u)\n", G.parse_lineno);
3796#endif
3797        return pi->num_cmds; /* used only for 0/nonzero check */
3798}
3799
3800static void done_pipe(struct parse_context *ctx, pipe_style type)
3801{
3802        int not_null;
3803
3804        debug_printf_parse("done_pipe entered, followup %d\n", type);
3805        /* Close previous command */
3806        not_null = done_command(ctx);
3807#if HAS_KEYWORDS
3808        ctx->pipe->pi_inverted = ctx->ctx_inverted;
3809        ctx->ctx_inverted = 0;
3810        ctx->pipe->res_word = ctx->ctx_res_w;
3811#endif
3812        if (type == PIPE_BG && ctx->list_head != ctx->pipe) {
3813                /* Necessary since && and || have precedence over &:
3814                 * "cmd1 && cmd2 &" must spawn both cmds, not only cmd2,
3815                 * in a backgrounded subshell.
3816                 */
3817                struct pipe *pi;
3818                struct command *command;
3819
3820                /* Is this actually this construct, all pipes end with && or ||? */
3821                pi = ctx->list_head;
3822                while (pi != ctx->pipe) {
3823                        if (pi->followup != PIPE_AND && pi->followup != PIPE_OR)
3824                                goto no_conv;
3825                        pi = pi->next;
3826                }
3827
3828                debug_printf_parse("BG with more than one pipe, converting to { p1 &&...pN; } &\n");
3829                pi->followup = PIPE_SEQ; /* close pN _not_ with "&"! */
3830                pi = xzalloc(sizeof(*pi));
3831                pi->followup = PIPE_BG;
3832                pi->num_cmds = 1;
3833                pi->cmds = xzalloc(sizeof(pi->cmds[0]));
3834                command = &pi->cmds[0];
3835                if (CMD_NORMAL != 0) /* "if xzalloc didn't do that already" */
3836                        command->cmd_type = CMD_NORMAL;
3837                command->group = ctx->list_head;
3838#if !BB_MMU
3839                command->group_as_string = xstrndup(
3840                            ctx->as_string.data,
3841                            ctx->as_string.length - 1 /* do not copy last char, "&" */
3842                );
3843#endif
3844                /* Replace all pipes in ctx with one newly created */
3845                ctx->list_head = ctx->pipe = pi;
3846                /* for cases like "cmd && &", do not be tricked by last command
3847                 * being null - the entire {...} & is NOT null! */
3848                not_null = 1;
3849        } else {
3850 no_conv:
3851                ctx->pipe->followup = type;
3852        }
3853
3854        /* Without this check, even just <enter> on command line generates
3855         * tree of three NOPs (!). Which is harmless but annoying.
3856         * IOW: it is safe to do it unconditionally. */
3857        if (not_null
3858#if ENABLE_HUSH_IF
3859         || ctx->ctx_res_w == RES_FI
3860#endif
3861#if ENABLE_HUSH_LOOPS
3862         || ctx->ctx_res_w == RES_DONE
3863         || ctx->ctx_res_w == RES_FOR
3864         || ctx->ctx_res_w == RES_IN
3865#endif
3866#if ENABLE_HUSH_CASE
3867         || ctx->ctx_res_w == RES_ESAC
3868#endif
3869        ) {
3870                struct pipe *new_p;
3871                debug_printf_parse("done_pipe: adding new pipe: "
3872                                "not_null:%d ctx->ctx_res_w:%d\n",
3873                                not_null, ctx->ctx_res_w);
3874                new_p = new_pipe();
3875                ctx->pipe->next = new_p;
3876                ctx->pipe = new_p;
3877                /* RES_THEN, RES_DO etc are "sticky" -
3878                 * they remain set for pipes inside if/while.
3879                 * This is used to control execution.
3880                 * RES_FOR and RES_IN are NOT sticky (needed to support
3881                 * cases where variable or value happens to match a keyword):
3882                 */
3883#if ENABLE_HUSH_LOOPS
3884                if (ctx->ctx_res_w == RES_FOR
3885                 || ctx->ctx_res_w == RES_IN)
3886                        ctx->ctx_res_w = RES_NONE;
3887#endif
3888#if ENABLE_HUSH_CASE
3889                if (ctx->ctx_res_w == RES_MATCH)
3890                        ctx->ctx_res_w = RES_CASE_BODY;
3891                if (ctx->ctx_res_w == RES_CASE)
3892                        ctx->ctx_res_w = RES_CASE_IN;
3893#endif
3894                ctx->command = NULL; /* trick done_command below */
3895                /* Create the memory for command, roughly:
3896                 * ctx->pipe->cmds = new struct command;
3897                 * ctx->command = &ctx->pipe->cmds[0];
3898                 */
3899                done_command(ctx);
3900                //debug_print_tree(ctx->list_head, 10);
3901        }
3902        debug_printf_parse("done_pipe return\n");
3903}
3904
3905static void initialize_context(struct parse_context *ctx)
3906{
3907        memset(ctx, 0, sizeof(*ctx));
3908        if (MAYBE_ASSIGNMENT != 0)
3909                ctx->is_assignment = MAYBE_ASSIGNMENT;
3910        ctx->pipe = ctx->list_head = new_pipe();
3911        /* Create the memory for command, roughly:
3912         * ctx->pipe->cmds = new struct command;
3913         * ctx->command = &ctx->pipe->cmds[0];
3914         */
3915        done_command(ctx);
3916}
3917
3918/* If a reserved word is found and processed, parse context is modified
3919 * and 1 is returned.
3920 */
3921#if HAS_KEYWORDS
3922struct reserved_combo {
3923        char literal[6];
3924        unsigned char res;
3925        unsigned char assignment_flag;
3926        uint32_t flag;
3927};
3928enum {
3929        FLAG_END   = (1 << RES_NONE ),
3930# if ENABLE_HUSH_IF
3931        FLAG_IF    = (1 << RES_IF   ),
3932        FLAG_THEN  = (1 << RES_THEN ),
3933        FLAG_ELIF  = (1 << RES_ELIF ),
3934        FLAG_ELSE  = (1 << RES_ELSE ),
3935        FLAG_FI    = (1 << RES_FI   ),
3936# endif
3937# if ENABLE_HUSH_LOOPS
3938        FLAG_FOR   = (1 << RES_FOR  ),
3939        FLAG_WHILE = (1 << RES_WHILE),
3940        FLAG_UNTIL = (1 << RES_UNTIL),
3941        FLAG_DO    = (1 << RES_DO   ),
3942        FLAG_DONE  = (1 << RES_DONE ),
3943        FLAG_IN    = (1 << RES_IN   ),
3944# endif
3945# if ENABLE_HUSH_CASE
3946        FLAG_MATCH = (1 << RES_MATCH),
3947        FLAG_ESAC  = (1 << RES_ESAC ),
3948# endif
3949        FLAG_START = (1 << RES_XXXX ),
3950};
3951
3952static const struct reserved_combo* match_reserved_word(o_string *word)
3953{
3954        /* Mostly a list of accepted follow-up reserved words.
3955         * FLAG_END means we are done with the sequence, and are ready
3956         * to turn the compound list into a command.
3957         * FLAG_START means the word must start a new compound list.
3958         */
3959        static const struct reserved_combo reserved_list[] ALIGN4 = {
3960# if ENABLE_HUSH_IF
3961                { "!",     RES_NONE,  NOT_ASSIGNMENT  , 0 },
3962                { "if",    RES_IF,    MAYBE_ASSIGNMENT, FLAG_THEN | FLAG_START },
3963                { "then",  RES_THEN,  MAYBE_ASSIGNMENT, FLAG_ELIF | FLAG_ELSE | FLAG_FI },
3964                { "elif",  RES_ELIF,  MAYBE_ASSIGNMENT, FLAG_THEN },
3965                { "else",  RES_ELSE,  MAYBE_ASSIGNMENT, FLAG_FI   },
3966                { "fi",    RES_FI,    NOT_ASSIGNMENT  , FLAG_END  },
3967# endif
3968# if ENABLE_HUSH_LOOPS
3969                { "for",   RES_FOR,   NOT_ASSIGNMENT  , FLAG_IN | FLAG_DO | FLAG_START },
3970                { "while", RES_WHILE, MAYBE_ASSIGNMENT, FLAG_DO | FLAG_START },
3971                { "until", RES_UNTIL, MAYBE_ASSIGNMENT, FLAG_DO | FLAG_START },
3972                { "in",    RES_IN,    NOT_ASSIGNMENT  , FLAG_DO   },
3973                { "do",    RES_DO,    MAYBE_ASSIGNMENT, FLAG_DONE },
3974                { "done",  RES_DONE,  NOT_ASSIGNMENT  , FLAG_END  },
3975# endif
3976# if ENABLE_HUSH_CASE
3977                { "case",  RES_CASE,  NOT_ASSIGNMENT  , FLAG_MATCH | FLAG_START },
3978                { "esac",  RES_ESAC,  NOT_ASSIGNMENT  , FLAG_END  },
3979# endif
3980        };
3981        const struct reserved_combo *r;
3982
3983        for (r = reserved_list; r < reserved_list + ARRAY_SIZE(reserved_list); r++) {
3984                if (strcmp(word->data, r->literal) == 0)
3985                        return r;
3986        }
3987        return NULL;
3988}
3989/* Return NULL: not a keyword, else: keyword
3990 */
3991static const struct reserved_combo* reserved_word(struct parse_context *ctx)
3992{
3993# if ENABLE_HUSH_CASE
3994        static const struct reserved_combo reserved_match = {
3995                "",        RES_MATCH, NOT_ASSIGNMENT , FLAG_MATCH | FLAG_ESAC
3996        };
3997# endif
3998        const struct reserved_combo *r;
3999
4000        if (ctx->word.has_quoted_part)
4001                return 0;
4002        r = match_reserved_word(&ctx->word);
4003        if (!r)
4004                return r; /* NULL */
4005
4006        debug_printf("found reserved word %s, res %d\n", r->literal, r->res);
4007# if ENABLE_HUSH_CASE
4008        if (r->res == RES_IN && ctx->ctx_res_w == RES_CASE_IN) {
4009                /* "case word IN ..." - IN part starts first MATCH part */
4010                r = &reserved_match;
4011        } else
4012# endif
4013        if (r->flag == 0) { /* '!' */
4014                if (ctx->ctx_inverted) { /* bash doesn't accept '! ! true' */
4015                        syntax_error("! ! command");
4016                        ctx->ctx_res_w = RES_SNTX;
4017                }
4018                ctx->ctx_inverted = 1;
4019                return r;
4020        }
4021        if (r->flag & FLAG_START) {
4022                struct parse_context *old;
4023
4024                old = xmemdup(ctx, sizeof(*ctx));
4025                debug_printf_parse("push stack %p\n", old);
4026                initialize_context(ctx);
4027                ctx->stack = old;
4028        } else if (/*ctx->ctx_res_w == RES_NONE ||*/ !(ctx->old_flag & (1 << r->res))) {
4029                syntax_error_at(ctx->word.data);
4030                ctx->ctx_res_w = RES_SNTX;
4031                return r;
4032        } else {
4033                /* "{...} fi" is ok. "{...} if" is not
4034                 * Example:
4035                 * if { echo foo; } then { echo bar; } fi */
4036                if (ctx->command->group)
4037                        done_pipe(ctx, PIPE_SEQ);
4038        }
4039
4040        ctx->ctx_res_w = r->res;
4041        ctx->old_flag = r->flag;
4042        ctx->is_assignment = r->assignment_flag;
4043        debug_printf_parse("ctx->is_assignment='%s'\n", assignment_flag[ctx->is_assignment]);
4044
4045        if (ctx->old_flag & FLAG_END) {
4046                struct parse_context *old;
4047
4048                done_pipe(ctx, PIPE_SEQ);
4049                debug_printf_parse("pop stack %p\n", ctx->stack);
4050                old = ctx->stack;
4051                old->command->group = ctx->list_head;
4052                old->command->cmd_type = CMD_NORMAL;
4053# if !BB_MMU
4054                /* At this point, the compound command's string is in
4055                 * ctx->as_string... except for the leading keyword!
4056                 * Consider this example: "echo a | if true; then echo a; fi"
4057                 * ctx->as_string will contain "true; then echo a; fi",
4058                 * with "if " remaining in old->as_string!
4059                 */
4060                {
4061                        char *str;
4062                        int len = old->as_string.length;
4063                        /* Concatenate halves */
4064                        o_addstr(&old->as_string, ctx->as_string.data);
4065                        o_free(&ctx->as_string);
4066                        /* Find where leading keyword starts in first half */
4067                        str = old->as_string.data + len;
4068                        if (str > old->as_string.data)
4069                                str--; /* skip whitespace after keyword */
4070                        while (str > old->as_string.data && isalpha(str[-1]))
4071                                str--;
4072                        /* Ugh, we're done with this horrid hack */
4073                        old->command->group_as_string = xstrdup(str);
4074                        debug_printf_parse("pop, remembering as:'%s'\n",
4075                                        old->command->group_as_string);
4076                }
4077# endif
4078                *ctx = *old;   /* physical copy */
4079                free(old);
4080        }
4081        return r;
4082}
4083#endif /* HAS_KEYWORDS */
4084
4085/* Word is complete, look at it and update parsing context.
4086 * Normal return is 0. Syntax errors return 1.
4087 * Note: on return, word is reset, but not o_free'd!
4088 */
4089static int done_word(struct parse_context *ctx)
4090{
4091        struct command *command = ctx->command;
4092
4093        debug_printf_parse("done_word entered: '%s' %p\n", ctx->word.data, command);
4094        if (ctx->word.length == 0 && !ctx->word.has_quoted_part) {
4095                debug_printf_parse("done_word return 0: true null, ignored\n");
4096                return 0;
4097        }
4098
4099        if (ctx->pending_redirect) {
4100                /* We do not glob in e.g. >*.tmp case. bash seems to glob here
4101                 * only if run as "bash", not "sh" */
4102                /* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
4103                 * "2.7 Redirection
4104                 * If the redirection operator is "<<" or "<<-", the word
4105                 * that follows the redirection operator shall be
4106                 * subjected to quote removal; it is unspecified whether
4107                 * any of the other expansions occur. For the other
4108                 * redirection operators, the word that follows the
4109                 * redirection operator shall be subjected to tilde
4110                 * expansion, parameter expansion, command substitution,
4111                 * arithmetic expansion, and quote removal.
4112                 * Pathname expansion shall not be performed
4113                 * on the word by a non-interactive shell; an interactive
4114                 * shell may perform it, but shall do so only when
4115                 * the expansion would result in one word."
4116                 */
4117//bash does not do parameter/command substitution or arithmetic expansion
4118//for _heredoc_ redirection word: these constructs look for exact eof marker
4119// as written:
4120// <<EOF$t
4121// <<EOF$((1))
4122// <<EOF`true`  [this case also makes heredoc "quoted", a-la <<"EOF". Probably bash-4.3.43 bug]
4123
4124                ctx->pending_redirect->rd_filename = xstrdup(ctx->word.data);
4125                /* Cater for >\file case:
4126                 * >\a creates file a; >\\a, >"\a", >"\\a" create file \a
4127                 * Same with heredocs:
4128                 * for <<\H delim is H; <<\\H, <<"\H", <<"\\H" - \H
4129                 */
4130                if (ctx->pending_redirect->rd_type == REDIRECT_HEREDOC) {
4131                        unbackslash(ctx->pending_redirect->rd_filename);
4132                        /* Is it <<"HEREDOC"? */
4133                        if (ctx->word.has_quoted_part) {
4134                                ctx->pending_redirect->rd_dup |= HEREDOC_QUOTED;
4135                        }
4136                }
4137                debug_printf_parse("word stored in rd_filename: '%s'\n", ctx->word.data);
4138                ctx->pending_redirect = NULL;
4139        } else {
4140#if HAS_KEYWORDS
4141# if ENABLE_HUSH_CASE
4142                if (ctx->ctx_dsemicolon
4143                 && strcmp(ctx->word.data, "esac") != 0 /* not "... pattern) cmd;; esac" */
4144                ) {
4145                        /* already done when ctx_dsemicolon was set to 1: */
4146                        /* ctx->ctx_res_w = RES_MATCH; */
4147                        ctx->ctx_dsemicolon = 0;
4148                } else
4149# endif
4150# if defined(CMD_TEST2_SINGLEWORD_NOGLOB)
4151                if (command->cmd_type == CMD_TEST2_SINGLEWORD_NOGLOB
4152                 && strcmp(ctx->word.data, "]]") == 0
4153                ) {
4154                        /* allow "[[ ]] >file" etc */
4155                        command->cmd_type = CMD_SINGLEWORD_NOGLOB;
4156                } else
4157# endif
4158                if (!command->argv /* if it's the first word... */
4159# if ENABLE_HUSH_LOOPS
4160                 && ctx->ctx_res_w != RES_FOR /* ...not after FOR or IN */
4161                 && ctx->ctx_res_w != RES_IN
4162# endif
4163# if ENABLE_HUSH_CASE
4164                 && ctx->ctx_res_w != RES_CASE
4165# endif
4166                ) {
4167                        const struct reserved_combo *reserved;
4168                        reserved = reserved_word(ctx);
4169                        debug_printf_parse("checking for reserved-ness: %d\n", !!reserved);
4170                        if (reserved) {
4171# if ENABLE_HUSH_LINENO_VAR
4172/* Case:
4173 * "while ...; do
4174 *      cmd ..."
4175 * If we don't close the pipe _now_, immediately after "do", lineno logic
4176 * sees "cmd" as starting at "do" - i.e., at the previous line.
4177 */
4178                                if (0
4179                                 IF_HUSH_IF(|| reserved->res == RES_THEN)
4180                                 IF_HUSH_IF(|| reserved->res == RES_ELIF)
4181                                 IF_HUSH_IF(|| reserved->res == RES_ELSE)
4182                                 IF_HUSH_LOOPS(|| reserved->res == RES_DO)
4183                                ) {
4184                                        done_pipe(ctx, PIPE_SEQ);
4185                                }
4186# endif
4187                                o_reset_to_empty_unquoted(&ctx->word);
4188                                debug_printf_parse("done_word return %d\n",
4189                                                (ctx->ctx_res_w == RES_SNTX));
4190                                return (ctx->ctx_res_w == RES_SNTX);
4191                        }
4192# if defined(CMD_TEST2_SINGLEWORD_NOGLOB)
4193                        if (strcmp(ctx->word.data, "[[") == 0) {
4194                                command->cmd_type = CMD_TEST2_SINGLEWORD_NOGLOB;
4195                        } else
4196# endif
4197# if defined(CMD_SINGLEWORD_NOGLOB)
4198                        if (0
4199                        /* In bash, local/export/readonly are special, args
4200                         * are assignments and therefore expansion of them
4201                         * should be "one-word" expansion:
4202                         *  $ export i=`echo 'a  b'` # one arg: "i=a  b"
4203                         * compare with:
4204                         *  $ ls i=`echo 'a  b'`     # two args: "i=a" and "b"
4205                         *  ls: cannot access i=a: No such file or directory
4206                         *  ls: cannot access b: No such file or directory
4207                         * Note: bash 3.2.33(1) does this only if export word
4208                         * itself is not quoted:
4209                         *  $ export i=`echo 'aaa  bbb'`; echo "$i"
4210                         *  aaa  bbb
4211                         *  $ "export" i=`echo 'aaa  bbb'`; echo "$i"
4212                         *  aaa
4213                         */
4214                         IF_HUSH_LOCAL(   || strcmp(ctx->word.data, "local") == 0)
4215                         IF_HUSH_EXPORT(  || strcmp(ctx->word.data, "export") == 0)
4216                         IF_HUSH_READONLY(|| strcmp(ctx->word.data, "readonly") == 0)
4217                        ) {
4218                                command->cmd_type = CMD_SINGLEWORD_NOGLOB;
4219                        }
4220# else
4221                        { /* empty block to pair "if ... else" */ }
4222# endif
4223                }
4224#endif /* HAS_KEYWORDS */
4225
4226                if (command->group) {
4227                        /* "{ echo foo; } echo bar" - bad */
4228                        syntax_error_at(ctx->word.data);
4229                        debug_printf_parse("done_word return 1: syntax error, "
4230                                        "groups and arglists don't mix\n");
4231                        return 1;
4232                }
4233
4234                /* If this word wasn't an assignment, next ones definitely
4235                 * can't be assignments. Even if they look like ones. */
4236                if (ctx->is_assignment != DEFINITELY_ASSIGNMENT
4237                 && ctx->is_assignment != WORD_IS_KEYWORD
4238                ) {
4239                        ctx->is_assignment = NOT_ASSIGNMENT;
4240                } else {
4241                        if (ctx->is_assignment == DEFINITELY_ASSIGNMENT) {
4242                                command->assignment_cnt++;
4243                                debug_printf_parse("++assignment_cnt=%d\n", command->assignment_cnt);
4244                        }
4245                        debug_printf_parse("ctx->is_assignment was:'%s'\n", assignment_flag[ctx->is_assignment]);
4246                        ctx->is_assignment = MAYBE_ASSIGNMENT;
4247                }
4248                debug_printf_parse("ctx->is_assignment='%s'\n", assignment_flag[ctx->is_assignment]);
4249                command->argv = add_string_to_strings(command->argv, xstrdup(ctx->word.data));
4250                debug_print_strings("word appended to argv", command->argv);
4251        }
4252
4253#if ENABLE_HUSH_LOOPS
4254        if (ctx->ctx_res_w == RES_FOR) {
4255                if (ctx->word.has_quoted_part
4256                 || endofname(command->argv[0])[0] != '\0'
4257                ) {
4258                        /* bash says just "not a valid identifier" */
4259                        syntax_error("bad variable name in for");
4260                        return 1;
4261                }
4262                /* Force FOR to have just one word (variable name) */
4263                /* NB: basically, this makes hush see "for v in ..."
4264                 * syntax as if it is "for v; in ...". FOR and IN become
4265                 * two pipe structs in parse tree. */
4266                done_pipe(ctx, PIPE_SEQ);
4267        }
4268#endif
4269#if ENABLE_HUSH_CASE
4270        /* Force CASE to have just one word */
4271        if (ctx->ctx_res_w == RES_CASE) {
4272                done_pipe(ctx, PIPE_SEQ);
4273        }
4274#endif
4275
4276        o_reset_to_empty_unquoted(&ctx->word);
4277
4278        debug_printf_parse("done_word return 0\n");
4279        return 0;
4280}
4281
4282
4283/* Peek ahead in the input to find out if we have a "&n" construct,
4284 * as in "2>&1", that represents duplicating a file descriptor.
4285 * Return:
4286 * REDIRFD_CLOSE if >&- "close fd" construct is seen,
4287 * REDIRFD_SYNTAX_ERR if syntax error,
4288 * REDIRFD_TO_FILE if no & was seen,
4289 * or the number found.
4290 */
4291#if BB_MMU
4292#define parse_redir_right_fd(as_string, input) \
4293        parse_redir_right_fd(input)
4294#endif
4295static int parse_redir_right_fd(o_string *as_string, struct in_str *input)
4296{
4297        int ch, d, ok;
4298
4299        ch = i_peek(input);
4300        if (ch != '&')
4301                return REDIRFD_TO_FILE;
4302
4303        ch = i_getch(input);  /* get the & */
4304        nommu_addchr(as_string, ch);
4305        ch = i_peek(input);
4306        if (ch == '-') {
4307                ch = i_getch(input);
4308                nommu_addchr(as_string, ch);
4309                return REDIRFD_CLOSE;
4310        }
4311        d = 0;
4312        ok = 0;
4313        while (ch != EOF && isdigit(ch)) {
4314                d = d*10 + (ch-'0');
4315                ok = 1;
4316                ch = i_getch(input);
4317                nommu_addchr(as_string, ch);
4318                ch = i_peek(input);
4319        }
4320        if (ok) return d;
4321
4322//TODO: this is the place to catch ">&file" bashism (redirect both fd 1 and 2)
4323
4324        bb_simple_error_msg("ambiguous redirect");
4325        return REDIRFD_SYNTAX_ERR;
4326}
4327
4328/* Return code is 0 normal, 1 if a syntax error is detected
4329 */
4330static int parse_redirect(struct parse_context *ctx,
4331                int fd,
4332                redir_type style,
4333                struct in_str *input)
4334{
4335        struct command *command = ctx->command;
4336        struct redir_struct *redir;
4337        struct redir_struct **redirp;
4338        int dup_num;
4339
4340        dup_num = REDIRFD_TO_FILE;
4341        if (style != REDIRECT_HEREDOC) {
4342                /* Check for a '>&1' type redirect */
4343                dup_num = parse_redir_right_fd(&ctx->as_string, input);
4344                if (dup_num == REDIRFD_SYNTAX_ERR)
4345                        return 1;
4346        } else {
4347                int ch = i_peek_and_eat_bkslash_nl(input);
4348                dup_num = (ch == '-'); /* HEREDOC_SKIPTABS bit is 1 */
4349                if (dup_num) { /* <<-... */
4350                        ch = i_getch(input);
4351                        nommu_addchr(&ctx->as_string, ch);
4352                        ch = i_peek(input);
4353                }
4354        }
4355
4356        if (style == REDIRECT_OVERWRITE && dup_num == REDIRFD_TO_FILE) {
4357                int ch = i_peek_and_eat_bkslash_nl(input);
4358                if (ch == '|') {
4359                        /* >|FILE redirect ("clobbering" >).
4360                         * Since we do not support "set -o noclobber" yet,
4361                         * >| and > are the same for now. Just eat |.
4362                         */
4363                        ch = i_getch(input);
4364                        nommu_addchr(&ctx->as_string, ch);
4365                }
4366        }
4367
4368        /* Create a new redir_struct and append it to the linked list */
4369        redirp = &command->redirects;
4370        while ((redir = *redirp) != NULL) {
4371                redirp = &(redir->next);
4372        }
4373        *redirp = redir = xzalloc(sizeof(*redir));
4374        /* redir->next = NULL; */
4375        /* redir->rd_filename = NULL; */
4376        redir->rd_type = style;
4377        redir->rd_fd = (fd == -1) ? redir_table[style].default_fd : fd;
4378
4379        debug_printf_parse("redirect type %d %s\n", redir->rd_fd,
4380                                redir_table[style].descrip);
4381
4382        redir->rd_dup = dup_num;
4383        if (style != REDIRECT_HEREDOC && dup_num != REDIRFD_TO_FILE) {
4384                /* Erik had a check here that the file descriptor in question
4385                 * is legit; I postpone that to "run time"
4386                 * A "-" representation of "close me" shows up as a -3 here */
4387                debug_printf_parse("duplicating redirect '%d>&%d'\n",
4388                                redir->rd_fd, redir->rd_dup);
4389        } else {
4390#if 0           /* Instead we emit error message at run time */
4391                if (ctx->pending_redirect) {
4392                        /* For example, "cmd > <file" */
4393                        syntax_error("invalid redirect");
4394                }
4395#endif
4396                /* Set ctx->pending_redirect, so we know what to do at the
4397                 * end of the next parsed word. */
4398                ctx->pending_redirect = redir;
4399        }
4400        return 0;
4401}
4402
4403/* If a redirect is immediately preceded by a number, that number is
4404 * supposed to tell which file descriptor to redirect.  This routine
4405 * looks for such preceding numbers.  In an ideal world this routine
4406 * needs to handle all the following classes of redirects...
4407 *     echo 2>foo     # redirects fd  2 to file "foo", nothing passed to echo
4408 *     echo 49>foo    # redirects fd 49 to file "foo", nothing passed to echo
4409 *     echo -2>foo    # redirects fd  1 to file "foo",    "-2" passed to echo
4410 *     echo 49x>foo   # redirects fd  1 to file "foo",   "49x" passed to echo
4411 *
4412 * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
4413 * "2.7 Redirection
4414 * ... If n is quoted, the number shall not be recognized as part of
4415 * the redirection expression. For example:
4416 * echo \2>a
4417 * writes the character 2 into file a"
4418 * We are getting it right by setting ->has_quoted_part on any \<char>
4419 *
4420 * A -1 return means no valid number was found,
4421 * the caller should use the appropriate default for this redirection.
4422 */
4423static int redirect_opt_num(o_string *o)
4424{
4425        int num;
4426
4427        if (o->data == NULL)
4428                return -1;
4429        num = bb_strtou(o->data, NULL, 10);
4430        if (errno || num < 0)
4431                return -1;
4432        o_reset_to_empty_unquoted(o);
4433        return num;
4434}
4435
4436#if BB_MMU
4437#define fetch_till_str(as_string, input, word, skip_tabs) \
4438        fetch_till_str(input, word, skip_tabs)
4439#endif
4440static char *fetch_till_str(o_string *as_string,
4441                struct in_str *input,
4442                const char *word,
4443                int heredoc_flags)
4444{
4445        o_string heredoc = NULL_O_STRING;
4446        unsigned past_EOL;
4447        int prev = 0; /* not \ */
4448        int ch;
4449
4450        /* Starting with "" is necessary for this case:
4451         * cat <<EOF
4452         *
4453         * xxx
4454         * EOF
4455         */
4456        heredoc.data = xzalloc(1); /* start as "", not as NULL */
4457
4458        goto jump_in;
4459
4460        while (1) {
4461                ch = i_getch(input);
4462                if (ch != EOF)
4463                        nommu_addchr(as_string, ch);
4464                if (ch == '\n' || ch == EOF) {
4465 check_heredoc_end:
4466                        if ((heredoc_flags & HEREDOC_QUOTED) || prev != '\\') {
4467                                /* End-of-line, and not a line continuation */
4468                                if (strcmp(heredoc.data + past_EOL, word) == 0) {
4469                                        heredoc.data[past_EOL] = '\0';
4470                                        debug_printf_heredoc("parsed '%s' heredoc '%s'\n", word, heredoc.data);
4471                                        return heredoc.data;
4472                                }
4473                                if (ch == '\n') {
4474                                        /* This is a new line.
4475                                         * Remember position and backslash-escaping status.
4476                                         */
4477                                        o_addchr(&heredoc, ch);
4478                                        prev = ch;
4479 jump_in:
4480                                        past_EOL = heredoc.length;
4481                                        /* Get 1st char of next line, possibly skipping leading tabs */
4482                                        do {
4483                                                ch = i_getch(input);
4484                                                if (ch != EOF)
4485                                                        nommu_addchr(as_string, ch);
4486                                        } while ((heredoc_flags & HEREDOC_SKIPTABS) && ch == '\t');
4487                                        /* If this immediately ended the line,
4488                                         * go back to end-of-line checks.
4489                                         */
4490                                        if (ch == '\n')
4491                                                goto check_heredoc_end;
4492                                }
4493                        } else {
4494                                /* Backslash-line continuation in an unquoted
4495                                 * heredoc. This does not need special handling
4496                                 * for heredoc body (unquoted heredocs are
4497                                 * expanded on "execution" and that would take
4498                                 * care of this case too), but not the case
4499                                 * of line continuation *in terminator*:
4500                                 *  cat <<EOF
4501                                 *  Ok1
4502                                 *  EO\
4503                                 *  F
4504                                 */
4505                                heredoc.data[--heredoc.length] = '\0';
4506                                prev = 0; /* not '\' */
4507                                continue;
4508                        }
4509                }
4510                if (ch == EOF) {
4511                        o_free(&heredoc);
4512                        return NULL; /* error */
4513                }
4514                o_addchr(&heredoc, ch);
4515                nommu_addchr(as_string, ch);
4516                if (prev == '\\' && ch == '\\')
4517                        /* Correctly handle foo\\<eol> (not a line cont.) */
4518                        prev = 0; /* not '\' */
4519                else
4520                        prev = ch;
4521        }
4522}
4523
4524/* Look at entire parse tree for not-yet-loaded REDIRECT_HEREDOCs
4525 * and load them all. There should be exactly heredoc_cnt of them.
4526 */
4527#if BB_MMU
4528#define fetch_heredocs(as_string, pi, heredoc_cnt, input) \
4529        fetch_heredocs(pi, heredoc_cnt, input)
4530#endif
4531static int fetch_heredocs(o_string *as_string, struct pipe *pi, int heredoc_cnt, struct in_str *input)
4532{
4533        while (pi && heredoc_cnt) {
4534                int i;
4535                struct command *cmd = pi->cmds;
4536
4537                debug_printf_heredoc("fetch_heredocs: num_cmds:%d cmd argv0:'%s'\n",
4538                                pi->num_cmds,
4539                                cmd->argv ? cmd->argv[0] : "NONE"
4540                );
4541                for (i = 0; i < pi->num_cmds; i++) {
4542                        struct redir_struct *redir = cmd->redirects;
4543
4544                        debug_printf_heredoc("fetch_heredocs: %d cmd argv0:'%s'\n",
4545                                        i, cmd->argv ? cmd->argv[0] : "NONE");
4546                        while (redir) {
4547                                if (redir->rd_type == REDIRECT_HEREDOC) {
4548                                        char *p;
4549
4550                                        redir->rd_type = REDIRECT_HEREDOC2;
4551                                        /* redir->rd_dup is (ab)used to indicate <<- */
4552                                        p = fetch_till_str(as_string, input,
4553                                                        redir->rd_filename, redir->rd_dup);
4554                                        if (!p) {
4555                                                syntax_error("unexpected EOF in here document");
4556                                                return -1;
4557                                        }
4558                                        free(redir->rd_filename);
4559                                        redir->rd_filename = p;
4560                                        heredoc_cnt--;
4561                                }
4562                                redir = redir->next;
4563                        }
4564                        if (cmd->group) {
4565                                //bb_error_msg("%s:%u heredoc_cnt:%d", __func__, __LINE__, heredoc_cnt);
4566                                heredoc_cnt = fetch_heredocs(as_string, cmd->group, heredoc_cnt, input);
4567                                //bb_error_msg("%s:%u heredoc_cnt:%d", __func__, __LINE__, heredoc_cnt);
4568                                if (heredoc_cnt < 0)
4569                                        return heredoc_cnt; /* error */
4570                        }
4571                        cmd++;
4572                }
4573                pi = pi->next;
4574        }
4575        return heredoc_cnt;
4576}
4577
4578
4579static int run_list(struct pipe *pi);
4580#if BB_MMU
4581#define parse_stream(pstring, heredoc_cnt_ptr, input, end_trigger) \
4582        parse_stream(heredoc_cnt_ptr, input, end_trigger)
4583#endif
4584static struct pipe *parse_stream(char **pstring,
4585                int *heredoc_cnt_ptr,
4586                struct in_str *input,
4587                int end_trigger);
4588
4589/* Returns number of heredocs not yet consumed,
4590 * or -1 on error.
4591 */
4592static int parse_group(struct parse_context *ctx,
4593                struct in_str *input, int ch)
4594{
4595        /* ctx->word contains characters seen prior to ( or {.
4596         * Typically it's empty, but for function defs,
4597         * it contains function name (without '()'). */
4598#if BB_MMU
4599# define as_string NULL
4600#else
4601        char *as_string = NULL;
4602#endif
4603        struct pipe *pipe_list;
4604        int heredoc_cnt = 0;
4605        int endch;
4606        struct command *command = ctx->command;
4607
4608        debug_printf_parse("parse_group entered\n");
4609#if ENABLE_HUSH_FUNCTIONS
4610        if (ch == '(' && !ctx->word.has_quoted_part) {
4611                if (ctx->word.length)
4612                        if (done_word(ctx))
4613                                return -1;
4614                if (!command->argv)
4615                        goto skip; /* (... */
4616                if (command->argv[1]) { /* word word ... (... */
4617                        syntax_error_unexpected_ch('(');
4618                        return -1;
4619                }
4620                /* it is "word(..." or "word (..." */
4621                do
4622                        ch = i_getch(input);
4623                while (ch == ' ' || ch == '\t');
4624                if (ch != ')') {
4625                        syntax_error_unexpected_ch(ch);
4626                        return -1;
4627                }
4628                nommu_addchr(&ctx->as_string, ch);
4629                do
4630                        ch = i_getch(input);
4631                while (ch == ' ' || ch == '\t' || ch == '\n');
4632                if (ch != '{' && ch != '(') {
4633                        syntax_error_unexpected_ch(ch);
4634                        return -1;
4635                }
4636                nommu_addchr(&ctx->as_string, ch);
4637                command->cmd_type = CMD_FUNCDEF;
4638                goto skip;
4639        }
4640#endif
4641
4642#if 0 /* Prevented by caller */
4643        if (command->argv /* word [word]{... */
4644         || ctx->word.length /* word{... */
4645         || ctx->word.has_quoted_part /* ""{... */
4646        ) {
4647                syntax_error(NULL);
4648                debug_printf_parse("parse_group return -1: "
4649                        "syntax error, groups and arglists don't mix\n");
4650                return -1;
4651        }
4652#endif
4653
4654 IF_HUSH_FUNCTIONS(skip:)
4655
4656        endch = '}';
4657        if (ch == '(') {
4658                endch = ')';
4659                IF_HUSH_FUNCTIONS(if (command->cmd_type != CMD_FUNCDEF))
4660                        command->cmd_type = CMD_SUBSHELL;
4661        } else {
4662                /* bash does not allow "{echo...", requires whitespace */
4663                ch = i_peek(input);
4664                if (ch != ' ' && ch != '\t' && ch != '\n'
4665                 && ch != '('   /* but "{(..." is allowed (without whitespace) */
4666                ) {
4667                        syntax_error_unexpected_ch(ch);
4668                        return -1;
4669                }
4670                if (ch != '(') {
4671                        ch = i_getch(input);
4672                        nommu_addchr(&ctx->as_string, ch);
4673                }
4674        }
4675
4676        debug_printf_heredoc("calling parse_stream, heredoc_cnt:%d\n", heredoc_cnt);
4677        pipe_list = parse_stream(&as_string, &heredoc_cnt, input, endch);
4678        debug_printf_heredoc("parse_stream returned: heredoc_cnt:%d\n", heredoc_cnt);
4679#if !BB_MMU
4680        if (as_string)
4681                o_addstr(&ctx->as_string, as_string);
4682#endif
4683
4684        /* empty ()/{} or parse error? */
4685        if (!pipe_list || pipe_list == ERR_PTR) {
4686                /* parse_stream already emitted error msg */
4687                if (!BB_MMU)
4688                        free(as_string);
4689                debug_printf_parse("parse_group return -1: "
4690                        "parse_stream returned %p\n", pipe_list);
4691                return -1;
4692        }
4693#if !BB_MMU
4694        as_string[strlen(as_string) - 1] = '\0'; /* plink ')' or '}' */
4695        command->group_as_string = as_string;
4696        debug_printf_parse("end of group, remembering as:'%s'\n",
4697                        command->group_as_string);
4698#endif
4699
4700#if ENABLE_HUSH_FUNCTIONS
4701        /* Convert "f() (cmds)" to "f() {(cmds)}" */
4702        if (command->cmd_type == CMD_FUNCDEF && endch == ')') {
4703                struct command *cmd2;
4704
4705                cmd2 = xzalloc(sizeof(*cmd2));
4706                cmd2->cmd_type = CMD_SUBSHELL;
4707                cmd2->group = pipe_list;
4708# if !BB_MMU
4709//UNTESTED!
4710                cmd2->group_as_string = command->group_as_string;
4711                command->group_as_string = xasprintf("(%s)", command->group_as_string);
4712# endif
4713
4714                pipe_list = new_pipe();
4715                pipe_list->cmds = cmd2;
4716                pipe_list->num_cmds = 1;
4717        }
4718#endif
4719
4720        command->group = pipe_list;
4721
4722        debug_printf_parse("parse_group return %d\n", heredoc_cnt);
4723        return heredoc_cnt;
4724        /* command remains "open", available for possible redirects */
4725#undef as_string
4726}
4727
4728#if ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS
4729/* Subroutines for copying $(...) and `...` things */
4730/* '...' */
4731static int add_till_single_quote(o_string *dest, struct in_str *input)
4732{
4733        while (1) {
4734                int ch = i_getch(input);
4735                if (ch == EOF) {
4736                        syntax_error_unterm_ch('\'');
4737                        return 0;
4738                }
4739                if (ch == '\'')
4740                        return 1;
4741                o_addchr(dest, ch);
4742        }
4743}
4744static int add_till_single_quote_dquoted(o_string *dest, struct in_str *input)
4745{
4746        while (1) {
4747                int ch = i_getch(input);
4748                if (ch == EOF) {
4749                        syntax_error_unterm_ch('\'');
4750                        return 0;
4751                }
4752                if (ch == '\'')
4753                        return 1;
4754                o_addqchr(dest, ch);
4755        }
4756}
4757/* "...\"...`..`...." - do we need to handle "...$(..)..." too? */
4758static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote);
4759static int add_till_double_quote(o_string *dest, struct in_str *input)
4760{
4761        while (1) {
4762                int ch = i_getch(input);
4763                if (ch == EOF) {
4764                        syntax_error_unterm_ch('"');
4765                        return 0;
4766                }
4767                if (ch == '"')
4768                        return 1;
4769                if (ch == '\\') {  /* \x. Copy both chars. */
4770                        o_addchr(dest, ch);
4771                        ch = i_getch(input);
4772                }
4773                o_addchr(dest, ch);
4774                if (ch == '`') {
4775                        if (!add_till_backquote(dest, input, /*in_dquote:*/ 1))
4776                                return 0;
4777                        o_addchr(dest, ch);
4778                        continue;
4779                }
4780                //if (ch == '$') ...
4781        }
4782}
4783/* Process `cmd` - copy contents until "`" is seen. Complicated by
4784 * \` quoting.
4785 * "Within the backquoted style of command substitution, backslash
4786 * shall retain its literal meaning, except when followed by: '$', '`', or '\'.
4787 * The search for the matching backquote shall be satisfied by the first
4788 * backquote found without a preceding backslash; during this search,
4789 * if a non-escaped backquote is encountered within a shell comment,
4790 * a here-document, an embedded command substitution of the $(command)
4791 * form, or a quoted string, undefined results occur. A single-quoted
4792 * or double-quoted string that begins, but does not end, within the
4793 * "`...`" sequence produces undefined results."
4794 * Example                               Output
4795 * echo `echo '\'TEST\`echo ZZ\`BEST`    \TESTZZBEST
4796 */
4797static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote)
4798{
4799        while (1) {
4800                int ch = i_getch(input);
4801                if (ch == '`')
4802                        return 1;
4803                if (ch == '\\') {
4804                        /* \x. Copy both unless it is \`, \$, \\ and maybe \" */
4805                        ch = i_getch(input);
4806                        if (ch != '`'
4807                         && ch != '$'
4808                         && ch != '\\'
4809                         && (!in_dquote || ch != '"')
4810                        ) {
4811                                o_addchr(dest, '\\');
4812                        }
4813                }
4814                if (ch == EOF) {
4815                        syntax_error_unterm_ch('`');
4816                        return 0;
4817                }
4818                o_addchr(dest, ch);
4819        }
4820}
4821/* Process $(cmd) - copy contents until ")" is seen. Complicated by
4822 * quoting and nested ()s.
4823 * "With the $(command) style of command substitution, all characters
4824 * following the open parenthesis to the matching closing parenthesis
4825 * constitute the command. Any valid shell script can be used for command,
4826 * except a script consisting solely of redirections which produces
4827 * unspecified results."
4828 * Example                              Output
4829 * echo $(echo '(TEST)' BEST)           (TEST) BEST
4830 * echo $(echo 'TEST)' BEST)            TEST) BEST
4831 * echo $(echo \(\(TEST\) BEST)         ((TEST) BEST
4832 *
4833 * Also adapted to eat ${var%...} and $((...)) constructs, since ... part
4834 * can contain arbitrary constructs, just like $(cmd).
4835 * In bash compat mode, it needs to also be able to stop on ':' or '/'
4836 * for ${var:N[:M]} and ${var/P[/R]} parsing.
4837 */
4838#define DOUBLE_CLOSE_CHAR_FLAG 0x80
4839static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsigned end_ch)
4840{
4841        int ch;
4842        char dbl = end_ch & DOUBLE_CLOSE_CHAR_FLAG;
4843# if BASH_SUBSTR || BASH_PATTERN_SUBST
4844        char end_char2 = end_ch >> 8;
4845# endif
4846        end_ch &= (DOUBLE_CLOSE_CHAR_FLAG - 1);
4847
4848# if ENABLE_HUSH_INTERACTIVE
4849        G.promptmode = 1; /* PS2 */
4850# endif
4851        debug_printf_prompt("%s promptmode=%d\n", __func__, G.promptmode);
4852
4853        while (1) {
4854                ch = i_getch(input);
4855                if (ch == EOF) {
4856                        syntax_error_unterm_ch(end_ch);
4857                        return 0;
4858                }
4859                if (ch == end_ch
4860# if BASH_SUBSTR || BASH_PATTERN_SUBST
4861                 || ch == end_char2
4862# endif
4863                ) {
4864                        if (!dbl)
4865                                break;
4866                        /* we look for closing )) of $((EXPR)) */
4867                        if (i_peek_and_eat_bkslash_nl(input) == end_ch) {
4868                                i_getch(input); /* eat second ')' */
4869                                break;
4870                        }
4871                }
4872                o_addchr(dest, ch);
4873                //bb_error_msg("%s:o_addchr('%c')", __func__, ch);
4874                if (ch == '(' || ch == '{') {
4875                        ch = (ch == '(' ? ')' : '}');
4876                        if (!add_till_closing_bracket(dest, input, ch))
4877                                return 0;
4878                        o_addchr(dest, ch);
4879                        continue;
4880                }
4881                if (ch == '\'') {
4882                        if (!add_till_single_quote(dest, input))
4883                                return 0;
4884                        o_addchr(dest, ch);
4885                        continue;
4886                }
4887                if (ch == '"') {
4888                        if (!add_till_double_quote(dest, input))
4889                                return 0;
4890                        o_addchr(dest, ch);
4891                        continue;
4892                }
4893                if (ch == '`') {
4894                        if (!add_till_backquote(dest, input, /*in_dquote:*/ 0))
4895                                return 0;
4896                        o_addchr(dest, ch);
4897                        continue;
4898                }
4899                if (ch == '\\') {
4900                        /* \x. Copy verbatim. Important for  \(, \) */
4901                        ch = i_getch(input);
4902                        if (ch == EOF) {
4903                                syntax_error_unterm_ch(end_ch);
4904                                return 0;
4905                        }
4906# if 0
4907                        if (ch == '\n') {
4908                                /* "backslash+newline", ignore both */
4909                                o_delchr(dest); /* undo insertion of '\' */
4910                                continue;
4911                        }
4912# endif
4913                        o_addchr(dest, ch);
4914                        //bb_error_msg("%s:o_addchr('%c') after '\\'", __func__, ch);
4915                        continue;
4916                }
4917        }
4918        debug_printf_parse("%s return '%s' ch:'%c'\n", __func__, dest->data, ch);
4919        return ch;
4920}
4921#endif /* ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS */
4922
4923#if BASH_DOLLAR_SQUOTE
4924/* Return code: 1 for "found and parsed", 0 for "seen something else" */
4925# if BB_MMU
4926#define parse_dollar_squote(as_string, dest, input) \
4927        parse_dollar_squote(dest, input)
4928#define as_string NULL
4929# endif
4930static int parse_dollar_squote(o_string *as_string, o_string *dest, struct in_str *input)
4931{
4932        int start;
4933        int ch = i_peek_and_eat_bkslash_nl(input);  /* first character after the $ */
4934        debug_printf_parse("parse_dollar_squote entered: ch='%c'\n", ch);
4935        if (ch != '\'')
4936                return 0;
4937
4938        dest->has_quoted_part = 1;
4939        start = dest->length;
4940
4941        ch = i_getch(input); /* eat ' */
4942        nommu_addchr(as_string, ch);
4943        while (1) {
4944                ch = i_getch(input);
4945                nommu_addchr(as_string, ch);
4946                if (ch == EOF) {
4947                        syntax_error_unterm_ch('\'');
4948                        return 0;
4949                }
4950                if (ch == '\'')
4951                        break;
4952                if (ch == SPECIAL_VAR_SYMBOL) {
4953                        /* Convert raw ^C to corresponding special variable reference */
4954                        o_addchr(dest, SPECIAL_VAR_SYMBOL);
4955                        o_addchr(dest, SPECIAL_VAR_QUOTED_SVS);
4956                        /* will addchr() another SPECIAL_VAR_SYMBOL (see after the if() block) */
4957                } else if (ch == '\\') {
4958                        static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
4959
4960                        ch = i_getch(input);
4961                        nommu_addchr(as_string, ch);
4962                        if (strchr(C_escapes, ch)) {
4963                                char buf[4];
4964                                char *p = buf;
4965                                int cnt = 2;
4966
4967                                buf[0] = ch;
4968                                if ((unsigned char)(ch - '0') <= 7) { /* \ooo */
4969                                        do {
4970                                                ch = i_peek(input);
4971                                                if ((unsigned char)(ch - '0') > 7)
4972                                                        break;
4973                                                *++p = ch = i_getch(input);
4974                                                nommu_addchr(as_string, ch);
4975                                        } while (--cnt != 0);
4976                                } else if (ch == 'x') { /* \xHH */
4977                                        do {
4978                                                ch = i_peek(input);
4979                                                if (!isxdigit(ch))
4980                                                        break;
4981                                                *++p = ch = i_getch(input);
4982                                                nommu_addchr(as_string, ch);
4983                                        } while (--cnt != 0);
4984                                        if (cnt == 2) { /* \x but next char is "bad" */
4985                                                ch = 'x';
4986                                                goto unrecognized;
4987                                        }
4988                                } /* else simple seq like \\ or \t */
4989                                *++p = '\0';
4990                                p = buf;
4991                                ch = bb_process_escape_sequence((void*)&p);
4992                                //bb_error_msg("buf:'%s' ch:%x", buf, ch);
4993                                if (ch == '\0')
4994                                        continue; /* bash compat: $'...\0...' emits nothing */
4995                        } else { /* unrecognized "\z": encode both chars unless ' or " */
4996                                if (ch != '\'' && ch != '"') {
4997 unrecognized:
4998                                        o_addqchr(dest, '\\');
4999                                }
5000                        }
5001                } /* if (\...) */
5002                o_addqchr(dest, ch);
5003        }
5004
5005        if (dest->length == start) {
5006                /* $'', $'\0', $'\000\x00' and the like */
5007                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5008                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5009        }
5010
5011        return 1;
5012# undef as_string
5013}
5014#else
5015# define parse_dollar_squote(as_string, dest, input) 0
5016#endif /* BASH_DOLLAR_SQUOTE */
5017
5018/* Return code: 0 for OK, 1 for syntax error */
5019#if BB_MMU
5020#define parse_dollar(as_string, dest, input, quote_mask) \
5021        parse_dollar(dest, input, quote_mask)
5022#define as_string NULL
5023#endif
5024static int parse_dollar(o_string *as_string,
5025                o_string *dest,
5026                struct in_str *input, unsigned char quote_mask)
5027{
5028        int ch = i_peek_and_eat_bkslash_nl(input);  /* first character after the $ */
5029
5030        debug_printf_parse("parse_dollar entered: ch='%c' quote_mask:0x%x\n", ch, quote_mask);
5031        if (isalpha(ch)) {
5032 make_var:
5033                ch = i_getch(input);
5034                nommu_addchr(as_string, ch);
5035 /*make_var1:*/
5036                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5037                while (1) {
5038                        debug_printf_parse(": '%c'\n", ch);
5039                        o_addchr(dest, ch | quote_mask);
5040                        quote_mask = 0;
5041                        ch = i_peek_and_eat_bkslash_nl(input);
5042                        if (!isalnum(ch) && ch != '_') {
5043                                /* End of variable name reached */
5044                                break;
5045                        }
5046                        ch = i_getch(input);
5047                        nommu_addchr(as_string, ch);
5048                }
5049                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5050        } else if (isdigit(ch)) {
5051 make_one_char_var:
5052                ch = i_getch(input);
5053                nommu_addchr(as_string, ch);
5054                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5055                debug_printf_parse(": '%c'\n", ch);
5056                o_addchr(dest, ch | quote_mask);
5057                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5058        } else switch (ch) {
5059        case '$': /* pid */
5060        case '!': /* last bg pid */
5061        case '?': /* last exit code */
5062        case '#': /* number of args */
5063        case '*': /* args */
5064        case '@': /* args */
5065        case '-': /* $- option flags set by set builtin or shell options (-i etc) */
5066                goto make_one_char_var;
5067        case '{': {
5068                char len_single_ch;
5069
5070                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5071
5072                ch = i_getch(input); /* eat '{' */
5073                nommu_addchr(as_string, ch);
5074
5075                ch = i_getch_and_eat_bkslash_nl(input); /* first char after '{' */
5076                /* It should be ${?}, or ${#var},
5077                 * or even ${?+subst} - operator acting on a special variable,
5078                 * or the beginning of variable name.
5079                 */
5080                if (ch == EOF
5081                 || (!strchr(_SPECIAL_VARS_STR, ch) && !isalnum(ch)) /* not one of those */
5082                ) {
5083 bad_dollar_syntax:
5084                        syntax_error_unterm_str("${name}");
5085                        debug_printf_parse("parse_dollar return 0: unterminated ${name}\n");
5086                        return 0;
5087                }
5088                nommu_addchr(as_string, ch);
5089                len_single_ch = ch;
5090                ch |= quote_mask;
5091
5092                /* It's possible to just call add_till_closing_bracket() at this point.
5093                 * However, this regresses some of our testsuite cases
5094                 * which check invalid constructs like ${%}.
5095                 * Oh well... let's check that the var name part is fine... */
5096
5097                if (isdigit(len_single_ch)
5098                 || (len_single_ch == '#' && isdigit(i_peek_and_eat_bkslash_nl(input)))
5099                ) {
5100                        /* Execution engine uses plain xatoi_positive()
5101                         * to interpret ${NNN} and {#NNN},
5102                         * check syntax here in the parser.
5103                         * (bash does not support expressions in ${#NN},
5104                         * e.g. ${#$var} and {#1:+WORD} are not supported).
5105                         */
5106                        unsigned cnt = 9; /* max 9 digits for ${NN} and 8 for {#NN} */
5107                        while (1) {
5108                                o_addchr(dest, ch);
5109                                debug_printf_parse(": '%c'\n", ch);
5110                                ch = i_getch_and_eat_bkslash_nl(input);
5111                                nommu_addchr(as_string, ch);
5112                                if (ch == '}')
5113                                        break;
5114                                if (--cnt == 0)
5115                                        goto bad_dollar_syntax;
5116                                if (len_single_ch != '#' && strchr(VAR_SUBST_OPS, ch))
5117                                        /* ${NN<op>...} is valid */
5118                                        goto eat_until_closing;
5119                                if (!isdigit(ch))
5120                                        goto bad_dollar_syntax;
5121                        }
5122                } else
5123                while (1) {
5124                        unsigned pos;
5125
5126                        o_addchr(dest, ch);
5127                        debug_printf_parse(": '%c'\n", ch);
5128
5129                        ch = i_getch(input);
5130                        nommu_addchr(as_string, ch);
5131                        if (ch == '}')
5132                                break;
5133                        if (!isalnum(ch) && ch != '_') {
5134                                unsigned end_ch;
5135                                unsigned char last_ch;
5136                                /* handle parameter expansions
5137                                 * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02
5138                                 */
5139                                if (!strchr(VAR_SUBST_OPS, ch)) { /* ${var<bad_char>... */
5140                                        if (len_single_ch != '#'
5141                                        /*|| !strchr(SPECIAL_VARS_STR, ch) - disallow errors like ${#+} ? */
5142                                         || i_peek(input) != '}'
5143                                        ) {
5144                                                goto bad_dollar_syntax;
5145                                        }
5146                                        /* else: it's "length of C" ${#C} op,
5147                                         * where C is a single char
5148                                         * special var name, e.g. ${#!}.
5149                                         */
5150                                }
5151 eat_until_closing:
5152                                /* Eat everything until closing '}' (or ':') */
5153                                end_ch = '}';
5154                                if (BASH_SUBSTR
5155                                 && ch == ':'
5156                                 && !strchr(MINUS_PLUS_EQUAL_QUESTION, i_peek(input))
5157                                ) {
5158                                        /* It's ${var:N[:M]} thing */
5159                                        end_ch = '}' * 0x100 + ':';
5160                                }
5161                                if (BASH_PATTERN_SUBST
5162                                 && ch == '/'
5163                                ) {
5164                                        /* It's ${var/[/]pattern[/repl]} thing */
5165                                        if (i_peek(input) == '/') { /* ${var//pattern[/repl]}? */
5166                                                i_getch(input);
5167                                                nommu_addchr(as_string, '/');
5168                                                ch = '\\';
5169                                        }
5170                                        end_ch = '}' * 0x100 + '/';
5171                                }
5172                                o_addchr(dest, ch);
5173                                /* The pattern can't be empty.
5174                                 * IOW: if the first char after "${v//" is a slash,
5175                                 * it does not terminate the pattern - it's the first char of the pattern:
5176                                 *  v=/dev/ram; echo ${v////-}  prints -dev-ram (pattern is "/")
5177                                 *  v=/dev/ram; echo ${v///r/-} prints /dev-am  (pattern is "/r")
5178                                 */
5179                                if (i_peek(input) == '/') {
5180                                        o_addchr(dest, i_getch(input));
5181                                }
5182 again:
5183                                if (!BB_MMU)
5184                                        pos = dest->length;
5185#if ENABLE_HUSH_DOLLAR_OPS
5186                                last_ch = add_till_closing_bracket(dest, input, end_ch);
5187                                if (last_ch == 0) /* error? */
5188                                        return 0;
5189#else
5190# error Simple code to only allow ${var} is not implemented
5191#endif
5192                                if (as_string) {
5193                                        o_addstr(as_string, dest->data + pos);
5194                                        o_addchr(as_string, last_ch);
5195                                }
5196
5197                                if ((BASH_SUBSTR || BASH_PATTERN_SUBST)
5198                                         && (end_ch & 0xff00)
5199                                ) {
5200                                        /* close the first block: */
5201                                        o_addchr(dest, SPECIAL_VAR_SYMBOL);
5202                                        /* while parsing N from ${var:N[:M]}
5203                                         * or pattern from ${var/[/]pattern[/repl]} */
5204                                        if ((end_ch & 0xff) == last_ch) {
5205                                                /* got ':' or '/'- parse the rest */
5206                                                end_ch = '}';
5207                                                goto again;
5208                                        }
5209                                        /* got '}' */
5210                                        if (BASH_SUBSTR && end_ch == '}' * 0x100 + ':') {
5211                                                /* it's ${var:N} - emulate :999999999 */
5212                                                o_addstr(dest, "999999999");
5213                                        } /* else: it's ${var/[/]pattern} */
5214                                }
5215                                break;
5216                        }
5217                        len_single_ch = 0; /* it can't be ${#C} op */
5218                }
5219                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5220                break;
5221        }
5222#if ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_TICK
5223        case '(': {
5224                unsigned pos;
5225
5226                ch = i_getch(input);
5227                nommu_addchr(as_string, ch);
5228# if ENABLE_FEATURE_SH_MATH
5229                if (i_peek_and_eat_bkslash_nl(input) == '(') {
5230                        ch = i_getch(input);
5231                        nommu_addchr(as_string, ch);
5232                        o_addchr(dest, SPECIAL_VAR_SYMBOL);
5233                        o_addchr(dest, quote_mask | '+');
5234                        if (!BB_MMU)
5235                                pos = dest->length;
5236                        if (!add_till_closing_bracket(dest, input, ')' | DOUBLE_CLOSE_CHAR_FLAG))
5237                                return 0; /* error */
5238                        if (as_string) {
5239                                o_addstr(as_string, dest->data + pos);
5240                                o_addchr(as_string, ')');
5241                                o_addchr(as_string, ')');
5242                        }
5243                        o_addchr(dest, SPECIAL_VAR_SYMBOL);
5244                        break;
5245                }
5246# endif
5247# if ENABLE_HUSH_TICK
5248                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5249                o_addchr(dest, quote_mask | '`');
5250                if (!BB_MMU)
5251                        pos = dest->length;
5252                if (!add_till_closing_bracket(dest, input, ')'))
5253                        return 0; /* error */
5254                if (as_string) {
5255                        o_addstr(as_string, dest->data + pos);
5256                        o_addchr(as_string, ')');
5257                }
5258                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5259# endif
5260                break;
5261        }
5262#endif
5263        case '_':
5264                goto make_var;
5265#if 0
5266        /* TODO: $_: */
5267        /* $_ Shell or shell script name; or last argument of last command
5268         * (if last command wasn't a pipe; if it was, bash sets $_ to "");
5269         * but in command's env, set to full pathname used to invoke it */
5270                ch = i_getch(input);
5271                nommu_addchr(as_string, ch);
5272                ch = i_peek_and_eat_bkslash_nl(input);
5273                if (isalnum(ch)) { /* it's $_name or $_123 */
5274                        ch = '_';
5275                        goto make_var1;
5276                }
5277                /* else: it's $_ */
5278#endif
5279        default:
5280                o_addQchr(dest, '$');
5281        }
5282        debug_printf_parse("parse_dollar return 1 (ok)\n");
5283        return 1;
5284#undef as_string
5285}
5286
5287#if BB_MMU
5288#define encode_string(as_string, dest, input, dquote_end) \
5289        encode_string(dest, input, dquote_end)
5290#define as_string NULL
5291#endif
5292static int encode_string(o_string *as_string,
5293                o_string *dest,
5294                struct in_str *input,
5295                int dquote_end)
5296{
5297        int ch;
5298        int next;
5299
5300 again:
5301        ch = i_getch(input);
5302        if (ch != EOF)
5303                nommu_addchr(as_string, ch);
5304        if (ch == dquote_end) { /* may be only '"' or EOF */
5305                debug_printf_parse("encode_string return 1 (ok)\n");
5306                return 1;
5307        }
5308        /* note: can't move it above ch == dquote_end check! */
5309        if (ch == EOF) {
5310                syntax_error_unterm_ch('"');
5311                return 0; /* error */
5312        }
5313        next = '\0';
5314        if (ch != '\n') {
5315                next = i_peek(input);
5316        }
5317        debug_printf_parse("\" ch=%c (%d) escape=%d\n",
5318                        ch, ch, !!(dest->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
5319        if (ch == '\\') {
5320                if (next == EOF) {
5321                        /* Testcase: in interactive shell a file with
5322                         *  echo "unterminated string\<eof>
5323                         * is sourced.
5324                         */
5325                        syntax_error_unterm_ch('"');
5326                        return 0; /* error */
5327                }
5328                /* bash:
5329                 * "The backslash retains its special meaning [in "..."]
5330                 * only when followed by one of the following characters:
5331                 * $, `, ", \, or <newline>.  A double quote may be quoted
5332                 * within double quotes by preceding it with a backslash."
5333                 * NB: in (unquoted) heredoc, above does not apply to ",
5334                 * therefore we check for it by "next == dquote_end" cond.
5335                 */
5336                if (next == dquote_end || strchr("$`\\\n", next)) {
5337                        ch = i_getch(input); /* eat next */
5338                        if (ch == '\n')
5339                                goto again; /* skip \<newline> */
5340                } /* else: ch remains == '\\', and we double it below: */
5341                o_addqchr(dest, ch); /* \c if c is a glob char, else just c */
5342                nommu_addchr(as_string, ch);
5343                goto again;
5344        }
5345        if (ch == '$') {
5346                //if (parse_dollar_squote(as_string, dest, input))
5347                //      goto again;
5348                if (!parse_dollar(as_string, dest, input, /*quote_mask:*/ 0x80)) {
5349                        debug_printf_parse("encode_string return 0: "
5350                                        "parse_dollar returned 0 (error)\n");
5351                        return 0;
5352                }
5353                goto again;
5354        }
5355#if ENABLE_HUSH_TICK
5356        if (ch == '`') {
5357                //unsigned pos = dest->length;
5358                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5359                o_addchr(dest, 0x80 | '`');
5360                if (!add_till_backquote(dest, input, /*in_dquote:*/ dquote_end == '"'))
5361                        return 0; /* error */
5362                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5363                //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos);
5364                goto again;
5365        }
5366#endif
5367        o_addQchr(dest, ch);
5368        if (ch == SPECIAL_VAR_SYMBOL) {
5369                /* Convert "^C" to corresponding special variable reference */
5370                o_addchr(dest, SPECIAL_VAR_QUOTED_SVS);
5371                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5372        }
5373        goto again;
5374#undef as_string
5375}
5376
5377/*
5378 * Scan input until EOF or end_trigger char.
5379 * Return a list of pipes to execute, or NULL on EOF
5380 * or if end_trigger character is met.
5381 * On syntax error, exit if shell is not interactive,
5382 * reset parsing machinery and start parsing anew,
5383 * or return ERR_PTR.
5384 */
5385static struct pipe *parse_stream(char **pstring,
5386                int *heredoc_cnt_ptr,
5387                struct in_str *input,
5388                int end_trigger)
5389{
5390        struct parse_context ctx;
5391        int heredoc_cnt;
5392
5393        /* Single-quote triggers a bypass of the main loop until its mate is
5394         * found.  When recursing, quote state is passed in via ctx.word.o_expflags.
5395         */
5396        debug_printf_parse("parse_stream entered, end_trigger='%c'\n",
5397                        end_trigger ? end_trigger : 'X');
5398        debug_enter();
5399
5400        initialize_context(&ctx);
5401
5402        /* If very first arg is "" or '', ctx.word.data may end up NULL.
5403         * Preventing this:
5404         */
5405        ctx.word.data = xzalloc(1); /* start as "", not as NULL */
5406
5407        /* We used to separate words on $IFS here. This was wrong.
5408         * $IFS is used only for word splitting when $var is expanded,
5409         * here we should use blank chars as separators, not $IFS
5410         */
5411
5412        heredoc_cnt = 0;
5413        while (1) {
5414                const char *is_blank;
5415                const char *is_special;
5416                int ch;
5417                int next;
5418                int redir_fd;
5419                redir_type redir_style;
5420
5421                ch = i_getch(input);
5422                debug_printf_parse(": ch=%c (%d) escape=%d\n",
5423                                ch, ch, !!(ctx.word.o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
5424                if (ch == EOF) {
5425                        struct pipe *pi;
5426
5427                        if (heredoc_cnt) {
5428                                syntax_error_unterm_str("here document");
5429                                goto parse_error_exitcode1;
5430                        }
5431                        if (end_trigger == ')') {
5432                                syntax_error_unterm_ch('(');
5433                                goto parse_error_exitcode1;
5434                        }
5435                        if (end_trigger == '}') {
5436                                syntax_error_unterm_ch('{');
5437                                goto parse_error_exitcode1;
5438                        }
5439
5440                        if (done_word(&ctx)) {
5441                                goto parse_error_exitcode1;
5442                        }
5443                        o_free_and_set_NULL(&ctx.word);
5444                        done_pipe(&ctx, PIPE_SEQ);
5445                        pi = ctx.list_head;
5446                        /* If we got nothing... */
5447                        /* (this makes bare "&" cmd a no-op.
5448                         * bash says: "syntax error near unexpected token '&'") */
5449                        if (pi->num_cmds == 0
5450                        IF_HAS_KEYWORDS(&& pi->res_word == RES_NONE)
5451                        ) {
5452                                free_pipe_list(pi);
5453                                pi = NULL;
5454                        }
5455#if !BB_MMU
5456                        debug_printf_parse("as_string1 '%s'\n", ctx.as_string.data);
5457                        if (pstring)
5458                                *pstring = ctx.as_string.data;
5459                        else
5460                                o_free(&ctx.as_string);
5461#endif
5462                        // heredoc_cnt must be 0 here anyway
5463                        //if (heredoc_cnt_ptr)
5464                        //      *heredoc_cnt_ptr = heredoc_cnt;
5465                        debug_leave();
5466                        debug_printf_heredoc("parse_stream return heredoc_cnt:%d\n", heredoc_cnt);
5467                        debug_printf_parse("parse_stream return %p\n", pi);
5468                        return pi;
5469                }
5470
5471                /* Handle "'" and "\" first, as they won't play nice with
5472                 * i_peek_and_eat_bkslash_nl() anyway:
5473                 *   echo z\\
5474                 * and
5475                 *   echo '\
5476                 *   '
5477                 * would break.
5478                 */
5479                if (ch == '\\') {
5480                        ch = i_getch(input);
5481                        if (ch == '\n')
5482                                continue; /* drop \<newline>, get next char */
5483                        nommu_addchr(&ctx.as_string, '\\');
5484                        if (ch == SPECIAL_VAR_SYMBOL) {
5485                                nommu_addchr(&ctx.as_string, ch);
5486                                /* Convert \^C to corresponding special variable reference */
5487                                goto case_SPECIAL_VAR_SYMBOL;
5488                        }
5489                        o_addchr(&ctx.word, '\\');
5490                        if (ch == EOF) {
5491                                /* Testcase: eval 'echo Ok\' */
5492                                /* bash-4.3.43 was removing backslash,
5493                                 * but 4.4.19 retains it, most other shells too
5494                                 */
5495                                continue; /* get next char */
5496                        }
5497                        /* Example: echo Hello \2>file
5498                         * we need to know that word 2 is quoted
5499                         */
5500                        ctx.word.has_quoted_part = 1;
5501                        nommu_addchr(&ctx.as_string, ch);
5502                        o_addchr(&ctx.word, ch);
5503                        continue; /* get next char */
5504                }
5505                nommu_addchr(&ctx.as_string, ch);
5506                if (ch == '\'') {
5507                        ctx.word.has_quoted_part = 1;
5508                        next = i_getch(input);
5509                        if (next == '\'' && !ctx.pending_redirect)
5510                                goto insert_empty_quoted_str_marker;
5511
5512                        ch = next;
5513                        while (1) {
5514                                if (ch == EOF) {
5515                                        syntax_error_unterm_ch('\'');
5516                                        goto parse_error_exitcode1;
5517                                }
5518                                nommu_addchr(&ctx.as_string, ch);
5519                                if (ch == '\'')
5520                                        break;
5521                                if (ch == SPECIAL_VAR_SYMBOL) {
5522                                        /* Convert raw ^C to corresponding special variable reference */
5523                                        o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5524                                        o_addchr(&ctx.word, SPECIAL_VAR_QUOTED_SVS);
5525                                }
5526                                o_addqchr(&ctx.word, ch);
5527                                ch = i_getch(input);
5528                        }
5529                        continue; /* get next char */
5530                }
5531
5532                next = '\0';
5533                if (ch != '\n')
5534                        next = i_peek_and_eat_bkslash_nl(input);
5535
5536                is_special = "{}<>&|();#" /* special outside of "str" */
5537                                "$\"" IF_HUSH_TICK("`") /* always special */
5538                                SPECIAL_VAR_SYMBOL_STR;
5539#if defined(CMD_TEST2_SINGLEWORD_NOGLOB)
5540                if (ctx.command->cmd_type == CMD_TEST2_SINGLEWORD_NOGLOB) {
5541                        /* In [[ ]], {}<>&|() are not special */
5542                        is_special += 8;
5543                } else
5544#endif
5545                /* Are { and } special here? */
5546                if (ctx.command->argv /* word [word]{... - non-special */
5547                 || ctx.word.length       /* word{... - non-special */
5548                 || ctx.word.has_quoted_part     /* ""{... - non-special */
5549                 || (next != ';'             /* }; - special */
5550                    && next != ')'           /* }) - special */
5551                    && next != '('           /* {( - special */
5552                    && next != '&'           /* }& and }&& ... - special */
5553                    && next != '|'           /* }|| ... - special */
5554                    && !strchr(defifs, next) /* {word - non-special */
5555                    )
5556                ) {
5557                        /* They are not special, skip "{}" */
5558                        is_special += 2;
5559                }
5560                is_special = strchr(is_special, ch);
5561                is_blank = strchr(defifs, ch);
5562
5563                if (!is_special && !is_blank) { /* ordinary char */
5564 ordinary_char:
5565                        o_addQchr(&ctx.word, ch);
5566                        if ((ctx.is_assignment == MAYBE_ASSIGNMENT
5567                            || ctx.is_assignment == WORD_IS_KEYWORD)
5568                         && ch == '='
5569                         && endofname(ctx.word.data)[0] == '='
5570                        ) {
5571                                ctx.is_assignment = DEFINITELY_ASSIGNMENT;
5572                                debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
5573                        }
5574                        continue;
5575                }
5576
5577                if (is_blank) {
5578#if ENABLE_HUSH_LINENO_VAR
5579/* Case:
5580 * "while ...; do<whitespace><newline>
5581 *      cmd ..."
5582 * would think that "cmd" starts in <whitespace> -
5583 * i.e., at the previous line.
5584 * We need to skip all whitespace before newlines.
5585 */
5586                        while (ch != '\n') {
5587                                next = i_peek(input);
5588                                if (next != ' ' && next != '\t' && next != '\n')
5589                                        break; /* next char is not ws */
5590                                ch = i_getch(input);
5591                        }
5592                        /* ch == last eaten whitespace char */
5593#endif
5594                        if (done_word(&ctx)) {
5595                                goto parse_error_exitcode1;
5596                        }
5597                        if (ch == '\n') {
5598                                /* Is this a case when newline is simply ignored?
5599                                 * Some examples:
5600                                 * "cmd | <newline> cmd ..."
5601                                 * "case ... in <newline> word) ..."
5602                                 */
5603                                if (IS_NULL_CMD(ctx.command)
5604                                 && ctx.word.length == 0
5605                                 && !ctx.word.has_quoted_part
5606                                 && heredoc_cnt == 0
5607                                ) {
5608                                        /* This newline can be ignored. But...
5609                                         * Without check #1, interactive shell
5610                                         * ignores even bare <newline>,
5611                                         * and shows the continuation prompt:
5612                                         * ps1_prompt$ <enter>
5613                                         * ps2> _   <=== wrong, should be ps1
5614                                         * Without check #2, "cmd & <newline>"
5615                                         * is similarly mistreated.
5616                                         * (BTW, this makes "cmd & cmd"
5617                                         * and "cmd && cmd" non-orthogonal.
5618                                         * Really, ask yourself, why
5619                                         * "cmd && <newline>" doesn't start
5620                                         * cmd but waits for more input?
5621                                         * The only reason is that it might be
5622                                         * a "cmd1 && <nl> cmd2 &" construct,
5623                                         * cmd1 may need to run in BG).
5624                                         */
5625                                        struct pipe *pi = ctx.list_head;
5626                                        if (pi->num_cmds != 0       /* check #1 */
5627                                         && pi->followup != PIPE_BG /* check #2 */
5628                                        ) {
5629                                                continue;
5630                                        }
5631                                }
5632                                /* Treat newline as a command separator. */
5633                                done_pipe(&ctx, PIPE_SEQ);
5634                                debug_printf_heredoc("heredoc_cnt:%d\n", heredoc_cnt);
5635                                if (heredoc_cnt) {
5636                                        heredoc_cnt = fetch_heredocs(&ctx.as_string, ctx.list_head, heredoc_cnt, input);
5637                                        if (heredoc_cnt != 0)
5638                                                goto parse_error_exitcode1;
5639                                }
5640                                ctx.is_assignment = MAYBE_ASSIGNMENT;
5641                                debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
5642                                ch = ';';
5643                                /* note: if (is_blank) continue;
5644                                 * will still trigger for us */
5645                        }
5646                }
5647
5648                /* "cmd}" or "cmd }..." without semicolon or &:
5649                 * } is an ordinary char in this case, even inside { cmd; }
5650                 * Pathological example: { ""}; } should exec "}" cmd
5651                 */
5652                if (ch == '}') {
5653                        if (ctx.word.length != 0 /* word} */
5654                         || ctx.word.has_quoted_part    /* ""} */
5655                        ) {
5656                                goto ordinary_char;
5657                        }
5658                        if (!IS_NULL_CMD(ctx.command)) { /* cmd } */
5659                                /* Generally, there should be semicolon: "cmd; }"
5660                                 * However, bash allows to omit it if "cmd" is
5661                                 * a group. Examples:
5662                                 * { { echo 1; } }
5663                                 * {(echo 1)}
5664                                 * { echo 0 >&2 | { echo 1; } }
5665                                 * { while false; do :; done }
5666                                 * { case a in b) ;; esac }
5667                                 */
5668                                if (ctx.command->group)
5669                                        goto term_group;
5670                                goto ordinary_char;
5671                        }
5672                        if (!IS_NULL_PIPE(ctx.pipe)) /* cmd | } */
5673                                /* Can't be an end of {cmd}, skip the check */
5674                                goto skip_end_trigger;
5675                        /* else: } does terminate a group */
5676                }
5677 term_group:
5678                if (end_trigger && end_trigger == ch
5679                 && (ch != ';' || heredoc_cnt == 0)
5680#if ENABLE_HUSH_CASE
5681                 && (ch != ')'
5682                    || ctx.ctx_res_w != RES_MATCH
5683                    || (!ctx.word.has_quoted_part && strcmp(ctx.word.data, "esac") == 0)
5684                    )
5685#endif
5686                ) {
5687                        if (done_word(&ctx)) {
5688                                goto parse_error_exitcode1;
5689                        }
5690                        done_pipe(&ctx, PIPE_SEQ);
5691                        ctx.is_assignment = MAYBE_ASSIGNMENT;
5692                        debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
5693                        /* Do we sit outside of any if's, loops or case's? */
5694                        if (!HAS_KEYWORDS
5695                        IF_HAS_KEYWORDS(|| (ctx.ctx_res_w == RES_NONE && ctx.old_flag == 0))
5696                        ) {
5697                                o_free_and_set_NULL(&ctx.word);
5698#if !BB_MMU
5699                                debug_printf_parse("as_string2 '%s'\n", ctx.as_string.data);
5700                                if (pstring)
5701                                        *pstring = ctx.as_string.data;
5702                                else
5703                                        o_free(&ctx.as_string);
5704#endif
5705                                if (ch != ';' && IS_NULL_PIPE(ctx.list_head)) {
5706                                        /* Example: bare "{ }", "()" */
5707                                        G.last_exitcode = 2; /* bash compat */
5708                                        syntax_error_unexpected_ch(ch);
5709                                        goto parse_error;
5710                                }
5711                                if (heredoc_cnt_ptr)
5712                                        *heredoc_cnt_ptr = heredoc_cnt;
5713                                debug_printf_heredoc("parse_stream return heredoc_cnt:%d\n", heredoc_cnt);
5714                                debug_printf_parse("parse_stream return %p: "
5715                                                "end_trigger char found\n",
5716                                                ctx.list_head);
5717                                debug_leave();
5718                                return ctx.list_head;
5719                        }
5720                }
5721
5722                if (is_blank)
5723                        continue;
5724
5725                /* Catch <, > before deciding whether this word is
5726                 * an assignment. a=1 2>z b=2: b=2 is still assignment */
5727                switch (ch) {
5728                case '>':
5729                        redir_fd = redirect_opt_num(&ctx.word);
5730                        if (done_word(&ctx)) {
5731                                goto parse_error_exitcode1;
5732                        }
5733                        redir_style = REDIRECT_OVERWRITE;
5734                        if (next == '>') {
5735                                redir_style = REDIRECT_APPEND;
5736                                ch = i_getch(input);
5737                                nommu_addchr(&ctx.as_string, ch);
5738                        }
5739#if 0
5740                        else if (next == '(') {
5741                                syntax_error(">(process) not supported");
5742                                goto parse_error_exitcode1;
5743                        }
5744#endif
5745                        if (parse_redirect(&ctx, redir_fd, redir_style, input))
5746                                goto parse_error_exitcode1;
5747                        continue; /* get next char */
5748                case '<':
5749                        redir_fd = redirect_opt_num(&ctx.word);
5750                        if (done_word(&ctx)) {
5751                                goto parse_error_exitcode1;
5752                        }
5753                        redir_style = REDIRECT_INPUT;
5754                        if (next == '<') {
5755                                redir_style = REDIRECT_HEREDOC;
5756                                heredoc_cnt++;
5757                                debug_printf_heredoc("++heredoc_cnt=%d\n", heredoc_cnt);
5758                                ch = i_getch(input);
5759                                nommu_addchr(&ctx.as_string, ch);
5760                        } else if (next == '>') {
5761                                redir_style = REDIRECT_IO;
5762                                ch = i_getch(input);
5763                                nommu_addchr(&ctx.as_string, ch);
5764                        }
5765#if 0
5766                        else if (next == '(') {
5767                                syntax_error("<(process) not supported");
5768                                goto parse_error_exitcode1;
5769                        }
5770#endif
5771                        if (parse_redirect(&ctx, redir_fd, redir_style, input))
5772                                goto parse_error_exitcode1;
5773                        continue; /* get next char */
5774                case '#':
5775                        if (ctx.word.length == 0 && !ctx.word.has_quoted_part) {
5776                                /* skip "#comment" */
5777                                /* note: we do not add it to &ctx.as_string */
5778/* TODO: in bash:
5779 * comment inside $() goes to the next \n, even inside quoted string (!):
5780 * cmd "$(cmd2 #comment)" - syntax error
5781 * cmd "`cmd2 #comment`" - ok
5782 * We accept both (comment ends where command subst ends, in both cases).
5783 */
5784                                while (1) {
5785                                        ch = i_peek(input);
5786                                        if (ch == '\n') {
5787                                                nommu_addchr(&ctx.as_string, '\n');
5788                                                break;
5789                                        }
5790                                        ch = i_getch(input);
5791                                        if (ch == EOF)
5792                                                break;
5793                                }
5794                                continue; /* get next char */
5795                        }
5796                        break;
5797                }
5798 skip_end_trigger:
5799
5800                if (ctx.is_assignment == MAYBE_ASSIGNMENT
5801                 /* check that we are not in word in "a=1 2>word b=1": */
5802                 && !ctx.pending_redirect
5803                ) {
5804                        /* ch is a special char and thus this word
5805                         * cannot be an assignment */
5806                        ctx.is_assignment = NOT_ASSIGNMENT;
5807                        debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
5808                }
5809
5810                /* Note: nommu_addchr(&ctx.as_string, ch) is already done */
5811
5812                switch (ch) {
5813                case_SPECIAL_VAR_SYMBOL:
5814                case SPECIAL_VAR_SYMBOL:
5815                        /* Convert raw ^C to corresponding special variable reference */
5816                        o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5817                        o_addchr(&ctx.word, SPECIAL_VAR_QUOTED_SVS);
5818                        /* fall through */
5819                case '#':
5820                        /* non-comment #: "echo a#b" etc */
5821                        o_addchr(&ctx.word, ch);
5822                        continue; /* get next char */
5823                case '$':
5824                        if (parse_dollar_squote(&ctx.as_string, &ctx.word, input))
5825                                continue; /* get next char */
5826                        if (!parse_dollar(&ctx.as_string, &ctx.word, input, /*quote_mask:*/ 0)) {
5827                                debug_printf_parse("parse_stream parse error: "
5828                                        "parse_dollar returned 0 (error)\n");
5829                                goto parse_error_exitcode1;
5830                        }
5831                        continue; /* get next char */
5832                case '"':
5833                        ctx.word.has_quoted_part = 1;
5834                        if (next == '"' && !ctx.pending_redirect) {
5835                                i_getch(input); /* eat second " */
5836 insert_empty_quoted_str_marker:
5837                                nommu_addchr(&ctx.as_string, next);
5838                                o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5839                                o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5840                                continue; /* get next char */
5841                        }
5842                        if (ctx.is_assignment == NOT_ASSIGNMENT)
5843                                ctx.word.o_expflags |= EXP_FLAG_ESC_GLOB_CHARS;
5844                        if (!encode_string(&ctx.as_string, &ctx.word, input, '"'))
5845                                goto parse_error_exitcode1;
5846                        ctx.word.o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS;
5847                        continue; /* get next char */
5848#if ENABLE_HUSH_TICK
5849                case '`': {
5850                        USE_FOR_NOMMU(unsigned pos;)
5851
5852                        o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5853                        o_addchr(&ctx.word, '`');
5854                        USE_FOR_NOMMU(pos = ctx.word.length;)
5855                        if (!add_till_backquote(&ctx.word, input, /*in_dquote:*/ 0))
5856                                goto parse_error_exitcode1;
5857# if !BB_MMU
5858                        o_addstr(&ctx.as_string, ctx.word.data + pos);
5859                        o_addchr(&ctx.as_string, '`');
5860# endif
5861                        o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5862                        //debug_printf_subst("SUBST RES3 '%s'\n", ctx.word.data + pos);
5863                        continue; /* get next char */
5864                }
5865#endif
5866                case ';':
5867#if ENABLE_HUSH_CASE
5868 case_semi:
5869#endif
5870                        if (done_word(&ctx)) {
5871                                goto parse_error_exitcode1;
5872                        }
5873                        done_pipe(&ctx, PIPE_SEQ);
5874#if ENABLE_HUSH_CASE
5875                        /* Eat multiple semicolons, detect
5876                         * whether it means something special */
5877                        while (1) {
5878                                ch = i_peek_and_eat_bkslash_nl(input);
5879                                if (ch != ';')
5880                                        break;
5881                                ch = i_getch(input);
5882                                nommu_addchr(&ctx.as_string, ch);
5883                                if (ctx.ctx_res_w == RES_CASE_BODY) {
5884                                        ctx.ctx_dsemicolon = 1;
5885                                        ctx.ctx_res_w = RES_MATCH;
5886                                        break;
5887                                }
5888                        }
5889#endif
5890 new_cmd:
5891                        /* We just finished a cmd. New one may start
5892                         * with an assignment */
5893                        ctx.is_assignment = MAYBE_ASSIGNMENT;
5894                        debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
5895                        continue; /* get next char */
5896                case '&':
5897                        if (done_word(&ctx)) {
5898                                goto parse_error_exitcode1;
5899                        }
5900                        if (next == '&') {
5901                                ch = i_getch(input);
5902                                nommu_addchr(&ctx.as_string, ch);
5903                                done_pipe(&ctx, PIPE_AND);
5904                        } else {
5905                                done_pipe(&ctx, PIPE_BG);
5906                        }
5907                        goto new_cmd;
5908                case '|':
5909                        if (done_word(&ctx)) {
5910                                goto parse_error_exitcode1;
5911                        }
5912#if ENABLE_HUSH_CASE
5913                        if (ctx.ctx_res_w == RES_MATCH)
5914                                break; /* we are in case's "word | word)" */
5915#endif
5916                        if (next == '|') { /* || */
5917                                ch = i_getch(input);
5918                                nommu_addchr(&ctx.as_string, ch);
5919                                done_pipe(&ctx, PIPE_OR);
5920                        } else {
5921                                /* we could pick up a file descriptor choice here
5922                                 * with redirect_opt_num(), but bash doesn't do it.
5923                                 * "echo foo 2| cat" yields "foo 2". */
5924                                done_command(&ctx);
5925                        }
5926                        goto new_cmd;
5927                case '(':
5928#if ENABLE_HUSH_CASE
5929                        /* "case... in [(]word)..." - skip '(' */
5930                        if (ctx.ctx_res_w == RES_MATCH
5931                         && ctx.command->argv == NULL /* not (word|(... */
5932                         && ctx.word.length == 0 /* not word(... */
5933                         && ctx.word.has_quoted_part == 0 /* not ""(... */
5934                        ) {
5935                                continue; /* get next char */
5936                        }
5937#endif
5938                        /* fall through */
5939                case '{': {
5940                        int n = parse_group(&ctx, input, ch);
5941                        if (n < 0) {
5942                                goto parse_error_exitcode1;
5943                        }
5944                        debug_printf_heredoc("parse_group done, needs heredocs:%d\n", n);
5945                        heredoc_cnt += n;
5946                        goto new_cmd;
5947                }
5948                case ')':
5949#if ENABLE_HUSH_CASE
5950                        if (ctx.ctx_res_w == RES_MATCH)
5951                                goto case_semi;
5952#endif
5953                case '}':
5954                        /* proper use of this character is caught by end_trigger:
5955                         * if we see {, we call parse_group(..., end_trigger='}')
5956                         * and it will match } earlier (not here). */
5957                        G.last_exitcode = 2;
5958                        syntax_error_unexpected_ch(ch);
5959                        goto parse_error;
5960                default:
5961                        if (HUSH_DEBUG)
5962                                bb_error_msg_and_die("BUG: unexpected %c", ch);
5963                }
5964        } /* while (1) */
5965
5966 parse_error_exitcode1:
5967        G.last_exitcode = 1;
5968 parse_error:
5969        {
5970                struct parse_context *pctx;
5971                IF_HAS_KEYWORDS(struct parse_context *p2;)
5972
5973                /* Clean up allocated tree.
5974                 * Sample for finding leaks on syntax error recovery path.
5975                 * Run it from interactive shell, watch pmap `pidof hush`.
5976                 * while if false; then false; fi; do break; fi
5977                 * Samples to catch leaks at execution:
5978                 * while if (true | { true;}); then echo ok; fi; do break; done
5979                 * while if (true | { true;}); then echo ok; fi; do (if echo ok; break; then :; fi) | cat; break; done
5980                 */
5981                pctx = &ctx;
5982                do {
5983                        /* Update pipe/command counts,
5984                         * otherwise freeing may miss some */
5985                        done_pipe(pctx, PIPE_SEQ);
5986                        debug_printf_clean("freeing list %p from ctx %p\n",
5987                                        pctx->list_head, pctx);
5988                        debug_print_tree(pctx->list_head, 0);
5989                        free_pipe_list(pctx->list_head);
5990                        debug_printf_clean("freed list %p\n", pctx->list_head);
5991#if !BB_MMU
5992                        o_free(&pctx->as_string);
5993#endif
5994                        IF_HAS_KEYWORDS(p2 = pctx->stack;)
5995                        if (pctx != &ctx) {
5996                                free(pctx);
5997                        }
5998                        IF_HAS_KEYWORDS(pctx = p2;)
5999                } while (HAS_KEYWORDS && pctx);
6000
6001                o_free(&ctx.word);
6002#if !BB_MMU
6003                if (pstring)
6004                        *pstring = NULL;
6005#endif
6006                debug_leave();
6007                return ERR_PTR;
6008        }
6009}
6010
6011
6012/*** Execution routines ***/
6013
6014/* Expansion can recurse, need forward decls: */
6015#if !BASH_PATTERN_SUBST && !ENABLE_HUSH_CASE
6016#define expand_string_to_string(str, EXP_flags, do_unbackslash) \
6017        expand_string_to_string(str)
6018#endif
6019static char *expand_string_to_string(const char *str, int EXP_flags, int do_unbackslash);
6020#if ENABLE_HUSH_TICK
6021static int process_command_subs(o_string *dest, const char *s);
6022#endif
6023static int expand_vars_to_list(o_string *output, int n, char *arg);
6024
6025/* expand_strvec_to_strvec() takes a list of strings, expands
6026 * all variable references within and returns a pointer to
6027 * a list of expanded strings, possibly with larger number
6028 * of strings. (Think VAR="a b"; echo $VAR).
6029 * This new list is allocated as a single malloc block.
6030 * NULL-terminated list of char* pointers is at the beginning of it,
6031 * followed by strings themselves.
6032 * Caller can deallocate entire list by single free(list). */
6033
6034/* A horde of its helpers come first: */
6035
6036static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len)
6037{
6038        while (--len >= 0) {
6039                char c = *str++;
6040
6041#if ENABLE_HUSH_BRACE_EXPANSION
6042                if (c == '{' || c == '}') {
6043                        /* { -> \{, } -> \} */
6044                        o_addchr(o, '\\');
6045                        /* And now we want to add { or } and continue:
6046                         *  o_addchr(o, c);
6047                         *  continue;
6048                         * luckily, just falling through achieves this.
6049                         */
6050                }
6051#endif
6052                o_addchr(o, c);
6053                if (c == '\\') {
6054                        /* \z -> \\\z; \<eol> -> \\<eol> */
6055                        o_addchr(o, '\\');
6056                        if (len) {
6057                                len--;
6058                                o_addchr(o, '\\');
6059                                o_addchr(o, *str++);
6060                        }
6061                }
6062        }
6063}
6064
6065/* Store given string, finalizing the word and starting new one whenever
6066 * we encounter IFS char(s). This is used for expanding variable values.
6067 * End-of-string does NOT finalize word: think about 'echo -$VAR-'.
6068 * Return in output->ended_in_ifs:
6069 * 1 - ended with IFS char, else 0 (this includes case of empty str).
6070 */
6071static int expand_on_ifs(o_string *output, int n, const char *str)
6072{
6073        int last_is_ifs = 0;
6074
6075        while (1) {
6076                int word_len;
6077
6078                if (!*str)  /* EOL - do not finalize word */
6079                        break;
6080                word_len = strcspn(str, G.ifs);
6081                if (word_len) {
6082                        /* We have WORD_LEN leading non-IFS chars */
6083                        if (!(output->o_expflags & EXP_FLAG_GLOB)) {
6084                                o_addblock(output, str, word_len);
6085                        } else {
6086                                /* Protect backslashes against globbing up :)
6087                                 * Example: "v='\*'; echo b$v" prints "b\*"
6088                                 * (and does not try to glob on "*")
6089                                 */
6090                                o_addblock_duplicate_backslash(output, str, word_len);
6091                                /*/ Why can't we do it easier? */
6092                                /*o_addblock(output, str, word_len); - WRONG: "v='\*'; echo Z$v" prints "Z*" instead of "Z\*" */
6093                                /*o_addqblock(output, str, word_len); - WRONG: "v='*'; echo Z$v" prints "Z*" instead of Z* files */
6094                        }
6095                        last_is_ifs = 0;
6096                        str += word_len;
6097                        if (!*str)  /* EOL - do not finalize word */
6098                                break;
6099                }
6100
6101                /* We know str here points to at least one IFS char */
6102                last_is_ifs = 1;
6103                str += strspn(str, G.ifs_whitespace); /* skip IFS whitespace chars */
6104                if (!*str)  /* EOL - do not finalize word */
6105                        break;
6106
6107                if (G.ifs_whitespace != G.ifs /* usually false ($IFS is usually all whitespace), */
6108                 && strchr(G.ifs, *str)       /* the second check would fail */
6109                ) {
6110                        /* This is a non-whitespace $IFS char */
6111                        /* Skip it and IFS whitespace chars, start new word */
6112                        str++;
6113                        str += strspn(str, G.ifs_whitespace);
6114                        goto new_word;
6115                }
6116
6117                /* Start new word... but not always! */
6118                /* Case "v=' a'; echo ''$v": we do need to finalize empty word: */
6119                if (output->has_quoted_part
6120                /*
6121                 * Case "v=' a'; echo $v":
6122                 * here nothing precedes the space in $v expansion,
6123                 * therefore we should not finish the word
6124                 * (IOW: if there *is* word to finalize, only then do it):
6125                 * It's okay if this accesses the byte before first argv[]:
6126                 * past call to o_save_ptr() cleared it to zero byte
6127                 * (grep for -prev-ifs-check-).
6128                 */
6129                 || output->data[output->length - 1]
6130                ) {
6131 new_word:
6132                        o_addchr(output, '\0');
6133                        debug_print_list("expand_on_ifs", output, n);
6134                        n = o_save_ptr(output, n);
6135                }
6136        }
6137
6138        output->ended_in_ifs = last_is_ifs;
6139        debug_print_list("expand_on_ifs[1]", output, n);
6140        return n;
6141}
6142
6143/* Helper to expand $((...)) and heredoc body. These act as if
6144 * they are in double quotes, with the exception that they are not :).
6145 * Just the rules are similar: "expand only $var and `cmd`"
6146 *
6147 * Returns malloced string.
6148 * As an optimization, we return NULL if expansion is not needed.
6149 */
6150static char *encode_then_expand_string(const char *str)
6151{
6152        char *exp_str;
6153        struct in_str input;
6154        o_string dest = NULL_O_STRING;
6155        const char *cp;
6156
6157        cp = str;
6158        for (;;) {
6159                if (!*cp) return NULL; /* string has no special chars */
6160                if (*cp == '$') break;
6161                if (*cp == '\\') break;
6162#if ENABLE_HUSH_TICK
6163                if (*cp == '`') break;
6164#endif
6165                cp++;
6166        }
6167
6168        /* We need to expand. Example:
6169         * echo $(($a + `echo 1`)) $((1 + $((2)) ))
6170         */
6171        setup_string_in_str(&input, str);
6172        encode_string(NULL, &dest, &input, EOF);
6173//TODO: error check (encode_string returns 0 on error)?
6174        //bb_error_msg("'%s' -> '%s'", str, dest.data);
6175        exp_str = expand_string_to_string(dest.data,
6176                        EXP_FLAG_ESC_GLOB_CHARS,
6177                        /*unbackslash:*/ 1
6178        );
6179        //bb_error_msg("'%s' -> '%s'", dest.data, exp_str);
6180        o_free(&dest);
6181        return exp_str;
6182}
6183
6184static const char *first_special_char_in_vararg(const char *cp)
6185{
6186        for (;;) {
6187                if (!*cp) return NULL; /* string has no special chars */
6188                if (*cp == '$') return cp;
6189                if (*cp == '\\') return cp;
6190                if (*cp == '\'') return cp;
6191                if (*cp == '"') return cp;
6192#if ENABLE_HUSH_TICK
6193                if (*cp == '`') return cp;
6194#endif
6195                /* dquoted "${x:+ARG}" should not glob, therefore
6196                 * '*' et al require some non-literal processing: */
6197                if (*cp == '*') return cp;
6198                if (*cp == '?') return cp;
6199                if (*cp == '[') return cp;
6200                cp++;
6201        }
6202}
6203
6204/* Expanding ARG in ${var#ARG}, ${var%ARG}, or ${var/ARG/ARG}.
6205 * These can contain single- and double-quoted strings,
6206 * and treated as if the ARG string is initially unquoted. IOW:
6207 * ${var#ARG} and "${var#ARG}" treat ARG the same (ARG can even be
6208 * a dquoted string: "${var#"zz"}"), the difference only comes later
6209 * (word splitting and globbing of the ${var...} result).
6210 */
6211#if !BASH_PATTERN_SUBST
6212#define encode_then_expand_vararg(str, handle_squotes, do_unbackslash) \
6213        encode_then_expand_vararg(str, handle_squotes)
6214#endif
6215static char *encode_then_expand_vararg(const char *str, int handle_squotes, int do_unbackslash)
6216{
6217#if !BASH_PATTERN_SUBST && ENABLE_HUSH_CASE
6218        const int do_unbackslash = 0;
6219#endif
6220        char *exp_str;
6221        struct in_str input;
6222        o_string dest = NULL_O_STRING;
6223
6224        if (!first_special_char_in_vararg(str)) {
6225                /* string has no special chars */
6226                return NULL;
6227        }
6228
6229        setup_string_in_str(&input, str);
6230        dest.data = xzalloc(1); /* start as "", not as NULL */
6231        exp_str = NULL;
6232
6233        for (;;) {
6234                int ch;
6235
6236                ch = i_getch(&input);
6237                debug_printf_parse("%s: ch=%c (%d) escape=%d\n",
6238                                __func__, ch, ch, !!dest.o_expflags);
6239
6240                if (!dest.o_expflags) {
6241                        if (ch == EOF)
6242                                break;
6243                        if (handle_squotes && ch == '\'') {
6244                                if (!add_till_single_quote_dquoted(&dest, &input))
6245                                        goto ret; /* error */
6246                                continue;
6247                        }
6248                }
6249                if (ch == EOF) {
6250                        syntax_error_unterm_ch('"');
6251                        goto ret; /* error */
6252                }
6253                if (ch == '"') {
6254                        dest.o_expflags ^= EXP_FLAG_ESC_GLOB_CHARS;
6255                        continue;
6256                }
6257                if (ch == '\\') {
6258                        ch = i_getch(&input);
6259                        if (ch == EOF) {
6260//example? error message?       syntax_error_unterm_ch('"');
6261                                debug_printf_parse("%s: error: \\<eof>\n", __func__);
6262                                goto ret;
6263                        }
6264                        o_addqchr(&dest, ch);
6265                        continue;
6266                }
6267                if (ch == '$') {
6268                        if (parse_dollar_squote(NULL, &dest, &input))
6269                                continue;
6270                        if (!parse_dollar(NULL, &dest, &input, /*quote_mask:*/ 0x80)) {
6271                                debug_printf_parse("%s: error: parse_dollar returned 0 (error)\n", __func__);
6272                                goto ret;
6273                        }
6274                        continue;
6275                }
6276#if ENABLE_HUSH_TICK
6277                if (ch == '`') {
6278                        //unsigned pos = dest->length;
6279                        o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6280                        o_addchr(&dest, 0x80 | '`');
6281                        if (!add_till_backquote(&dest, &input,
6282                                        /*in_dquote:*/ dest.o_expflags /* nonzero if EXP_FLAG_ESC_GLOB_CHARS set */
6283                                )
6284                        ) {
6285                                goto ret; /* error */
6286                        }
6287                        o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6288                        //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos);
6289                        continue;
6290                }
6291#endif
6292                o_addQchr(&dest, ch);
6293        } /* for (;;) */
6294
6295        debug_printf_parse("encode: '%s' -> '%s'\n", str, dest.data);
6296        exp_str = expand_string_to_string(dest.data,
6297                        do_unbackslash ? EXP_FLAG_ESC_GLOB_CHARS : 0,
6298                        do_unbackslash
6299        );
6300 ret:
6301        debug_printf_parse("expand: '%s' -> '%s'\n", dest.data, exp_str);
6302        o_free(&dest);
6303        return exp_str;
6304}
6305
6306/* Expanding ARG in ${var+ARG}, ${var-ARG}
6307 */
6308static int encode_then_append_var_plusminus(o_string *output, int n,
6309                char *str, int dquoted)
6310{
6311        struct in_str input;
6312        o_string dest = NULL_O_STRING;
6313
6314        if (!first_special_char_in_vararg(str)
6315         && '\0' == str[strcspn(str, G.ifs)]
6316        ) {
6317                /* string has no special chars
6318                 * && string has no $IFS chars
6319                 */
6320                if (dquoted) {
6321                        /* Prints 1 (quoted expansion is a "" word, not nothing):
6322                         * set -- "${notexist-}"; echo $#
6323                         */
6324                        output->has_quoted_part = 1;
6325                }
6326                return expand_vars_to_list(output, n, str);
6327        }
6328
6329        setup_string_in_str(&input, str);
6330
6331        for (;;) {
6332                int ch;
6333
6334                ch = i_getch(&input);
6335                debug_printf_parse("%s: ch=%c (%d) escape=%x\n",
6336                                __func__, ch, ch, dest.o_expflags);
6337
6338                if (!dest.o_expflags) {
6339                        if (ch == EOF)
6340                                break;
6341                        if (!dquoted && strchr(G.ifs, ch)) {
6342                                /* PREFIX${x:d${e}f ...} and we met space: expand "d${e}f" and start new word.
6343                                 * do not assume we are at the start of the word (PREFIX above).
6344                                 */
6345                                if (dest.data) {
6346                                        n = expand_vars_to_list(output, n, dest.data);
6347                                        o_free_and_set_NULL(&dest);
6348                                        o_addchr(output, '\0');
6349                                        n = o_save_ptr(output, n); /* create next word */
6350                                } else
6351                                if (output->length != o_get_last_ptr(output, n)
6352                                 || output->has_quoted_part
6353                                ) {
6354                                        /* For these cases:
6355                                         * f() { for i; do echo "|$i|"; done; }; x=x
6356                                         * f a${x:+ }b  # 1st condition
6357                                         * |a|
6358                                         * |b|
6359                                         * f ""${x:+ }b  # 2nd condition
6360                                         * ||
6361                                         * |b|
6362                                         */
6363                                        o_addchr(output, '\0');
6364                                        n = o_save_ptr(output, n); /* create next word */
6365                                }
6366                                continue;
6367                        }
6368                        if (!dquoted && ch == '\'') {
6369                                if (!add_till_single_quote_dquoted(&dest, &input))
6370                                        goto ret; /* error */
6371                                o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6372                                o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6373                                continue;
6374                        }
6375                }
6376                if (ch == EOF) {
6377                        syntax_error_unterm_ch('"');
6378                        goto ret; /* error */
6379                }
6380                if (ch == '"') {
6381                        dest.o_expflags ^= EXP_FLAG_ESC_GLOB_CHARS;
6382                        if (dest.o_expflags) {
6383                                o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6384                                o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6385                        }
6386                        continue;
6387                }
6388                if (ch == '\\') {
6389                        ch = i_getch(&input);
6390                        if (ch == EOF) {
6391//example? error message?       syntax_error_unterm_ch('"');
6392                                debug_printf_parse("%s: error: \\<eof>\n", __func__);
6393                                goto ret;
6394                        }
6395                        o_addqchr(&dest, ch);
6396                        continue;
6397                }
6398                if (ch == '$') {
6399                        if (!parse_dollar(NULL, &dest, &input, /*quote_mask:*/ (dest.o_expflags || dquoted) ? 0x80 : 0)) {
6400                                debug_printf_parse("%s: error: parse_dollar returned 0 (error)\n", __func__);
6401                                goto ret;
6402                        }
6403                        continue;
6404                }
6405#if ENABLE_HUSH_TICK
6406                if (ch == '`') {
6407                        //unsigned pos = dest->length;
6408                        o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6409                        o_addchr(&dest, (dest.o_expflags || dquoted) ? 0x80 | '`' : '`');
6410                        if (!add_till_backquote(&dest, &input,
6411                                        /*in_dquote:*/ dest.o_expflags /* nonzero if EXP_FLAG_ESC_GLOB_CHARS set */
6412                                )
6413                        ) {
6414                                goto ret; /* error */
6415                        }
6416                        o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6417                        //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos);
6418                        continue;
6419                }
6420#endif
6421                if (dquoted) {
6422                        /* Always glob-protect if in dquotes:
6423                         * x=x; echo "${x:+/bin/c*}" - prints: /bin/c*
6424                         * x=x; echo "${x:+"/bin/c*"}" - prints: /bin/c*
6425                         */
6426                        o_addqchr(&dest, ch);
6427                } else {
6428                        /* Glob-protect only if char is quoted:
6429                         * x=x; echo ${x:+/bin/c*} - prints many filenames
6430                         * x=x; echo ${x:+"/bin/c*"} - prints: /bin/c*
6431                         */
6432                        o_addQchr(&dest, ch);
6433                }
6434        } /* for (;;) */
6435
6436        if (dest.data) {
6437                n = expand_vars_to_list(output, n, dest.data);
6438        }
6439 ret:
6440        o_free(&dest);
6441        return n;
6442}
6443
6444#if ENABLE_FEATURE_SH_MATH
6445static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p)
6446{
6447        arith_state_t math_state;
6448        arith_t res;
6449        char *exp_str;
6450
6451        math_state.lookupvar = get_local_var_value;
6452        math_state.setvar = set_local_var_from_halves;
6453        //math_state.endofname = endofname;
6454        exp_str = encode_then_expand_string(arg);
6455        res = arith(&math_state, exp_str ? exp_str : arg);
6456        free(exp_str);
6457        if (errmsg_p)
6458                *errmsg_p = math_state.errmsg;
6459        if (math_state.errmsg)
6460                msg_and_die_if_script(math_state.errmsg);
6461        return res;
6462}
6463#endif
6464
6465#if BASH_PATTERN_SUBST
6466/* ${var/[/]pattern[/repl]} helpers */
6467static char *strstr_pattern(char *val, const char *pattern, int *size)
6468{
6469        int sz = strcspn(pattern, "*?[\\");
6470        if (pattern[sz] == '\0') {
6471                /* Optimization for trivial patterns.
6472                 * Testcase for very slow replace (performs about 22k replaces):
6473                 * x=::::::::::::::::::::::
6474                 * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x}
6475                 * echo "${x//:/|}"
6476                 */
6477                *size = sz;
6478                return strstr(val, pattern);
6479        }
6480
6481        while (1) {
6482                char *end = scan_and_match(val, pattern, SCAN_MOVE_FROM_RIGHT + SCAN_MATCH_LEFT_HALF);
6483                debug_printf_varexp("val:'%s' pattern:'%s' end:'%s'\n", val, pattern, end);
6484                if (end) {
6485                        *size = end - val;
6486                        return val;
6487                }
6488                if (*val == '\0')
6489                        return NULL;
6490                /* Optimization: if "*pat" did not match the start of "string",
6491                 * we know that "tring", "ring" etc will not match too:
6492                 */
6493                if (pattern[0] == '*')
6494                        return NULL;
6495                val++;
6496        }
6497}
6498static char *replace_pattern(char *val, const char *pattern, const char *repl, char exp_op)
6499{
6500        char *result = NULL;
6501        unsigned res_len = 0;
6502        unsigned repl_len = strlen(repl);
6503
6504        /* Null pattern never matches, including if "var" is empty */
6505        if (!pattern[0])
6506                return result; /* NULL, no replaces happened */
6507
6508        while (1) {
6509                int size;
6510                char *s = strstr_pattern(val, pattern, &size);
6511                if (!s)
6512                        break;
6513
6514                result = xrealloc(result, res_len + (s - val) + repl_len + 1);
6515                strcpy(mempcpy(result + res_len, val, s - val), repl);
6516                res_len += (s - val) + repl_len;
6517                debug_printf_varexp("val:'%s' s:'%s' result:'%s'\n", val, s, result);
6518
6519                val = s + size;
6520                if (exp_op == '/')
6521                        break;
6522        }
6523        if (*val && result) {
6524                result = xrealloc(result, res_len + strlen(val) + 1);
6525                strcpy(result + res_len, val);
6526                debug_printf_varexp("val:'%s' result:'%s'\n", val, result);
6527        }
6528        debug_printf_varexp("result:'%s'\n", result);
6529        return result;
6530}
6531#endif /* BASH_PATTERN_SUBST */
6532
6533static int append_str_maybe_ifs_split(o_string *output, int n,
6534                int first_ch, const char *val)
6535{
6536        if (!(first_ch & 0x80)) { /* unquoted $VAR */
6537                debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val,
6538                                !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
6539                if (val && val[0])
6540                        n = expand_on_ifs(output, n, val);
6541        } else { /* quoted "$VAR" */
6542                output->has_quoted_part = 1;
6543                debug_printf_expand("quoted '%s', output->o_escape:%d\n", val,
6544                                !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
6545                if (val && val[0])
6546                        o_addQstr(output, val);
6547        }
6548        return n;
6549}
6550
6551/* Handle <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct.
6552 */
6553static NOINLINE int expand_one_var(o_string *output, int n,
6554                int first_ch, char *arg, char **pp)
6555{
6556        const char *val;
6557        char *to_be_freed;
6558        char *p;
6559        char *var;
6560        char exp_op;
6561        char exp_save = exp_save; /* for compiler */
6562        char *exp_saveptr; /* points to expansion operator */
6563        char *exp_word = exp_word; /* for compiler */
6564        char arg0;
6565
6566        val = NULL;
6567        to_be_freed = NULL;
6568        p = *pp;
6569        *p = '\0'; /* replace trailing SPECIAL_VAR_SYMBOL */
6570        var = arg;
6571        exp_saveptr = arg[1] ? strchr(VAR_ENCODED_SUBST_OPS, arg[1]) : NULL;
6572        arg0 = arg[0];
6573        arg[0] = (arg0 & 0x7f);
6574        exp_op = 0;
6575
6576        if (arg[0] == '#' && arg[1] /* ${#...} but not ${#} */
6577         && (!exp_saveptr               /* and ( not(${#<op_char>...}) */
6578            || (arg[2] == '\0' && strchr(SPECIAL_VARS_STR, arg[1])) /* or ${#C} "len of $C" ) */
6579            )           /* NB: skipping ^^^specvar check mishandles ${#::2} */
6580        ) {
6581                /* It must be length operator: ${#var} */
6582                var++;
6583                exp_op = 'L';
6584        } else {
6585                /* Maybe handle parameter expansion */
6586                if (exp_saveptr /* if 2nd char is one of expansion operators */
6587                 && strchr(NUMERIC_SPECVARS_STR, arg[0]) /* 1st char is special variable */
6588                ) {
6589                        /* ${?:0}, ${#[:]%0} etc */
6590                        exp_saveptr = var + 1;
6591                } else {
6592                        /* ${?}, ${var}, ${var:0}, ${var[:]%0} etc */
6593                        exp_saveptr = var+1 + strcspn(var+1, VAR_ENCODED_SUBST_OPS);
6594                }
6595                exp_op = exp_save = *exp_saveptr;
6596                if (exp_op) {
6597                        exp_word = exp_saveptr + 1;
6598                        if (exp_op == ':') {
6599                                exp_op = *exp_word++;
6600//TODO: try ${var:} and ${var:bogus} in non-bash config
6601                                if (BASH_SUBSTR
6602                                 && (!exp_op || !strchr(MINUS_PLUS_EQUAL_QUESTION, exp_op))
6603                                ) {
6604                                        /* oops... it's ${var:N[:M]}, not ${var:?xxx} or some such */
6605                                        exp_op = ':';
6606                                        exp_word--;
6607                                }
6608                        }
6609                        *exp_saveptr = '\0';
6610                } /* else: it's not an expansion op, but bare ${var} */
6611        }
6612
6613        /* Look up the variable in question */
6614        if (isdigit(var[0])) {
6615                /* parse_dollar should have vetted var for us */
6616                int nn = xatoi_positive(var);
6617                if (nn < G.global_argc)
6618                        val = G.global_argv[nn];
6619                /* else val remains NULL: $N with too big N */
6620        } else {
6621                switch (var[0]) {
6622                case '$': /* pid */
6623                        val = utoa(G.root_pid);
6624                        break;
6625                case '!': /* bg pid */
6626                        val = G.last_bg_pid ? utoa(G.last_bg_pid) : "";
6627                        break;
6628                case '?': /* exitcode */
6629                        val = utoa(G.last_exitcode);
6630                        break;
6631                case '#': /* argc */
6632                        val = utoa(G.global_argc ? G.global_argc-1 : 0);
6633                        break;
6634                case '-': { /* active options */
6635                        /* Check set_mode() to see what option chars we support */
6636                        char *cp;
6637                        val = cp = G.optstring_buf;
6638                        if (G.o_opt[OPT_O_ERREXIT])
6639                                *cp++ = 'e';
6640                        if (G_interactive_fd)
6641                                *cp++ = 'i';
6642                        if (G_x_mode)
6643                                *cp++ = 'x';
6644                        /* If G.o_opt[OPT_O_NOEXEC] is true,
6645                         * commands read but are not executed,
6646                         * so $- can not execute too, 'n' is never seen in $-.
6647                         */
6648                        if (G.opt_c)
6649                                *cp++ = 'c';
6650                        if (G.opt_s)
6651                                *cp++ = 's';
6652                        *cp = '\0';
6653                        break;
6654                }
6655                default:
6656                        val = get_local_var_value(var);
6657                }
6658        }
6659
6660        /* Handle any expansions */
6661        if (exp_op == 'L') {
6662                reinit_unicode_for_hush();
6663                debug_printf_expand("expand: length(%s)=", val);
6664                val = utoa(val ? unicode_strlen(val) : 0);
6665                debug_printf_expand("%s\n", val);
6666        } else if (exp_op) {
6667                if (exp_op == '%' || exp_op == '#') {
6668                        /* Standard-mandated substring removal ops:
6669                         * ${parameter%word} - remove smallest suffix pattern
6670                         * ${parameter%%word} - remove largest suffix pattern
6671                         * ${parameter#word} - remove smallest prefix pattern
6672                         * ${parameter##word} - remove largest prefix pattern
6673                         *
6674                         * Word is expanded to produce a glob pattern.
6675                         * Then var's value is matched to it and matching part removed.
6676                         */
6677                        /* bash compat: if x is "" and no shrinking of it is possible,
6678                         * inner ${...} is not evaluated. Example:
6679                         *  unset b; : ${a%${b=B}}; echo $b
6680                         * assignment b=B only happens if $a is not "".
6681                         */
6682                        if (val && val[0]) {
6683                                char *t;
6684                                char *exp_exp_word;
6685                                char *loc;
6686                                unsigned scan_flags = pick_scan(exp_op, *exp_word);
6687                                if (exp_op == *exp_word)  /* ## or %% */
6688                                        exp_word++;
6689                                debug_printf_expand("expand: exp_word:'%s'\n", exp_word);
6690                                exp_exp_word = encode_then_expand_vararg(exp_word, /*handle_squotes:*/ 1, /*unbackslash:*/ 0);
6691                                if (exp_exp_word)
6692                                        exp_word = exp_exp_word;
6693                                debug_printf_expand("expand: exp_word:'%s'\n", exp_word);
6694                                /*
6695                                 * HACK ALERT. We depend here on the fact that
6696                                 * G.global_argv and results of utoa and get_local_var_value
6697                                 * are actually in writable memory:
6698                                 * scan_and_match momentarily stores NULs there.
6699                                 */
6700                                t = (char*)val;
6701                                loc = scan_and_match(t, exp_word, scan_flags);
6702                                debug_printf_expand("op:%c str:'%s' pat:'%s' res:'%s'\n", exp_op, t, exp_word, loc);
6703                                free(exp_exp_word);
6704                                if (loc) { /* match was found */
6705                                        if (scan_flags & SCAN_MATCH_LEFT_HALF) /* #[#] */
6706                                                val = loc; /* take right part */
6707                                        else /* %[%] */
6708                                                val = to_be_freed = xstrndup(val, loc - val); /* left */
6709                                }
6710                        }
6711                }
6712#if BASH_PATTERN_SUBST
6713                else if (exp_op == '/' || exp_op == '\\') {
6714                        /* It's ${var/[/]pattern[/repl]} thing.
6715                         * Note that in encoded form it has TWO parts:
6716                         * var/pattern<SPECIAL_VAR_SYMBOL>repl<SPECIAL_VAR_SYMBOL>
6717                         * and if // is used, it is encoded as \:
6718                         * var\pattern<SPECIAL_VAR_SYMBOL>repl<SPECIAL_VAR_SYMBOL>
6719                         */
6720                        /* bash compat: if var is "", both pattern and repl
6721                         * are still evaluated, if it is unset, then not:
6722                         * unset b; a=; : ${a/z/${b=3}}; echo $b      # b=3
6723                         * unset b; unset a; : ${a/z/${b=3}}; echo $b # b not set
6724                         */
6725                        if (val /*&& val[0]*/) {
6726                                /* pattern uses non-standard expansion.
6727                                 * repl should be unbackslashed and globbed
6728                                 * by the usual expansion rules:
6729                                 *  >az >bz
6730                                 *  v='a bz'; echo "${v/a*z/a*z}" #prints "a*z"
6731                                 *  v='a bz'; echo "${v/a*z/\z}"  #prints "z"
6732                                 *  v='a bz'; echo ${v/a*z/a*z}   #prints "az"
6733                                 *  v='a bz'; echo ${v/a*z/\z}    #prints "z"
6734                                 * (note that a*z _pattern_ is never globbed!)
6735                                 */
6736                                char *pattern, *repl, *t;
6737                                pattern = encode_then_expand_vararg(exp_word, /*handle_squotes:*/ 1, /*unbackslash:*/ 0);
6738                                if (!pattern)
6739                                        pattern = xstrdup(exp_word);
6740                                debug_printf_varexp("pattern:'%s'->'%s'\n", exp_word, pattern);
6741                                *p++ = SPECIAL_VAR_SYMBOL;
6742                                exp_word = p;
6743                                p = strchr(p, SPECIAL_VAR_SYMBOL);
6744                                *p = '\0';
6745                                repl = encode_then_expand_vararg(exp_word, /*handle_squotes:*/ 1, /*unbackslash:*/ 1);
6746                                debug_printf_varexp("repl:'%s'->'%s'\n", exp_word, repl);
6747                                /* HACK ALERT. We depend here on the fact that
6748                                 * G.global_argv and results of utoa and get_local_var_value
6749                                 * are actually in writable memory:
6750                                 * replace_pattern momentarily stores NULs there. */
6751                                t = (char*)val;
6752                                to_be_freed = replace_pattern(t,
6753                                                pattern,
6754                                                (repl ? repl : exp_word),
6755                                                exp_op);
6756                                if (to_be_freed) /* at least one replace happened */
6757                                        val = to_be_freed;
6758                                free(pattern);
6759                                free(repl);
6760                        } else {
6761                                /* Unset variable always gives nothing */
6762                                //  a=; echo ${a/*/w}      # "w"
6763                                //  unset a; echo ${a/*/w} # ""
6764                                /* Just skip "replace" part */
6765                                *p++ = SPECIAL_VAR_SYMBOL;
6766                                p = strchr(p, SPECIAL_VAR_SYMBOL);
6767                                *p = '\0';
6768                        }
6769                }
6770#endif /* BASH_PATTERN_SUBST */
6771                else if (exp_op == ':') {
6772#if BASH_SUBSTR && ENABLE_FEATURE_SH_MATH
6773                        /* It's ${var:N[:M]} bashism.
6774                         * Note that in encoded form it has TWO parts:
6775                         * var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL>
6776                         */
6777                        arith_t beg, len;
6778                        unsigned vallen;
6779                        const char *errmsg;
6780
6781                        beg = expand_and_evaluate_arith(exp_word, &errmsg);
6782                        if (errmsg)
6783                                goto empty_result;
6784                        debug_printf_varexp("beg:'%s'=%lld\n", exp_word, (long long)beg);
6785                        *p++ = SPECIAL_VAR_SYMBOL;
6786                        exp_word = p;
6787                        p = strchr(p, SPECIAL_VAR_SYMBOL);
6788                        *p = '\0';
6789                        vallen = val ? strlen(val) : 0;
6790                        if (beg < 0) {
6791                                /* negative beg counts from the end */
6792                                beg = (arith_t)vallen + beg;
6793                        }
6794                        /* If expansion will be empty, do not even evaluate len */
6795                        if (!val || beg < 0 || beg > vallen) {
6796                                /* Why > vallen, not >=? bash:
6797                                 * unset b; a=ab; : ${a:2:${b=3}}; echo $b  # "", b=3 (!!!)
6798                                 * unset b; a=a; : ${a:2:${b=3}}; echo $b   # "", b not set
6799                                 */
6800                                goto empty_result;
6801                        }
6802                        len = expand_and_evaluate_arith(exp_word, &errmsg);
6803                        if (errmsg)
6804                                goto empty_result;
6805                        debug_printf_varexp("len:'%s'=%lld\n", exp_word, (long long)len);
6806                        debug_printf_varexp("from val:'%s'\n", val);
6807                        if (len < 0) {
6808                                /* in bash, len=-n means strlen()-n */
6809                                len = (arith_t)vallen - beg + len;
6810                                if (len < 0) /* bash compat */
6811                                        msg_and_die_if_script("%s: substring expression < 0", var);
6812                        }
6813                        if (len <= 0 || !val /*|| beg >= vallen*/) {
6814 empty_result:
6815                                val = NULL;
6816                        } else {
6817                                /* Paranoia. What if user entered 9999999999999
6818                                 * which fits in arith_t but not int? */
6819                                if (len > INT_MAX)
6820                                        len = INT_MAX;
6821                                val = to_be_freed = xstrndup(val + beg, len);
6822                        }
6823                        debug_printf_varexp("val:'%s'\n", val);
6824#else /* not (HUSH_SUBSTR_EXPANSION && FEATURE_SH_MATH) */
6825                        msg_and_die_if_script("malformed ${%s:...}", var);
6826                        val = NULL;
6827#endif
6828                } else { /* one of "-=+?" */
6829                        /* Standard-mandated substitution ops:
6830                         * ${var?word} - indicate error if unset
6831                         *      If var is unset, word (or a message indicating it is unset
6832                         *      if word is null) is written to standard error
6833                         *      and the shell exits with a non-zero exit status.
6834                         *      Otherwise, the value of var is substituted.
6835                         * ${var-word} - use default value
6836                         *      If var is unset, word is substituted.
6837                         * ${var=word} - assign and use default value
6838                         *      If var is unset, word is assigned to var.
6839                         *      In all cases, final value of var is substituted.
6840                         * ${var+word} - use alternative value
6841                         *      If var is unset, null is substituted.
6842                         *      Otherwise, word is substituted.
6843                         *
6844                         * Word is subjected to tilde expansion, parameter expansion,
6845                         * command substitution, and arithmetic expansion.
6846                         * If word is not needed, it is not expanded.
6847                         *
6848                         * Colon forms (${var:-word}, ${var:=word} etc) do the same,
6849                         * but also treat null var as if it is unset.
6850                         *
6851                         * Word-splitting and single quote behavior:
6852                         *
6853                         * $ f() { for i; do echo "|$i|"; done; }
6854                         *
6855                         * $ x=; f ${x:?'x y' z}; echo $?
6856                         * bash: x: x y z       # neither f nor "echo $?" executes
6857                         * (if interactive, bash does not exit, but merely aborts to prompt. $? is set to 1)
6858                         * $ x=; f "${x:?'x y' z}"
6859                         * bash: x: x y z       # dash prints: dash: x: 'x y' z
6860                         *
6861                         * $ x=; f ${x:='x y' z}
6862                         * |x|
6863                         * |y|
6864                         * |z|
6865                         * $ x=; f "${x:='x y' z}"
6866                         * |'x y' z|
6867                         *
6868                         * $ x=x; f ${x:+'x y' z}
6869                         * |x y|
6870                         * |z|
6871                         * $ x=x; f "${x:+'x y' z}"
6872                         * |'x y' z|
6873                         *
6874                         * $ x=; f ${x:-'x y' z}
6875                         * |x y|
6876                         * |z|
6877                         * $ x=; f "${x:-'x y' z}"
6878                         * |'x y' z|
6879                         */
6880                        int use_word = (!val || ((exp_save == ':') && !val[0]));
6881                        if (exp_op == '+')
6882                                use_word = !use_word;
6883                        debug_printf_expand("expand: op:%c (null:%s) test:%i\n", exp_op,
6884                                        (exp_save == ':') ? "true" : "false", use_word);
6885                        if (use_word) {
6886                                if (exp_op == '+' || exp_op == '-') {
6887                                        /* ${var+word} - use alternative value */
6888                                        /* ${var-word} - use default value */
6889                                        n = encode_then_append_var_plusminus(output, n, exp_word,
6890                                                        /*dquoted:*/ (arg0 & 0x80)
6891                                        );
6892                                        val = NULL;
6893                                } else {
6894                                        /* ${var?word} - indicate error if unset */
6895                                        /* ${var=word} - assign and use default value */
6896                                        to_be_freed = encode_then_expand_vararg(exp_word,
6897                                                        /*handle_squotes:*/ !(arg0 & 0x80),
6898                                                        /*unbackslash:*/ 0
6899                                        );
6900                                        if (to_be_freed)
6901                                                exp_word = to_be_freed;
6902                                        if (exp_op == '?') {
6903                                                /* mimic bash message */
6904                                                msg_and_die_if_script("%s: %s",
6905                                                        var,
6906                                                        exp_word[0]
6907                                                        ? exp_word
6908                                                        : "parameter null or not set"
6909                                                        /* ash has more specific messages, a-la: */
6910                                                        /*: (exp_save == ':' ? "parameter null or not set" : "parameter not set")*/
6911                                                );
6912//TODO: how interactive bash aborts expansion mid-command?
6913//It aborts the entire line, returns to prompt:
6914// $ f() { for i; do echo "|$i|"; done; }; x=; f "${x:?'x y' z}"; echo YO
6915// bash: x: x y z
6916// $
6917// ("echo YO" is not executed, neither the f function call)
6918                                        } else {
6919                                                val = exp_word;
6920                                        }
6921                                        if (exp_op == '=') {
6922                                                /* ${var=[word]} or ${var:=[word]} */
6923                                                if (isdigit(var[0]) || var[0] == '#') {
6924                                                        /* mimic bash message */
6925                                                        msg_and_die_if_script("$%s: cannot assign in this way", var);
6926                                                        val = NULL;
6927                                                } else {
6928                                                        char *new_var = xasprintf("%s=%s", var, val);
6929                                                        set_local_var(new_var, /*flag:*/ 0);
6930                                                }
6931                                        }
6932                                }
6933                        }
6934                } /* one of "-=+?" */
6935
6936                *exp_saveptr = exp_save;
6937        } /* if (exp_op) */
6938
6939        arg[0] = arg0;
6940        *pp = p;
6941
6942        n = append_str_maybe_ifs_split(output, n, first_ch, val);
6943
6944        free(to_be_freed);
6945        return n;
6946}
6947
6948/* Expand all variable references in given string, adding words to list[]
6949 * at n, n+1,... positions. Return updated n (so that list[n] is next one
6950 * to be filled). This routine is extremely tricky: has to deal with
6951 * variables/parameters with whitespace, $* and $@, and constructs like
6952 * 'echo -$*-'. If you play here, you must run testsuite afterwards! */
6953static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
6954{
6955        /* output->o_expflags & EXP_FLAG_SINGLEWORD (0x80) if we are in
6956         * expansion of right-hand side of assignment == 1-element expand.
6957         */
6958        char cant_be_null = 0; /* only bit 0x80 matters */
6959        char *p;
6960
6961        debug_printf_expand("expand_vars_to_list: arg:'%s' singleword:%x\n", arg,
6962                        !!(output->o_expflags & EXP_FLAG_SINGLEWORD));
6963        debug_print_list("expand_vars_to_list[0]", output, n);
6964
6965        while ((p = strchr(arg, SPECIAL_VAR_SYMBOL)) != NULL) {
6966                char first_ch;
6967#if ENABLE_FEATURE_SH_MATH
6968                char arith_buf[sizeof(arith_t)*3 + 2];
6969#endif
6970
6971                if (output->ended_in_ifs) {
6972                        o_addchr(output, '\0');
6973                        n = o_save_ptr(output, n);
6974                        output->ended_in_ifs = 0;
6975                }
6976
6977                o_addblock(output, arg, p - arg);
6978                debug_print_list("expand_vars_to_list[1]", output, n);
6979                arg = ++p;
6980                p = strchr(p, SPECIAL_VAR_SYMBOL);
6981
6982                /* Fetch special var name (if it is indeed one of them)
6983                 * and quote bit, force the bit on if singleword expansion -
6984                 * important for not getting v=$@ expand to many words. */
6985                first_ch = arg[0] | (output->o_expflags & EXP_FLAG_SINGLEWORD);
6986
6987                /* Is this variable quoted and thus expansion can't be null?
6988                 * "$@" is special. Even if quoted, it can still
6989                 * expand to nothing (not even an empty string),
6990                 * thus it is excluded. */
6991                if ((first_ch & 0x7f) != '@')
6992                        cant_be_null |= first_ch;
6993
6994                switch (first_ch & 0x7f) {
6995                /* Highest bit in first_ch indicates that var is double-quoted */
6996                case '*':
6997                case '@': {
6998                        int i;
6999                        if (!G.global_argv[1])
7000                                break;
7001                        i = 1;
7002                        cant_be_null |= first_ch; /* do it for "$@" _now_, when we know it's not empty */
7003                        if (!(first_ch & 0x80)) { /* unquoted $* or $@ */
7004                                while (G.global_argv[i]) {
7005                                        n = expand_on_ifs(output, n, G.global_argv[i]);
7006                                        debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, G.global_argc - 1);
7007                                        if (G.global_argv[i++][0] && G.global_argv[i]) {
7008                                                /* this argv[] is not empty and not last:
7009                                                 * put terminating NUL, start new word */
7010                                                o_addchr(output, '\0');
7011                                                debug_print_list("expand_vars_to_list[2]", output, n);
7012                                                n = o_save_ptr(output, n);
7013                                                debug_print_list("expand_vars_to_list[3]", output, n);
7014                                        }
7015                                }
7016                        } else
7017                        /* If EXP_FLAG_SINGLEWORD, we handle assignment 'a=....$@.....'
7018                         * and in this case should treat it like '$*' - see 'else...' below */
7019                        if (first_ch == (char)('@'|0x80)  /* quoted $@ */
7020                         && !(output->o_expflags & EXP_FLAG_SINGLEWORD) /* not v="$@" case */
7021                        ) {
7022                                while (1) {
7023                                        o_addQstr(output, G.global_argv[i]);
7024                                        if (++i >= G.global_argc)
7025                                                break;
7026                                        o_addchr(output, '\0');
7027                                        debug_print_list("expand_vars_to_list[4]", output, n);
7028                                        n = o_save_ptr(output, n);
7029                                }
7030                        } else { /* quoted $* (or v="$@" case): add as one word */
7031                                while (1) {
7032                                        o_addQstr(output, G.global_argv[i]);
7033                                        if (!G.global_argv[++i])
7034                                                break;
7035                                        if (G.ifs[0])
7036                                                o_addchr(output, G.ifs[0]);
7037                                }
7038                                output->has_quoted_part = 1;
7039                        }
7040                        break;
7041                }
7042                case SPECIAL_VAR_SYMBOL: {
7043                        /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_SYMBOL> */
7044                        /* "Empty variable", used to make "" etc to not disappear */
7045                        output->has_quoted_part = 1;
7046                        cant_be_null = 0x80;
7047                        arg++;
7048                        break;
7049                }
7050                case SPECIAL_VAR_QUOTED_SVS:
7051                        /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_QUOTED_SVS><SPECIAL_VAR_SYMBOL> */
7052                        /* "^C variable", represents literal ^C char (possible in scripts) */
7053                        o_addchr(output, SPECIAL_VAR_SYMBOL);
7054                        arg++;
7055                        break;
7056#if ENABLE_HUSH_TICK
7057                case '`': {
7058                        /* <SPECIAL_VAR_SYMBOL>`cmd<SPECIAL_VAR_SYMBOL> */
7059                        o_string subst_result = NULL_O_STRING;
7060
7061                        *p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */
7062                        arg++;
7063                        /* Can't just stuff it into output o_string,
7064                         * expanded result may need to be globbed
7065                         * and $IFS-split */
7066                        debug_printf_subst("SUBST '%s' first_ch %x\n", arg, first_ch);
7067                        G.last_exitcode = process_command_subs(&subst_result, arg);
7068                        G.expand_exitcode = G.last_exitcode;
7069                        debug_printf_subst("SUBST RES:%d '%s'\n", G.last_exitcode, subst_result.data);
7070                        n = append_str_maybe_ifs_split(output, n, first_ch, subst_result.data);
7071                        o_free(&subst_result);
7072                        break;
7073                }
7074#endif
7075#if ENABLE_FEATURE_SH_MATH
7076                case '+': {
7077                        /* <SPECIAL_VAR_SYMBOL>+arith<SPECIAL_VAR_SYMBOL> */
7078                        arith_t res;
7079
7080                        arg++; /* skip '+' */
7081                        *p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */
7082                        debug_printf_subst("ARITH '%s' first_ch %x\n", arg, first_ch);
7083                        res = expand_and_evaluate_arith(arg, NULL);
7084                        debug_printf_subst("ARITH RES '"ARITH_FMT"'\n", res);
7085                        sprintf(arith_buf, ARITH_FMT, res);
7086                        if (res < 0
7087                         && first_ch == (char)('+'|0x80)
7088                        /* && (output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS) */
7089                        ) {
7090                                /* Quoted negative ariths, like filename[0"$((-9))"],
7091                                 * should not be interpreted as glob ranges.
7092                                 * Convert leading '-' to '\-':
7093                                 */
7094                                o_grow_by(output, 1);
7095                                output->data[output->length++] = '\\';
7096                        }
7097                        o_addstr(output, arith_buf);
7098                        break;
7099                }
7100#endif
7101                default:
7102                        /* <SPECIAL_VAR_SYMBOL>varname[ops]<SPECIAL_VAR_SYMBOL> */
7103                        n = expand_one_var(output, n, first_ch, arg, &p);
7104                        break;
7105                } /* switch (char after <SPECIAL_VAR_SYMBOL>) */
7106
7107                /* Restore NULL'ed SPECIAL_VAR_SYMBOL.
7108                 * Do the check to avoid writing to a const string. */
7109                if (*p != SPECIAL_VAR_SYMBOL)
7110                        *p = SPECIAL_VAR_SYMBOL;
7111                arg = ++p;
7112        } /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */
7113
7114        if (*arg) {
7115                /* handle trailing string */
7116                if (output->ended_in_ifs) {
7117                        o_addchr(output, '\0');
7118                        n = o_save_ptr(output, n);
7119                }
7120                debug_print_list("expand_vars_to_list[a]", output, n);
7121                /* this part is literal, and it was already pre-quoted
7122                 * if needed (much earlier), do not use o_addQstr here!
7123                 */
7124                o_addstr(output, arg);
7125                debug_print_list("expand_vars_to_list[b]", output, n);
7126        } else
7127        if (output->length == o_get_last_ptr(output, n) /* expansion is empty */
7128         && !(cant_be_null & 0x80)   /* and all vars were not quoted */
7129         && !output->has_quoted_part
7130        ) {
7131                n--;
7132                /* allow to reuse list[n] later without re-growth */
7133                output->has_empty_slot = 1;
7134        }
7135
7136        return n;
7137}
7138
7139static char **expand_variables(char **argv, unsigned expflags)
7140{
7141        int n;
7142        char **list;
7143        o_string output = NULL_O_STRING;
7144
7145        output.o_expflags = expflags;
7146
7147        n = 0;
7148        for (;;) {
7149                /* go to next list[n] */
7150                output.ended_in_ifs = 0;
7151                n = o_save_ptr(&output, n);
7152
7153                if (!*argv)
7154                        break;
7155
7156                /* expand argv[i] */
7157                n = expand_vars_to_list(&output, n, *argv++);
7158                /* if (!output->has_empty_slot) -- need this?? */
7159                        o_addchr(&output, '\0');
7160        }
7161        debug_print_list("expand_variables", &output, n);
7162
7163        /* output.data (malloced in one block) gets returned in "list" */
7164        list = o_finalize_list(&output, n);
7165        debug_print_strings("expand_variables[1]", list);
7166        return list;
7167}
7168
7169static char **expand_strvec_to_strvec(char **argv)
7170{
7171        return expand_variables(argv, EXP_FLAG_GLOB | EXP_FLAG_ESC_GLOB_CHARS);
7172}
7173
7174#if defined(CMD_SINGLEWORD_NOGLOB) || defined(CMD_TEST2_SINGLEWORD_NOGLOB)
7175static char **expand_strvec_to_strvec_singleword_noglob(char **argv)
7176{
7177        return expand_variables(argv, EXP_FLAG_SINGLEWORD);
7178}
7179#endif
7180
7181/* Used for expansion of right hand of assignments,
7182 * $((...)), heredocs, variable expansion parts.
7183 *
7184 * NB: should NOT do globbing!
7185 * "export v=/bin/c*; env | grep ^v=" outputs "v=/bin/c*"
7186 */
7187static char *expand_string_to_string(const char *str, int EXP_flags, int do_unbackslash)
7188{
7189#if !BASH_PATTERN_SUBST && !ENABLE_HUSH_CASE
7190        const int do_unbackslash = 1;
7191        const int EXP_flags = EXP_FLAG_ESC_GLOB_CHARS;
7192#endif
7193        char *argv[2], **list;
7194
7195        debug_printf_expand("string_to_string<='%s'\n", str);
7196        /* This is generally an optimization, but it also
7197         * handles "", which otherwise trips over !list[0] check below.
7198         * (is this ever happens that we actually get str="" here?)
7199         */
7200        if (!strchr(str, SPECIAL_VAR_SYMBOL) && !strchr(str, '\\')) {
7201                //TODO: Can use on strings with \ too, just unbackslash() them?
7202                debug_printf_expand("string_to_string(fast)=>'%s'\n", str);
7203                return xstrdup(str);
7204        }
7205
7206        argv[0] = (char*)str;
7207        argv[1] = NULL;
7208        list = expand_variables(argv, EXP_flags | EXP_FLAG_SINGLEWORD);
7209        if (!list[0]) {
7210                /* Example where it happens:
7211                 * x=; echo ${x:-"$@"}
7212                 */
7213                ((char*)list)[0] = '\0';
7214        } else {
7215                if (HUSH_DEBUG)
7216                        if (list[1])
7217                                bb_simple_error_msg_and_die("BUG in varexp2");
7218                /* actually, just move string 2*sizeof(char*) bytes back */
7219                overlapping_strcpy((char*)list, list[0]);
7220                if (do_unbackslash)
7221                        unbackslash((char*)list);
7222        }
7223        debug_printf_expand("string_to_string=>'%s'\n", (char*)list);
7224        return (char*)list;
7225}
7226
7227#if 0
7228static char* expand_strvec_to_string(char **argv)
7229{
7230        char **list;
7231
7232        list = expand_variables(argv, EXP_FLAG_SINGLEWORD);
7233        /* Convert all NULs to spaces */
7234        if (list[0]) {
7235                int n = 1;
7236                while (list[n]) {
7237                        if (HUSH_DEBUG)
7238                                if (list[n-1] + strlen(list[n-1]) + 1 != list[n])
7239                                        bb_error_msg_and_die("BUG in varexp3");
7240                        /* bash uses ' ' regardless of $IFS contents */
7241                        list[n][-1] = ' ';
7242                        n++;
7243                }
7244        }
7245        overlapping_strcpy((char*)list, list[0] ? list[0] : "");
7246        debug_printf_expand("strvec_to_string='%s'\n", (char*)list);
7247        return (char*)list;
7248}
7249#endif
7250
7251static char **expand_assignments(char **argv, int count)
7252{
7253        int i;
7254        char **p;
7255
7256        G.expanded_assignments = p = NULL;
7257        /* Expand assignments into one string each */
7258        for (i = 0; i < count; i++) {
7259                p = add_string_to_strings(p,
7260                        expand_string_to_string(argv[i],
7261                                EXP_FLAG_ESC_GLOB_CHARS,
7262                                /*unbackslash:*/ 1
7263                        )
7264                );
7265                G.expanded_assignments = p;
7266        }
7267        G.expanded_assignments = NULL;
7268        return p;
7269}
7270
7271
7272static void switch_off_special_sigs(unsigned mask)
7273{
7274        unsigned sig = 0;
7275        while ((mask >>= 1) != 0) {
7276                sig++;
7277                if (!(mask & 1))
7278                        continue;
7279#if ENABLE_HUSH_TRAP
7280                if (G_traps) {
7281                        if (G_traps[sig] && !G_traps[sig][0])
7282                                /* trap is '', has to remain SIG_IGN */
7283                                continue;
7284                        free(G_traps[sig]);
7285                        G_traps[sig] = NULL;
7286                }
7287#endif
7288                /* We are here only if no trap or trap was not '' */
7289                install_sighandler(sig, SIG_DFL);
7290        }
7291}
7292
7293#if BB_MMU
7294/* never called */
7295void re_execute_shell(char ***to_free, const char *s,
7296                char *g_argv0, char **g_argv,
7297                char **builtin_argv) NORETURN;
7298
7299static void reset_traps_to_defaults(void)
7300{
7301        /* This function is always called in a child shell
7302         * after fork (not vfork, NOMMU doesn't use this function).
7303         */
7304        IF_HUSH_TRAP(unsigned sig;)
7305        unsigned mask;
7306
7307        /* Child shells are not interactive.
7308         * SIGTTIN/SIGTTOU/SIGTSTP should not have special handling.
7309         * Testcase: (while :; do :; done) + ^Z should background.
7310         * Same goes for SIGTERM, SIGHUP, SIGINT.
7311         */
7312        mask = (G.special_sig_mask & SPECIAL_INTERACTIVE_SIGS) | G_fatal_sig_mask;
7313        if (!G_traps && !mask)
7314                return; /* already no traps and no special sigs */
7315
7316        /* Switch off special sigs */
7317        switch_off_special_sigs(mask);
7318# if ENABLE_HUSH_JOB
7319        G_fatal_sig_mask = 0;
7320# endif
7321        G.special_sig_mask &= ~SPECIAL_INTERACTIVE_SIGS;
7322        /* SIGQUIT,SIGCHLD and maybe SPECIAL_JOBSTOP_SIGS
7323         * remain set in G.special_sig_mask */
7324
7325# if ENABLE_HUSH_TRAP
7326        if (!G_traps)
7327                return;
7328
7329        /* Reset all sigs to default except ones with empty traps */
7330        for (sig = 0; sig < NSIG; sig++) {
7331                if (!G_traps[sig])
7332                        continue; /* no trap: nothing to do */
7333                if (!G_traps[sig][0])
7334                        continue; /* empty trap: has to remain SIG_IGN */
7335                /* sig has non-empty trap, reset it: */
7336                free(G_traps[sig]);
7337                G_traps[sig] = NULL;
7338                /* There is no signal for trap 0 (EXIT) */
7339                if (sig == 0)
7340                        continue;
7341                install_sighandler(sig, pick_sighandler(sig));
7342        }
7343# endif
7344}
7345
7346#else /* !BB_MMU */
7347
7348static void re_execute_shell(char ***to_free, const char *s,
7349                char *g_argv0, char **g_argv,
7350                char **builtin_argv) NORETURN;
7351static void re_execute_shell(char ***to_free, const char *s,
7352                char *g_argv0, char **g_argv,
7353                char **builtin_argv)
7354{
7355# define NOMMU_HACK_FMT ("-$%x:%x:%x:%x:%x:%llx" IF_HUSH_LOOPS(":%x"))
7356        /* delims + 2 * (number of bytes in printed hex numbers) */
7357        char param_buf[sizeof(NOMMU_HACK_FMT) + 2 * (sizeof(int)*6 + sizeof(long long)*1)];
7358        char *heredoc_argv[4];
7359        struct variable *cur;
7360# if ENABLE_HUSH_FUNCTIONS
7361        struct function *funcp;
7362# endif
7363        char **argv, **pp;
7364        unsigned cnt;
7365        unsigned long long empty_trap_mask;
7366
7367        if (!g_argv0) { /* heredoc */
7368                argv = heredoc_argv;
7369                argv[0] = (char *) G.argv0_for_re_execing;
7370                argv[1] = (char *) "-<";
7371                argv[2] = (char *) s;
7372                argv[3] = NULL;
7373                pp = &argv[3]; /* used as pointer to empty environment */
7374                goto do_exec;
7375        }
7376
7377        cnt = 0;
7378        pp = builtin_argv;
7379        if (pp) while (*pp++)
7380                cnt++;
7381
7382        empty_trap_mask = 0;
7383        if (G_traps) {
7384                int sig;
7385                for (sig = 1; sig < NSIG; sig++) {
7386                        if (G_traps[sig] && !G_traps[sig][0])
7387                                empty_trap_mask |= 1LL << sig;
7388                }
7389        }
7390
7391        sprintf(param_buf, NOMMU_HACK_FMT
7392                        , (unsigned) G.root_pid
7393                        , (unsigned) G.root_ppid
7394                        , (unsigned) G.last_bg_pid
7395                        , (unsigned) G.last_exitcode
7396                        , cnt
7397                        , empty_trap_mask
7398                        IF_HUSH_LOOPS(, G.depth_of_loop)
7399                        );
7400# undef NOMMU_HACK_FMT
7401        /* 1:hush 2:-$<pid>:<pid>:<exitcode>:<etc...> <vars...> <funcs...>
7402         * 3:-c 4:<cmd> 5:<arg0> <argN...> 6:NULL
7403         */
7404        cnt += 6;
7405        for (cur = G.top_var; cur; cur = cur->next) {
7406                if (!cur->flg_export || cur->flg_read_only)
7407                        cnt += 2;
7408        }
7409# if ENABLE_HUSH_FUNCTIONS
7410        for (funcp = G.top_func; funcp; funcp = funcp->next)
7411                cnt += 3;
7412# endif
7413        pp = g_argv;
7414        while (*pp++)
7415                cnt++;
7416        *to_free = argv = pp = xzalloc(sizeof(argv[0]) * cnt);
7417        *pp++ = (char *) G.argv0_for_re_execing;
7418        *pp++ = param_buf;
7419        for (cur = G.top_var; cur; cur = cur->next) {
7420                if (strcmp(cur->varstr, hush_version_str) == 0)
7421                        continue;
7422                if (cur->flg_read_only) {
7423                        *pp++ = (char *) "-R";
7424                        *pp++ = cur->varstr;
7425                } else if (!cur->flg_export) {
7426                        *pp++ = (char *) "-V";
7427                        *pp++ = cur->varstr;
7428                }
7429        }
7430# if ENABLE_HUSH_FUNCTIONS
7431        for (funcp = G.top_func; funcp; funcp = funcp->next) {
7432                *pp++ = (char *) "-F";
7433                *pp++ = funcp->name;
7434                *pp++ = funcp->body_as_string;
7435        }
7436# endif
7437        /* We can pass activated traps here. Say, -Tnn:trap_string
7438         *
7439         * However, POSIX says that subshells reset signals with traps
7440         * to SIG_DFL.
7441         * I tested bash-3.2 and it not only does that with true subshells
7442         * of the form ( list ), but with any forked children shells.
7443         * I set trap "echo W" WINCH; and then tried:
7444         *
7445         * { echo 1; sleep 20; echo 2; } &
7446         * while true; do echo 1; sleep 20; echo 2; break; done &
7447         * true | { echo 1; sleep 20; echo 2; } | cat
7448         *
7449         * In all these cases sending SIGWINCH to the child shell
7450         * did not run the trap. If I add trap "echo V" WINCH;
7451         * _inside_ group (just before echo 1), it works.
7452         *
7453         * I conclude it means we don't need to pass active traps here.
7454         */
7455        *pp++ = (char *) "-c";
7456        *pp++ = (char *) s;
7457        if (builtin_argv) {
7458                while (*++builtin_argv)
7459                        *pp++ = *builtin_argv;
7460                *pp++ = (char *) "";
7461        }
7462        *pp++ = g_argv0;
7463        while (*g_argv)
7464                *pp++ = *g_argv++;
7465        /* *pp = NULL; - is already there */
7466        pp = environ;
7467
7468 do_exec:
7469        debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s);
7470        /* Don't propagate SIG_IGN to the child */
7471        if (SPECIAL_JOBSTOP_SIGS != 0)
7472                switch_off_special_sigs(G.special_sig_mask & SPECIAL_JOBSTOP_SIGS);
7473        execve(bb_busybox_exec_path, argv, pp);
7474        /* Fallback. Useful for init=/bin/hush usage etc */
7475        if (argv[0][0] == '/')
7476                execve(argv[0], argv, pp);
7477        xfunc_error_retval = 127;
7478        bb_simple_error_msg_and_die("can't re-execute the shell");
7479}
7480#endif  /* !BB_MMU */
7481
7482
7483static int run_and_free_list(struct pipe *pi);
7484
7485/* Executing from string: eval, sh -c '...'
7486 *          or from file: /etc/profile, . file, sh <script>, sh (intereactive)
7487 * end_trigger controls how often we stop parsing
7488 * NUL: parse all, execute, return
7489 * ';': parse till ';' or newline, execute, repeat till EOF
7490 */
7491static void parse_and_run_stream(struct in_str *inp, int end_trigger)
7492{
7493        /* Why we need empty flag?
7494         * An obscure corner case "false; ``; echo $?":
7495         * empty command in `` should still set $? to 0.
7496         * But we can't just set $? to 0 at the start,
7497         * this breaks "false; echo `echo $?`" case.
7498         */
7499        bool empty = 1;
7500        while (1) {
7501                struct pipe *pipe_list;
7502
7503#if ENABLE_HUSH_INTERACTIVE
7504                if (end_trigger == ';') {
7505                        G.promptmode = 0; /* PS1 */
7506                        debug_printf_prompt("%s promptmode=%d\n", __func__, G.promptmode);
7507                }
7508#endif
7509                pipe_list = parse_stream(NULL, NULL, inp, end_trigger);
7510                if (!pipe_list || pipe_list == ERR_PTR) { /* EOF/error */
7511                        /* If we are in "big" script
7512                         * (not in `cmd` or something similar)...
7513                         */
7514                        if (pipe_list == ERR_PTR && end_trigger == ';') {
7515                                /* Discard cached input (rest of line) */
7516                                int ch = inp->last_char;
7517                                while (ch != EOF && ch != '\n') {
7518                                        //bb_error_msg("Discarded:'%c'", ch);
7519                                        ch = i_getch(inp);
7520                                }
7521                                /* Force prompt */
7522                                inp->p = NULL;
7523                                /* This stream isn't empty */
7524                                empty = 0;
7525                                continue;
7526                        }
7527                        if (!pipe_list && empty)
7528                                G.last_exitcode = 0;
7529                        break;
7530                }
7531                debug_print_tree(pipe_list, 0);
7532                debug_printf_exec("parse_and_run_stream: run_and_free_list\n");
7533                run_and_free_list(pipe_list);
7534                empty = 0;
7535                if (G_flag_return_in_progress == 1)
7536                        break;
7537        }
7538}
7539
7540static void parse_and_run_string(const char *s)
7541{
7542        struct in_str input;
7543        //IF_HUSH_LINENO_VAR(unsigned sv = G.parse_lineno;)
7544
7545        setup_string_in_str(&input, s);
7546        parse_and_run_stream(&input, '\0');
7547        //IF_HUSH_LINENO_VAR(G.parse_lineno = sv;)
7548}
7549
7550static void parse_and_run_file(HFILE *fp)
7551{
7552        struct in_str input;
7553        IF_HUSH_LINENO_VAR(unsigned sv = G.parse_lineno;)
7554
7555        IF_HUSH_LINENO_VAR(G.parse_lineno = 1;)
7556        setup_file_in_str(&input, fp);
7557        parse_and_run_stream(&input, ';');
7558        IF_HUSH_LINENO_VAR(G.parse_lineno = sv;)
7559}
7560
7561#if ENABLE_HUSH_TICK
7562static int generate_stream_from_string(const char *s, pid_t *pid_p)
7563{
7564        pid_t pid;
7565        int channel[2];
7566# if !BB_MMU
7567        char **to_free = NULL;
7568# endif
7569
7570        xpipe(channel);
7571        pid = BB_MMU ? xfork() : xvfork();
7572        if (pid == 0) { /* child */
7573                disable_restore_tty_pgrp_on_exit();
7574                /* Process substitution is not considered to be usual
7575                 * 'command execution'.
7576                 * SUSv3 says ctrl-Z should be ignored, ctrl-C should not.
7577                 */
7578                bb_signals(0
7579                        + (1 << SIGTSTP)
7580                        + (1 << SIGTTIN)
7581                        + (1 << SIGTTOU)
7582                        , SIG_IGN);
7583                close(channel[0]); /* NB: close _first_, then move fd! */
7584                xmove_fd(channel[1], 1);
7585# if ENABLE_HUSH_TRAP
7586                /* Awful hack for `trap` or $(trap).
7587                 *
7588                 * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
7589                 * contains an example where "trap" is executed in a subshell:
7590                 *
7591                 * save_traps=$(trap)
7592                 * ...
7593                 * eval "$save_traps"
7594                 *
7595                 * Standard does not say that "trap" in subshell shall print
7596                 * parent shell's traps. It only says that its output
7597                 * must have suitable form, but then, in the above example
7598                 * (which is not supposed to be normative), it implies that.
7599                 *
7600                 * bash (and probably other shell) does implement it
7601                 * (traps are reset to defaults, but "trap" still shows them),
7602                 * but as a result, "trap" logic is hopelessly messed up:
7603                 *
7604                 * # trap
7605                 * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
7606                 * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
7607                 * # true | trap   <--- trap is in subshell - no output (ditto)
7608                 * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
7609                 * trap -- 'echo Ho' SIGWINCH
7610                 * # echo `(trap)`         <--- in subshell in subshell - output
7611                 * trap -- 'echo Ho' SIGWINCH
7612                 * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
7613                 * trap -- 'echo Ho' SIGWINCH
7614                 *
7615                 * The rules when to forget and when to not forget traps
7616                 * get really complex and nonsensical.
7617                 *
7618                 * Our solution: ONLY bare $(trap) or `trap` is special.
7619                 */
7620                s = skip_whitespace(s);
7621                if (is_prefixed_with(s, "trap")
7622                 && skip_whitespace(s + 4)[0] == '\0'
7623                ) {
7624                        static const char *const argv[] = { NULL, NULL };
7625                        builtin_trap((char**)argv);
7626                        fflush_all(); /* important */
7627                        _exit(0);
7628                }
7629# endif
7630# if BB_MMU
7631                /* Prevent it from trying to handle ctrl-z etc */
7632                IF_HUSH_JOB(G.run_list_level = 1;)
7633                CLEAR_RANDOM_T(&G.random_gen); /* or else $RANDOM repeats in child */
7634                reset_traps_to_defaults();
7635                IF_HUSH_MODE_X(G.x_mode_depth++;)
7636                //bb_error_msg("%s: ++x_mode_depth=%d", __func__, G.x_mode_depth);
7637                parse_and_run_string(s);
7638                _exit(G.last_exitcode);
7639# else
7640        /* We re-execute after vfork on NOMMU. This makes this script safe:
7641         * yes "0123456789012345678901234567890" | dd bs=32 count=64k >BIG
7642         * huge=`cat BIG` # was blocking here forever
7643         * echo OK
7644         */
7645                re_execute_shell(&to_free,
7646                                s,
7647                                G.global_argv[0],
7648                                G.global_argv + 1,
7649                                NULL);
7650# endif
7651        }
7652
7653        /* parent */
7654        *pid_p = pid;
7655# if ENABLE_HUSH_FAST
7656        G.count_SIGCHLD++;
7657//bb_error_msg("[%d] fork in generate_stream_from_string:"
7658//              " G.count_SIGCHLD:%d G.handled_SIGCHLD:%d",
7659//              getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
7660# endif
7661        enable_restore_tty_pgrp_on_exit();
7662# if !BB_MMU
7663        free(to_free);
7664# endif
7665        close(channel[1]);
7666        return channel[0];
7667}
7668
7669/* Return code is exit status of the process that is run. */
7670static int process_command_subs(o_string *dest, const char *s)
7671{
7672        FILE *fp;
7673        pid_t pid;
7674        int status, ch, eol_cnt;
7675
7676        fp = xfdopen_for_read(generate_stream_from_string(s, &pid));
7677
7678        /* Now send results of command back into original context */
7679        eol_cnt = 0;
7680        while ((ch = getc(fp)) != EOF) {
7681                if (ch == '\0')
7682                        continue;
7683                if (ch == '\n') {
7684                        eol_cnt++;
7685                        continue;
7686                }
7687                while (eol_cnt) {
7688                        o_addchr(dest, '\n');
7689                        eol_cnt--;
7690                }
7691                o_addQchr(dest, ch);
7692        }
7693
7694        debug_printf("done reading from `cmd` pipe, closing it\n");
7695        fclose(fp);
7696        /* We need to extract exitcode. Test case
7697         * "true; echo `sleep 1; false` $?"
7698         * should print 1 */
7699        safe_waitpid(pid, &status, 0);
7700        debug_printf("child exited. returning its exitcode:%d\n", WEXITSTATUS(status));
7701        return WEXITSTATUS(status);
7702}
7703#endif /* ENABLE_HUSH_TICK */
7704
7705
7706static void setup_heredoc(struct redir_struct *redir)
7707{
7708        struct fd_pair pair;
7709        pid_t pid;
7710        int len, written;
7711        /* the _body_ of heredoc (misleading field name) */
7712        const char *heredoc = redir->rd_filename;
7713        char *expanded;
7714#if !BB_MMU
7715        char **to_free;
7716#endif
7717
7718        expanded = NULL;
7719        if (!(redir->rd_dup & HEREDOC_QUOTED)) {
7720                expanded = encode_then_expand_string(heredoc);
7721                if (expanded)
7722                        heredoc = expanded;
7723        }
7724        len = strlen(heredoc);
7725
7726        close(redir->rd_fd); /* often saves dup2+close in xmove_fd */
7727        xpiped_pair(pair);
7728        xmove_fd(pair.rd, redir->rd_fd);
7729
7730        /* Try writing without forking. Newer kernels have
7731         * dynamically growing pipes. Must use non-blocking write! */
7732        ndelay_on(pair.wr);
7733        while (1) {
7734                written = write(pair.wr, heredoc, len);
7735                if (written <= 0)
7736                        break;
7737                len -= written;
7738                if (len == 0) {
7739                        close(pair.wr);
7740                        free(expanded);
7741                        return;
7742                }
7743                heredoc += written;
7744        }
7745        ndelay_off(pair.wr);
7746
7747        /* Okay, pipe buffer was not big enough */
7748        /* Note: we must not create a stray child (bastard? :)
7749         * for the unsuspecting parent process. Child creates a grandchild
7750         * and exits before parent execs the process which consumes heredoc
7751         * (that exec happens after we return from this function) */
7752#if !BB_MMU
7753        to_free = NULL;
7754#endif
7755        pid = xvfork();
7756        if (pid == 0) {
7757                /* child */
7758                disable_restore_tty_pgrp_on_exit();
7759                pid = BB_MMU ? xfork() : xvfork();
7760                if (pid != 0)
7761                        _exit(0);
7762                /* grandchild */
7763                close(redir->rd_fd); /* read side of the pipe */
7764#if BB_MMU
7765                full_write(pair.wr, heredoc, len); /* may loop or block */
7766                _exit(0);
7767#else
7768                /* Delegate blocking writes to another process */
7769                xmove_fd(pair.wr, STDOUT_FILENO);
7770                re_execute_shell(&to_free, heredoc, NULL, NULL, NULL);
7771#endif
7772        }
7773        /* parent */
7774#if ENABLE_HUSH_FAST
7775        G.count_SIGCHLD++;
7776//bb_error_msg("[%d] fork in setup_heredoc: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
7777#endif
7778        enable_restore_tty_pgrp_on_exit();
7779#if !BB_MMU
7780        free(to_free);
7781#endif
7782        close(pair.wr);
7783        free(expanded);
7784        wait(NULL); /* wait till child has died */
7785}
7786
7787struct squirrel {
7788        int orig_fd;
7789        int moved_to;
7790        /* moved_to = n: fd was moved to n; restore back to orig_fd after redir */
7791        /* moved_to = -1: fd was opened by redirect; close orig_fd after redir */
7792};
7793
7794static struct squirrel *append_squirrel(struct squirrel *sq, int i, int orig, int moved)
7795{
7796        sq = xrealloc(sq, (i + 2) * sizeof(sq[0]));
7797        sq[i].orig_fd = orig;
7798        sq[i].moved_to = moved;
7799        sq[i+1].orig_fd = -1; /* end marker */
7800        return sq;
7801}
7802
7803static struct squirrel *add_squirrel(struct squirrel *sq, int fd, int avoid_fd)
7804{
7805        int moved_to;
7806        int i;
7807
7808        i = 0;
7809        if (sq) for (; sq[i].orig_fd >= 0; i++) {
7810                /* If we collide with an already moved fd... */
7811                if (fd == sq[i].moved_to) {
7812                        sq[i].moved_to = dup_CLOEXEC(sq[i].moved_to, avoid_fd);
7813                        debug_printf_redir("redirect_fd %d: already busy, moving to %d\n", fd, sq[i].moved_to);
7814                        if (sq[i].moved_to < 0) /* what? */
7815                                xfunc_die();
7816                        return sq;
7817                }
7818                if (fd == sq[i].orig_fd) {
7819                        /* Example: echo Hello >/dev/null 1>&2 */
7820                        debug_printf_redir("redirect_fd %d: already moved\n", fd);
7821                        return sq;
7822                }
7823        }
7824
7825        /* If this fd is open, we move and remember it; if it's closed, moved_to = -1 */
7826        moved_to = dup_CLOEXEC(fd, avoid_fd);
7827        debug_printf_redir("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, moved_to);
7828        if (moved_to < 0 && errno != EBADF)
7829                xfunc_die();
7830        return append_squirrel(sq, i, fd, moved_to);
7831}
7832
7833static struct squirrel *add_squirrel_closed(struct squirrel *sq, int fd)
7834{
7835        int i;
7836
7837        i = 0;
7838        if (sq) for (; sq[i].orig_fd >= 0; i++) {
7839                /* If we collide with an already moved fd... */
7840                if (fd == sq[i].orig_fd) {
7841                        /* Examples:
7842                         * "echo 3>FILE 3>&- 3>FILE"
7843                         * "echo 3>&- 3>FILE"
7844                         * No need for last redirect to insert
7845                         * another "need to close 3" indicator.
7846                         */
7847                        debug_printf_redir("redirect_fd %d: already moved or closed\n", fd);
7848                        return sq;
7849                }
7850        }
7851
7852        debug_printf_redir("redirect_fd %d: previous fd was closed\n", fd);
7853        return append_squirrel(sq, i, fd, -1);
7854}
7855
7856/* fd: redirect wants this fd to be used (e.g. 3>file).
7857 * Move all conflicting internally used fds,
7858 * and remember them so that we can restore them later.
7859 */
7860static int save_fd_on_redirect(int fd, int avoid_fd, struct squirrel **sqp)
7861{
7862        if (avoid_fd < 9) /* the important case here is that it can be -1 */
7863                avoid_fd = 9;
7864
7865#if ENABLE_HUSH_INTERACTIVE
7866        if (fd != 0 /* don't trigger for G_interactive_fd == 0 (that's "not interactive" flag) */
7867         && fd == G_interactive_fd
7868        ) {
7869                /* Testcase: "ls -l /proc/$$/fd 255>&-" should work */
7870                G_interactive_fd = xdup_CLOEXEC_and_close(G_interactive_fd, avoid_fd);
7871                debug_printf_redir("redirect_fd %d: matches interactive_fd, moving it to %d\n", fd, G_interactive_fd);
7872                return 1; /* "we closed fd" */
7873        }
7874#endif
7875        /* Are we called from setup_redirects(squirrel==NULL)
7876         * in redirect in a [v]forked child?
7877         */
7878        if (sqp == NULL) {
7879                /* No need to move script fds.
7880                 * For NOMMU case, it's actively wrong: we'd change ->fd
7881                 * fields in memory for the parent, but parent's fds
7882                 * aren't moved, it would use wrong fd!
7883                 * Reproducer: "cmd 3>FILE" in script.
7884                 * If we would call move_HFILEs_on_redirect(), child would:
7885                 *  fcntl64(3, F_DUPFD_CLOEXEC, 10)   = 10
7886                 *  close(3)                          = 0
7887                 * and change ->fd to 10 if fd#3 is a script fd. WRONG.
7888                 */
7889                //bb_error_msg("sqp == NULL: [v]forked child");
7890                return 0;
7891        }
7892
7893        /* If this one of script's fds? */
7894        if (move_HFILEs_on_redirect(fd, avoid_fd))
7895                return 1; /* yes. "we closed fd" (actually moved it) */
7896
7897        /* Are we called for "exec 3>FILE"? Came through
7898         * redirect_and_varexp_helper(squirrel=ERR_PTR) -> setup_redirects(ERR_PTR)
7899         * This case used to fail for this script:
7900         *  exec 3>FILE
7901         *  echo Ok
7902         *  ...100000 more lines...
7903         *  echo Ok
7904         * as follows:
7905         *  read(3, "exec 3>FILE\necho Ok\necho Ok"..., 1024) = 1024
7906         *  open("FILE", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 4
7907         *  dup2(4, 3)                        = 3
7908         *  ^^^^^^^^ oops, we lost fd#3 opened to our script!
7909         *  close(4)                          = 0
7910         *  write(1, "Ok\n", 3)               = 3
7911         *  ...                               = 3
7912         *  write(1, "Ok\n", 3)               = 3
7913         *  read(3, 0x94fbc08, 1024)          = -1 EBADF (Bad file descriptor)
7914         *  ^^^^^^^^ oops, wrong fd!!!
7915         * With this case separate from sqp == NULL and *after* move_HFILEs,
7916         * it now works:
7917         */
7918        if (sqp == ERR_PTR) {
7919                /* Don't preserve redirected fds: exec is _meant_ to change these */
7920                //bb_error_msg("sqp == ERR_PTR: exec >FILE");
7921                return 0;
7922        }
7923
7924        /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
7925        *sqp = add_squirrel(*sqp, fd, avoid_fd);
7926        return 0; /* "we did not close fd" */
7927}
7928
7929static void restore_redirects(struct squirrel *sq)
7930{
7931        if (sq) {
7932                int i;
7933                for (i = 0; sq[i].orig_fd >= 0; i++) {
7934                        if (sq[i].moved_to >= 0) {
7935                                /* We simply die on error */
7936                                debug_printf_redir("restoring redirected fd from %d to %d\n", sq[i].moved_to, sq[i].orig_fd);
7937                                xmove_fd(sq[i].moved_to, sq[i].orig_fd);
7938                        } else {
7939                                /* cmd1 9>FILE; cmd2_should_see_fd9_closed */
7940                                debug_printf_redir("restoring redirected fd %d: closing it\n", sq[i].orig_fd);
7941                                close(sq[i].orig_fd);
7942                        }
7943                }
7944                free(sq);
7945        }
7946        if (G.HFILE_stdin
7947         && G.HFILE_stdin->fd > STDIN_FILENO
7948        /* we compare > STDIN, not == STDIN, since hfgetc()
7949         * closes fd and sets ->fd to -1 if EOF is reached.
7950         * Testcase: echo 'pwd' | hush
7951         */
7952        ) {
7953                /* Testcase: interactive "read r <FILE; echo $r; read r; echo $r".
7954                 * Redirect moves ->fd to e.g. 10,
7955                 * and it is not restored above (we do not restore script fds
7956                 * after redirects, we just use new, "moved" fds).
7957                 * However for stdin, get_user_input() -> read_line_input(),
7958                 * and read builtin, depend on fd == STDIN_FILENO.
7959                 */
7960                debug_printf_redir("restoring %d to stdin\n", G.HFILE_stdin->fd);
7961                xmove_fd(G.HFILE_stdin->fd, STDIN_FILENO);
7962                G.HFILE_stdin->fd = STDIN_FILENO;
7963        }
7964
7965        /* If moved, G_interactive_fd stays on new fd, not restoring it */
7966}
7967
7968#if ENABLE_FEATURE_SH_STANDALONE && BB_MMU
7969static void close_saved_fds_and_FILE_fds(void)
7970{
7971        if (G_interactive_fd)
7972                close(G_interactive_fd);
7973        close_all_HFILE_list();
7974}
7975#endif
7976
7977static int internally_opened_fd(int fd, struct squirrel *sq)
7978{
7979        int i;
7980
7981#if ENABLE_HUSH_INTERACTIVE
7982        if (fd == G_interactive_fd)
7983                return 1;
7984#endif
7985        /* If this one of script's fds? */
7986        if (fd_in_HFILEs(fd))
7987                return 1;
7988
7989        if (sq) for (i = 0; sq[i].orig_fd >= 0; i++) {
7990                if (fd == sq[i].moved_to)
7991                        return 1;
7992        }
7993        return 0;
7994}
7995
7996/* squirrel != NULL means we squirrel away copies of stdin, stdout,
7997 * and stderr if they are redirected. */
7998static int setup_redirects(struct command *prog, struct squirrel **sqp)
7999{
8000        struct redir_struct *redir;
8001
8002        for (redir = prog->redirects; redir; redir = redir->next) {
8003                int newfd;
8004                int closed;
8005
8006                if (redir->rd_type == REDIRECT_HEREDOC2) {
8007                        /* "rd_fd<<HERE" case */
8008                        save_fd_on_redirect(redir->rd_fd, /*avoid:*/ 0, sqp);
8009                        /* for REDIRECT_HEREDOC2, rd_filename holds _contents_
8010                         * of the heredoc */
8011                        debug_printf_redir("set heredoc '%s'\n",
8012                                        redir->rd_filename);
8013                        setup_heredoc(redir);
8014                        continue;
8015                }
8016
8017                if (redir->rd_dup == REDIRFD_TO_FILE) {
8018                        /* "rd_fd<*>file" case (<*> is <,>,>>,<>) */
8019                        char *p;
8020                        int mode;
8021
8022                        if (redir->rd_filename == NULL) {
8023                                /* Examples:
8024                                 * "cmd >" (no filename)
8025                                 * "cmd > <file" (2nd redirect starts too early)
8026                                 */
8027                                syntax_error("invalid redirect");
8028                                continue;
8029                        }
8030                        mode = redir_table[redir->rd_type].mode;
8031                        p = expand_string_to_string(redir->rd_filename,
8032                                EXP_FLAG_ESC_GLOB_CHARS, /*unbackslash:*/ 1);
8033                        newfd = open_or_warn(p, mode);
8034                        free(p);
8035                        if (newfd < 0) {
8036                                /* Error message from open_or_warn can be lost
8037                                 * if stderr has been redirected, but bash
8038                                 * and ash both lose it as well
8039                                 * (though zsh doesn't!)
8040                                 */
8041                                return 1;
8042                        }
8043                        if (newfd == redir->rd_fd && sqp) {
8044                                /* open() gave us precisely the fd we wanted.
8045                                 * This means that this fd was not busy
8046                                 * (not opened to anywhere).
8047                                 * Remember to close it on restore:
8048                                 */
8049                                *sqp = add_squirrel_closed(*sqp, newfd);
8050                                debug_printf_redir("redir to previously closed fd %d\n", newfd);
8051                        }
8052                } else {
8053                        /* "rd_fd>&rd_dup" or "rd_fd>&-" case */
8054                        newfd = redir->rd_dup;
8055                }
8056
8057                if (newfd == redir->rd_fd)
8058                        continue;
8059
8060                /* if "N>FILE": move newfd to redir->rd_fd */
8061                /* if "N>&M": dup newfd to redir->rd_fd */
8062                /* if "N>&-": close redir->rd_fd (newfd is REDIRFD_CLOSE) */
8063
8064                closed = save_fd_on_redirect(redir->rd_fd, /*avoid:*/ newfd, sqp);
8065                if (newfd == REDIRFD_CLOSE) {
8066                        /* "N>&-" means "close me" */
8067                        if (!closed) {
8068                                /* ^^^ optimization: saving may already
8069                                 * have closed it. If not... */
8070                                close(redir->rd_fd);
8071                        }
8072                        /* Sometimes we do another close on restore, getting EBADF.
8073                         * Consider "echo 3>FILE 3>&-"
8074                         * first redirect remembers "need to close 3",
8075                         * and second redirect closes 3! Restore code then closes 3 again.
8076                         */
8077                } else {
8078                        /* if newfd is a script fd or saved fd, simulate EBADF */
8079                        if (internally_opened_fd(newfd, sqp && sqp != ERR_PTR ? *sqp : NULL)) {
8080                                //errno = EBADF;
8081                                //bb_perror_msg_and_die("can't duplicate file descriptor");
8082                                newfd = -1; /* same effect as code above */
8083                        }
8084                        xdup2(newfd, redir->rd_fd);
8085                        if (redir->rd_dup == REDIRFD_TO_FILE)
8086                                /* "rd_fd > FILE" */
8087                                close(newfd);
8088                        /* else: "rd_fd > rd_dup" */
8089                }
8090        }
8091        return 0;
8092}
8093
8094static char *find_in_path(const char *arg)
8095{
8096        char *ret = NULL;
8097        const char *PATH = get_local_var_value("PATH");
8098
8099        if (!PATH)
8100                return NULL;
8101
8102        while (1) {
8103                const char *end = strchrnul(PATH, ':');
8104                int sz = end - PATH; /* must be int! */
8105
8106                free(ret);
8107                if (sz != 0) {
8108                        ret = xasprintf("%.*s/%s", sz, PATH, arg);
8109                } else {
8110                        /* We have xxx::yyyy in $PATH,
8111                         * it means "use current dir" */
8112                        ret = xstrdup(arg);
8113                }
8114                if (access(ret, F_OK) == 0)
8115                        break;
8116
8117                if (*end == '\0') {
8118                        free(ret);
8119                        return NULL;
8120                }
8121                PATH = end + 1;
8122        }
8123
8124        return ret;
8125}
8126
8127static const struct built_in_command *find_builtin_helper(const char *name,
8128                const struct built_in_command *x,
8129                const struct built_in_command *end)
8130{
8131        while (x != end) {
8132                if (strcmp(name, x->b_cmd) != 0) {
8133                        x++;
8134                        continue;
8135                }
8136                debug_printf_exec("found builtin '%s'\n", name);
8137                return x;
8138        }
8139        return NULL;
8140}
8141static const struct built_in_command *find_builtin1(const char *name)
8142{
8143        return find_builtin_helper(name, bltins1, &bltins1[ARRAY_SIZE(bltins1)]);
8144}
8145static const struct built_in_command *find_builtin(const char *name)
8146{
8147        const struct built_in_command *x = find_builtin1(name);
8148        if (x)
8149                return x;
8150        return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]);
8151}
8152
8153#if ENABLE_HUSH_JOB && EDITING_HAS_get_exe_name
8154static const char * FAST_FUNC get_builtin_name(int i)
8155{
8156        if (/*i >= 0 && */ i < ARRAY_SIZE(bltins1)) {
8157                return bltins1[i].b_cmd;
8158        }
8159        i -= ARRAY_SIZE(bltins1);
8160        if (i < ARRAY_SIZE(bltins2)) {
8161                return bltins2[i].b_cmd;
8162        }
8163        return NULL;
8164}
8165#endif
8166
8167static void remove_nested_vars(void)
8168{
8169        struct variable *cur;
8170        struct variable **cur_pp;
8171
8172        cur_pp = &G.top_var;
8173        while ((cur = *cur_pp) != NULL) {
8174                if (cur->var_nest_level <= G.var_nest_level) {
8175                        cur_pp = &cur->next;
8176                        continue;
8177                }
8178                /* Unexport */
8179                if (cur->flg_export) {
8180                        debug_printf_env("unexporting nested '%s'/%u\n", cur->varstr, cur->var_nest_level);
8181                        bb_unsetenv(cur->varstr);
8182                }
8183                /* Remove from global list */
8184                *cur_pp = cur->next;
8185                /* Free */
8186                if (!cur->max_len) {
8187                        debug_printf_env("freeing nested '%s'/%u\n", cur->varstr, cur->var_nest_level);
8188                        free(cur->varstr);
8189                }
8190                free(cur);
8191        }
8192}
8193
8194static void enter_var_nest_level(void)
8195{
8196        G.var_nest_level++;
8197        debug_printf_env("var_nest_level++ %u\n", G.var_nest_level);
8198
8199        /* Try: f() { echo -n .; f; }; f
8200         * struct variable::var_nest_level is uint16_t,
8201         * thus limiting recursion to < 2^16.
8202         * In any case, with 8 Mbyte stack SEGV happens
8203         * not too long after 2^16 recursions anyway.
8204         */
8205        if (G.var_nest_level > 0xff00)
8206                bb_error_msg_and_die("fatal recursion (depth %u)", G.var_nest_level);
8207}
8208
8209static void leave_var_nest_level(void)
8210{
8211        G.var_nest_level--;
8212        debug_printf_env("var_nest_level-- %u\n", G.var_nest_level);
8213        if (HUSH_DEBUG && (int)G.var_nest_level < 0)
8214                bb_simple_error_msg_and_die("BUG: nesting underflow");
8215
8216        remove_nested_vars();
8217}
8218
8219#if ENABLE_HUSH_FUNCTIONS
8220static struct function **find_function_slot(const char *name)
8221{
8222        struct function *funcp;
8223        struct function **funcpp = &G.top_func;
8224
8225        while ((funcp = *funcpp) != NULL) {
8226                if (strcmp(name, funcp->name) == 0) {
8227                        debug_printf_exec("found function '%s'\n", name);
8228                        break;
8229                }
8230                funcpp = &funcp->next;
8231        }
8232        return funcpp;
8233}
8234
8235static ALWAYS_INLINE const struct function *find_function(const char *name)
8236{
8237        const struct function *funcp = *find_function_slot(name);
8238        return funcp;
8239}
8240
8241/* Note: takes ownership on name ptr */
8242static struct function *new_function(char *name)
8243{
8244        struct function **funcpp = find_function_slot(name);
8245        struct function *funcp = *funcpp;
8246
8247        if (funcp != NULL) {
8248                struct command *cmd = funcp->parent_cmd;
8249                debug_printf_exec("func %p parent_cmd %p\n", funcp, cmd);
8250                if (!cmd) {
8251                        debug_printf_exec("freeing & replacing function '%s'\n", funcp->name);
8252                        free(funcp->name);
8253                        /* Note: if !funcp->body, do not free body_as_string!
8254                         * This is a special case of "-F name body" function:
8255                         * body_as_string was not malloced! */
8256                        if (funcp->body) {
8257                                free_pipe_list(funcp->body);
8258# if !BB_MMU
8259                                free(funcp->body_as_string);
8260# endif
8261                        }
8262                } else {
8263                        debug_printf_exec("reinserting in tree & replacing function '%s'\n", funcp->name);
8264                        cmd->argv[0] = funcp->name;
8265                        cmd->group = funcp->body;
8266# if !BB_MMU
8267                        cmd->group_as_string = funcp->body_as_string;
8268# endif
8269                }
8270        } else {
8271                debug_printf_exec("remembering new function '%s'\n", name);
8272                funcp = *funcpp = xzalloc(sizeof(*funcp));
8273                /*funcp->next = NULL;*/
8274        }
8275
8276        funcp->name = name;
8277        return funcp;
8278}
8279
8280# if ENABLE_HUSH_UNSET
8281static void unset_func(const char *name)
8282{
8283        struct function **funcpp = find_function_slot(name);
8284        struct function *funcp = *funcpp;
8285
8286        if (funcp != NULL) {
8287                debug_printf_exec("freeing function '%s'\n", funcp->name);
8288                *funcpp = funcp->next;
8289                /* funcp is unlinked now, deleting it.
8290                 * Note: if !funcp->body, the function was created by
8291                 * "-F name body", do not free ->body_as_string
8292                 * and ->name as they were not malloced. */
8293                if (funcp->body) {
8294                        free_pipe_list(funcp->body);
8295                        free(funcp->name);
8296#  if !BB_MMU
8297                        free(funcp->body_as_string);
8298#  endif
8299                }
8300                free(funcp);
8301        }
8302}
8303# endif
8304
8305# if BB_MMU
8306#define exec_function(to_free, funcp, argv) \
8307        exec_function(funcp, argv)
8308# endif
8309static void exec_function(char ***to_free,
8310                const struct function *funcp,
8311                char **argv) NORETURN;
8312static void exec_function(char ***to_free,
8313                const struct function *funcp,
8314                char **argv)
8315{
8316# if BB_MMU
8317        int n;
8318
8319        argv[0] = G.global_argv[0];
8320        G.global_argv = argv;
8321        G.global_argc = n = 1 + string_array_len(argv + 1);
8322
8323// Example when we are here: "cmd | func"
8324// func will run with saved-redirect fds open.
8325// $ f() { echo /proc/self/fd/*; }
8326// $ true | f
8327// /proc/self/fd/0 /proc/self/fd/1 /proc/self/fd/2 /proc/self/fd/255 /proc/self/fd/3
8328// stdio^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ G_interactive_fd^ DIR fd for glob
8329// Same in script:
8330// $ . ./SCRIPT
8331// /proc/self/fd/0 /proc/self/fd/1 /proc/self/fd/2 /proc/self/fd/255 /proc/self/fd/3 /proc/self/fd/4
8332// stdio^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ G_interactive_fd^ opened ./SCRIPT DIR fd for glob
8333// They are CLOEXEC so external programs won't see them, but
8334// for "more correctness" we might want to close those extra fds here:
8335//?     close_saved_fds_and_FILE_fds();
8336
8337        /* "we are in a function, ok to use return" */
8338        G_flag_return_in_progress = -1;
8339        enter_var_nest_level();
8340        IF_HUSH_LOCAL(G.func_nest_level++;)
8341
8342        /* On MMU, funcp->body is always non-NULL */
8343        n = run_list(funcp->body);
8344        _exit(n);
8345# else
8346//?     close_saved_fds_and_FILE_fds();
8347
8348//TODO: check whether "true | func_with_return" works
8349
8350        re_execute_shell(to_free,
8351                        funcp->body_as_string,
8352                        G.global_argv[0],
8353                        argv + 1,
8354                        NULL);
8355# endif
8356}
8357
8358static int run_function(const struct function *funcp, char **argv)
8359{
8360        int rc;
8361        save_arg_t sv;
8362        smallint sv_flg;
8363
8364        save_and_replace_G_args(&sv, argv);
8365
8366        /* "We are in function, ok to use return" */
8367        sv_flg = G_flag_return_in_progress;
8368        G_flag_return_in_progress = -1;
8369
8370        /* Make "local" variables properly shadow previous ones */
8371        IF_HUSH_LOCAL(enter_var_nest_level();)
8372        IF_HUSH_LOCAL(G.func_nest_level++;)
8373
8374        /* On MMU, funcp->body is always non-NULL */
8375# if !BB_MMU
8376        if (!funcp->body) {
8377                /* Function defined by -F */
8378                parse_and_run_string(funcp->body_as_string);
8379                rc = G.last_exitcode;
8380        } else
8381# endif
8382        {
8383                rc = run_list(funcp->body);
8384        }
8385
8386        IF_HUSH_LOCAL(G.func_nest_level--;)
8387        IF_HUSH_LOCAL(leave_var_nest_level();)
8388
8389        G_flag_return_in_progress = sv_flg;
8390# if ENABLE_HUSH_TRAP
8391        debug_printf_exec("G.return_exitcode=-1\n");
8392        G.return_exitcode = -1; /* invalidate stashed return value */
8393# endif
8394
8395        restore_G_args(&sv, argv);
8396
8397        return rc;
8398}
8399#endif /* ENABLE_HUSH_FUNCTIONS */
8400
8401
8402#if BB_MMU
8403#define exec_builtin(to_free, x, argv) \
8404        exec_builtin(x, argv)
8405#else
8406#define exec_builtin(to_free, x, argv) \
8407        exec_builtin(to_free, argv)
8408#endif
8409static void exec_builtin(char ***to_free,
8410                const struct built_in_command *x,
8411                char **argv) NORETURN;
8412static void exec_builtin(char ***to_free,
8413                const struct built_in_command *x,
8414                char **argv)
8415{
8416#if BB_MMU
8417        int rcode;
8418//?     close_saved_fds_and_FILE_fds();
8419        rcode = x->b_function(argv);
8420        fflush_all();
8421        _exit(rcode);
8422#else
8423        fflush_all();
8424        /* On NOMMU, we must never block!
8425         * Example: { sleep 99 | read line; } & echo Ok
8426         */
8427        re_execute_shell(to_free,
8428                        argv[0],
8429                        G.global_argv[0],
8430                        G.global_argv + 1,
8431                        argv);
8432#endif
8433}
8434
8435
8436static void execvp_or_die(char **argv) NORETURN;
8437static void execvp_or_die(char **argv)
8438{
8439        int e;
8440        debug_printf_exec("execing '%s'\n", argv[0]);
8441        /* Don't propagate SIG_IGN to the child */
8442        if (SPECIAL_JOBSTOP_SIGS != 0)
8443                switch_off_special_sigs(G.special_sig_mask & SPECIAL_JOBSTOP_SIGS);
8444        execvp(argv[0], argv);
8445        e = 2;
8446        if (errno == EACCES) e = 126;
8447        if (errno == ENOENT) e = 127;
8448        bb_perror_msg("can't execute '%s'", argv[0]);
8449        _exit(e);
8450}
8451
8452#if ENABLE_HUSH_MODE_X
8453static void x_mode_print_optionally_squoted(const char *str)
8454{
8455        unsigned len;
8456        const char *cp;
8457
8458        cp = str;
8459
8460        /* the set of chars which-cause-string-to-be-squoted mimics bash */
8461        /* test a char with: bash -c 'set -x; echo "CH"' */
8462        if (str[strcspn(str, "\\\"'`$(){}[]<>;#&|~*?!^"
8463                        " " "\001\002\003\004\005\006\007"
8464                        "\010\011\012\013\014\015\016\017"
8465                        "\020\021\022\023\024\025\026\027"
8466                        "\030\031\032\033\034\035\036\037"
8467                        )
8468                ] == '\0'
8469        ) {
8470                /* string has no special chars */
8471                x_mode_addstr(str);
8472                return;
8473        }
8474
8475        cp = str;
8476        for (;;) {
8477                /* print '....' up to EOL or first squote */
8478                len = (int)(strchrnul(cp, '\'') - cp);
8479                if (len != 0) {
8480                        x_mode_addchr('\'');
8481                        x_mode_addblock(cp, len);
8482                        x_mode_addchr('\'');
8483                        cp += len;
8484                }
8485                if (*cp == '\0')
8486                        break;
8487                /* string contains squote(s), print them as \' */
8488                x_mode_addchr('\\');
8489                x_mode_addchr('\'');
8490                cp++;
8491        }
8492}
8493static void dump_cmd_in_x_mode(char **argv)
8494{
8495        if (G_x_mode && argv) {
8496                unsigned n;
8497
8498                /* "+[+++...][ cmd...]\n\0" */
8499                x_mode_prefix();
8500                n = 0;
8501                while (argv[n]) {
8502                        x_mode_addchr(' ');
8503                        if (argv[n][0] == '\0') {
8504                                x_mode_addchr('\'');
8505                                x_mode_addchr('\'');
8506                        } else {
8507                                x_mode_print_optionally_squoted(argv[n]);
8508                        }
8509                        n++;
8510                }
8511                x_mode_flush();
8512        }
8513}
8514#else
8515# define dump_cmd_in_x_mode(argv) ((void)0)
8516#endif
8517
8518#if ENABLE_HUSH_COMMAND
8519static void if_command_vV_print_and_exit(char opt_vV, char *cmd, const char *explanation)
8520{
8521        char *to_free;
8522
8523        if (!opt_vV)
8524                return;
8525
8526        to_free = NULL;
8527        if (!explanation) {
8528                char *path = getenv("PATH");
8529                explanation = to_free = find_executable(cmd, &path); /* path == NULL is ok */
8530                if (!explanation)
8531                        _exit(1); /* PROG was not found */
8532                if (opt_vV != 'V')
8533                        cmd = to_free; /* -v PROG prints "/path/to/PROG" */
8534        }
8535        printf((opt_vV == 'V') ? "%s is %s\n" : "%s\n", cmd, explanation);
8536        free(to_free);
8537        fflush_all();
8538        _exit(0);
8539}
8540#else
8541# define if_command_vV_print_and_exit(a,b,c) ((void)0)
8542#endif
8543
8544#if BB_MMU
8545#define pseudo_exec_argv(nommu_save, argv, assignment_cnt, argv_expanded) \
8546        pseudo_exec_argv(argv, assignment_cnt, argv_expanded)
8547#define pseudo_exec(nommu_save, command, argv_expanded) \
8548        pseudo_exec(command, argv_expanded)
8549#endif
8550
8551/* Called after [v]fork() in run_pipe, or from builtin_exec.
8552 * Never returns.
8553 * Don't exit() here.  If you don't exec, use _exit instead.
8554 * The at_exit handlers apparently confuse the calling process,
8555 * in particular stdin handling. Not sure why? -- because of vfork! (vda)
8556 */
8557static void pseudo_exec_argv(nommu_save_t *nommu_save,
8558                char **argv, int assignment_cnt,
8559                char **argv_expanded) NORETURN;
8560static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save,
8561                char **argv, int assignment_cnt,
8562                char **argv_expanded)
8563{
8564        const struct built_in_command *x;
8565        struct variable **sv_shadowed;
8566        char **new_env;
8567        IF_HUSH_COMMAND(char opt_vV = 0;)
8568        IF_HUSH_FUNCTIONS(const struct function *funcp;)
8569
8570        new_env = expand_assignments(argv, assignment_cnt);
8571        dump_cmd_in_x_mode(new_env);
8572
8573        if (!argv[assignment_cnt]) {
8574                /* Case when we are here: ... | var=val | ...
8575                 * (note that we do not exit early, i.e., do not optimize out
8576                 * expand_assignments(): think about ... | var=`sleep 1` | ...
8577                 */
8578                free_strings(new_env);
8579                _exit(EXIT_SUCCESS);
8580        }
8581
8582        sv_shadowed = G.shadowed_vars_pp;
8583#if BB_MMU
8584        G.shadowed_vars_pp = NULL; /* "don't save, free them instead" */
8585#else
8586        G.shadowed_vars_pp = &nommu_save->old_vars;
8587        G.var_nest_level++;
8588#endif
8589        set_vars_and_save_old(new_env);
8590        G.shadowed_vars_pp = sv_shadowed;
8591
8592        if (argv_expanded) {
8593                argv = argv_expanded;
8594        } else {
8595                argv = expand_strvec_to_strvec(argv + assignment_cnt);
8596#if !BB_MMU
8597                nommu_save->argv = argv;
8598#endif
8599        }
8600        dump_cmd_in_x_mode(argv);
8601
8602#if ENABLE_FEATURE_SH_STANDALONE || BB_MMU
8603        if (strchr(argv[0], '/') != NULL)
8604                goto skip;
8605#endif
8606
8607#if ENABLE_HUSH_FUNCTIONS
8608        /* Check if the command matches any functions (this goes before bltins) */
8609        funcp = find_function(argv[0]);
8610        if (funcp)
8611                exec_function(&nommu_save->argv_from_re_execing, funcp, argv);
8612#endif
8613
8614#if ENABLE_HUSH_COMMAND
8615        /* "command BAR": run BAR without looking it up among functions
8616         * "command -v BAR": print "BAR" or "/path/to/BAR"; or exit 1
8617         * "command -V BAR": print "BAR is {a function,a shell builtin,/path/to/BAR}"
8618         */
8619        while (strcmp(argv[0], "command") == 0 && argv[1]) {
8620                char *p;
8621
8622                argv++;
8623                p = *argv;
8624                if (p[0] != '-' || !p[1])
8625                        continue; /* bash allows "command command command [-OPT] BAR" */
8626
8627                for (;;) {
8628                        p++;
8629                        switch (*p) {
8630                        case '\0':
8631                                argv++;
8632                                p = *argv;
8633                                if (p[0] != '-' || !p[1])
8634                                        goto after_opts;
8635                                continue; /* next arg is also -opts, process it too */
8636                        case 'v':
8637                        case 'V':
8638                                opt_vV = *p;
8639                                continue;
8640                        default:
8641                                bb_error_msg_and_die("%s: %s: invalid option", "command", argv[0]);
8642                        }
8643                }
8644        }
8645 after_opts:
8646# if ENABLE_HUSH_FUNCTIONS
8647        if (opt_vV && find_function(argv[0]))
8648                if_command_vV_print_and_exit(opt_vV, argv[0], "a function");
8649# endif
8650#endif
8651
8652        /* Check if the command matches any of the builtins.
8653         * Depending on context, this might be redundant.  But it's
8654         * easier to waste a few CPU cycles than it is to figure out
8655         * if this is one of those cases.
8656         */
8657        /* Why "BB_MMU ? :" difference in logic? -
8658         * On NOMMU, it is more expensive to re-execute shell
8659         * just in order to run echo or test builtin.
8660         * It's better to skip it here and run corresponding
8661         * non-builtin later. */
8662        x = BB_MMU ? find_builtin(argv[0]) : find_builtin1(argv[0]);
8663        if (x) {
8664                if_command_vV_print_and_exit(opt_vV, argv[0], "a shell builtin");
8665                exec_builtin(&nommu_save->argv_from_re_execing, x, argv);
8666        }
8667
8668#if ENABLE_FEATURE_SH_STANDALONE
8669        /* Check if the command matches any busybox applets */
8670        {
8671                int a = find_applet_by_name(argv[0]);
8672                if (a >= 0) {
8673                        if_command_vV_print_and_exit(opt_vV, argv[0], "an applet");
8674# if BB_MMU /* see above why on NOMMU it is not allowed */
8675                        if (APPLET_IS_NOEXEC(a)) {
8676                                /* Do not leak open fds from opened script files etc.
8677                                 * Testcase: interactive "ls -l /proc/self/fd"
8678                                 * should not show tty fd open.
8679                                 */
8680                                close_saved_fds_and_FILE_fds();
8681//FIXME: should also close saved redir fds
8682//This casuses test failures in
8683//redir_children_should_not_see_saved_fd_2.tests
8684//redir_children_should_not_see_saved_fd_3.tests
8685//if you replace "busybox find" with just "find" in them
8686                                /* Without this, "rm -i FILE" can't be ^C'ed: */
8687                                switch_off_special_sigs(G.special_sig_mask);
8688                                debug_printf_exec("running applet '%s'\n", argv[0]);
8689                                run_noexec_applet_and_exit(a, argv[0], argv);
8690                        }
8691# endif
8692                        /* Re-exec ourselves */
8693                        debug_printf_exec("re-execing applet '%s'\n", argv[0]);
8694                        /* Don't propagate SIG_IGN to the child */
8695                        if (SPECIAL_JOBSTOP_SIGS != 0)
8696                                switch_off_special_sigs(G.special_sig_mask & SPECIAL_JOBSTOP_SIGS);
8697                        execv(bb_busybox_exec_path, argv);
8698                        /* If they called chroot or otherwise made the binary no longer
8699                         * executable, fall through */
8700                }
8701        }
8702#endif
8703
8704#if ENABLE_FEATURE_SH_STANDALONE || BB_MMU
8705 skip:
8706#endif
8707        if_command_vV_print_and_exit(opt_vV, argv[0], NULL);
8708        execvp_or_die(argv);
8709}
8710
8711/* Called after [v]fork() in run_pipe
8712 */
8713static void pseudo_exec(nommu_save_t *nommu_save,
8714                struct command *command,
8715                char **argv_expanded) NORETURN;
8716static void pseudo_exec(nommu_save_t *nommu_save,
8717                struct command *command,
8718                char **argv_expanded)
8719{
8720#if ENABLE_HUSH_FUNCTIONS
8721        if (command->cmd_type == CMD_FUNCDEF) {
8722                /* Ignore funcdefs in pipes:
8723                 * true | f() { cmd }
8724                 */
8725                _exit(0);
8726        }
8727#endif
8728
8729        if (command->argv) {
8730                pseudo_exec_argv(nommu_save, command->argv,
8731                                command->assignment_cnt, argv_expanded);
8732        }
8733
8734        if (command->group) {
8735                /* Cases when we are here:
8736                 * ( list )
8737                 * { list } &
8738                 * ... | ( list ) | ...
8739                 * ... | { list } | ...
8740                 */
8741#if BB_MMU
8742                int rcode;
8743                debug_printf_exec("pseudo_exec: run_list\n");
8744                reset_traps_to_defaults();
8745                rcode = run_list(command->group);
8746                /* OK to leak memory by not calling free_pipe_list,
8747                 * since this process is about to exit */
8748                _exit(rcode);
8749#else
8750                re_execute_shell(&nommu_save->argv_from_re_execing,
8751                                command->group_as_string,
8752                                G.global_argv[0],
8753                                G.global_argv + 1,
8754                                NULL);
8755#endif
8756        }
8757
8758        /* Case when we are here: ... | >file */
8759        debug_printf_exec("pseudo_exec'ed null command\n");
8760        _exit(EXIT_SUCCESS);
8761}
8762
8763#if ENABLE_HUSH_JOB
8764static const char *get_cmdtext(struct pipe *pi)
8765{
8766        char **argv;
8767        char *p;
8768        int len;
8769
8770        /* This is subtle. ->cmdtext is created only on first backgrounding.
8771         * (Think "cat, <ctrl-z>, fg, <ctrl-z>, fg, <ctrl-z>...." here...)
8772         * On subsequent bg argv is trashed, but we won't use it */
8773        if (pi->cmdtext)
8774                return pi->cmdtext;
8775
8776        argv = pi->cmds[0].argv;
8777        if (!argv) {
8778                pi->cmdtext = xzalloc(1);
8779                return pi->cmdtext;
8780        }
8781        len = 0;
8782        do {
8783                len += strlen(*argv) + 1;
8784        } while (*++argv);
8785        p = xmalloc(len);
8786        pi->cmdtext = p;
8787        argv = pi->cmds[0].argv;
8788        do {
8789                p = stpcpy(p, *argv);
8790                *p++ = ' ';
8791        } while (*++argv);
8792        p[-1] = '\0';
8793        return pi->cmdtext;
8794}
8795
8796static void remove_job_from_table(struct pipe *pi)
8797{
8798        struct pipe *prev_pipe;
8799
8800        if (pi == G.job_list) {
8801                G.job_list = pi->next;
8802        } else {
8803                prev_pipe = G.job_list;
8804                while (prev_pipe->next != pi)
8805                        prev_pipe = prev_pipe->next;
8806                prev_pipe->next = pi->next;
8807        }
8808        G.last_jobid = 0;
8809        if (G.job_list)
8810                G.last_jobid = G.job_list->jobid;
8811}
8812
8813static void delete_finished_job(struct pipe *pi)
8814{
8815        remove_job_from_table(pi);
8816        free_pipe(pi);
8817}
8818
8819static void clean_up_last_dead_job(void)
8820{
8821        if (G.job_list && !G.job_list->alive_cmds)
8822                delete_finished_job(G.job_list);
8823}
8824
8825static void insert_job_into_table(struct pipe *pi)
8826{
8827        struct pipe *job, **jobp;
8828        int i;
8829
8830        clean_up_last_dead_job();
8831
8832        /* Find the end of the list, and find next job ID to use */
8833        i = 0;
8834        jobp = &G.job_list;
8835        while ((job = *jobp) != NULL) {
8836                if (job->jobid > i)
8837                        i = job->jobid;
8838                jobp = &job->next;
8839        }
8840        pi->jobid = i + 1;
8841
8842        /* Create a new job struct at the end */
8843        job = *jobp = xmemdup(pi, sizeof(*pi));
8844        job->next = NULL;
8845        job->cmds = xzalloc(sizeof(pi->cmds[0]) * pi->num_cmds);
8846        /* Cannot copy entire pi->cmds[] vector! This causes double frees */
8847        for (i = 0; i < pi->num_cmds; i++) {
8848                job->cmds[i].pid = pi->cmds[i].pid;
8849                /* all other fields are not used and stay zero */
8850        }
8851        job->cmdtext = xstrdup(get_cmdtext(pi));
8852
8853        if (G_interactive_fd)
8854                printf("[%u] %u %s\n", job->jobid, (unsigned)job->cmds[0].pid, job->cmdtext);
8855        G.last_jobid = job->jobid;
8856}
8857#endif /* JOB */
8858
8859static int job_exited_or_stopped(struct pipe *pi)
8860{
8861        int rcode, i;
8862
8863        if (pi->alive_cmds != pi->stopped_cmds)
8864                return -1;
8865
8866        /* All processes in fg pipe have exited or stopped */
8867        rcode = 0;
8868        i = pi->num_cmds;
8869        while (--i >= 0) {
8870                rcode = pi->cmds[i].cmd_exitcode;
8871                /* usually last process gives overall exitstatus,
8872                 * but with "set -o pipefail", last *failed* process does */
8873                if (G.o_opt[OPT_O_PIPEFAIL] == 0 || rcode != 0)
8874                        break;
8875        }
8876        IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
8877        return rcode;
8878}
8879
8880static int process_wait_result(struct pipe *fg_pipe, pid_t childpid, int status)
8881{
8882#if ENABLE_HUSH_JOB
8883        struct pipe *pi;
8884#endif
8885        int i, dead;
8886
8887        dead = WIFEXITED(status) || WIFSIGNALED(status);
8888
8889#if DEBUG_JOBS
8890        if (WIFSTOPPED(status))
8891                debug_printf_jobs("pid %d stopped by sig %d (exitcode %d)\n",
8892                                childpid, WSTOPSIG(status), WEXITSTATUS(status));
8893        if (WIFSIGNALED(status))
8894                debug_printf_jobs("pid %d killed by sig %d (exitcode %d)\n",
8895                                childpid, WTERMSIG(status), WEXITSTATUS(status));
8896        if (WIFEXITED(status))
8897                debug_printf_jobs("pid %d exited, exitcode %d\n",
8898                                childpid, WEXITSTATUS(status));
8899#endif
8900        /* Were we asked to wait for a fg pipe? */
8901        if (fg_pipe) {
8902                i = fg_pipe->num_cmds;
8903
8904                while (--i >= 0) {
8905                        int rcode;
8906
8907                        debug_printf_jobs("check pid %d\n", fg_pipe->cmds[i].pid);
8908                        if (fg_pipe->cmds[i].pid != childpid)
8909                                continue;
8910                        if (dead) {
8911                                int ex;
8912                                fg_pipe->cmds[i].pid = 0;
8913                                fg_pipe->alive_cmds--;
8914                                ex = WEXITSTATUS(status);
8915                                /* bash prints killer signal's name for *last*
8916                                 * process in pipe (prints just newline for SIGINT/SIGPIPE).
8917                                 * Mimic this. Example: "sleep 5" + (^\ or kill -QUIT)
8918                                 */
8919                                if (WIFSIGNALED(status)) {
8920                                        int sig = WTERMSIG(status);
8921#if ENABLE_HUSH_JOB
8922                                        if (G.run_list_level == 1
8923                                        /* ^^^^^ Do not print in nested contexts, example:
8924                                         * echo `sleep 1; sh -c 'kill -9 $$'` - prints "137", NOT "Killed 137"
8925                                         */
8926                                         && i == fg_pipe->num_cmds-1
8927                                        ) {
8928                                                /* strsignal() is for bash compat. ~600 bloat versus bbox's get_signame() */
8929                                                puts(sig == SIGINT || sig == SIGPIPE ? "" : strsignal(sig));
8930                                        }
8931#endif
8932                                        /* TODO: if (WCOREDUMP(status)) + " (core dumped)"; */
8933                                        /* MIPS has 128 sigs (1..128), if sig==128,
8934                                         * 128 + sig would result in exitcode 256 -> 0!
8935                                         */
8936                                        ex = 128 | sig;
8937                                }
8938                                fg_pipe->cmds[i].cmd_exitcode = ex;
8939                        } else {
8940                                fg_pipe->stopped_cmds++;
8941                        }
8942                        debug_printf_jobs("fg_pipe: alive_cmds %d stopped_cmds %d\n",
8943                                        fg_pipe->alive_cmds, fg_pipe->stopped_cmds);
8944                        rcode = job_exited_or_stopped(fg_pipe);
8945                        if (rcode >= 0) {
8946/* Note: *non-interactive* bash does not continue if all processes in fg pipe
8947 * are stopped. Testcase: "cat | cat" in a script (not on command line!)
8948 * and "killall -STOP cat" */
8949                                if (G_interactive_fd) {
8950#if ENABLE_HUSH_JOB
8951                                        if (fg_pipe->alive_cmds != 0)
8952                                                insert_job_into_table(fg_pipe);
8953#endif
8954                                        return rcode;
8955                                }
8956                                if (fg_pipe->alive_cmds == 0)
8957                                        return rcode;
8958                        }
8959                        /* There are still running processes in the fg_pipe */
8960                        return -1;
8961                }
8962                /* It wasn't in fg_pipe, look for process in bg pipes */
8963        }
8964
8965#if ENABLE_HUSH_JOB
8966        /* We were asked to wait for bg or orphaned children */
8967        /* No need to remember exitcode in this case */
8968        for (pi = G.job_list; pi; pi = pi->next) {
8969                for (i = 0; i < pi->num_cmds; i++) {
8970                        if (pi->cmds[i].pid == childpid)
8971                                goto found_pi_and_prognum;
8972                }
8973        }
8974        /* Happens when shell is used as init process (init=/bin/sh) */
8975        debug_printf("checkjobs: pid %d was not in our list!\n", childpid);
8976        return -1; /* this wasn't a process from fg_pipe */
8977
8978 found_pi_and_prognum:
8979        if (dead) {
8980                /* child exited */
8981                int rcode = WEXITSTATUS(status);
8982                if (WIFSIGNALED(status))
8983                        /* NB: not 128 + sig, MIPS has sig 128 */
8984                        rcode = 128 | WTERMSIG(status);
8985                pi->cmds[i].cmd_exitcode = rcode;
8986                if (G.last_bg_pid == pi->cmds[i].pid)
8987                        G.last_bg_pid_exitcode = rcode;
8988                pi->cmds[i].pid = 0;
8989                pi->alive_cmds--;
8990                if (!pi->alive_cmds) {
8991# if ENABLE_HUSH_BASH_COMPAT
8992                        G.dead_job_exitcode = job_exited_or_stopped(pi);
8993# endif
8994                        if (G_interactive_fd) {
8995                                printf(JOB_STATUS_FORMAT, pi->jobid,
8996                                                "Done", pi->cmdtext);
8997                                delete_finished_job(pi);
8998                        } else {
8999/*
9000 * bash deletes finished jobs from job table only in interactive mode,
9001 * after "jobs" cmd, or if pid of a new process matches one of the old ones
9002 * (see cleanup_dead_jobs(), delete_old_job(), J_NOTIFIED in bash source).
9003 * Testcase script: "(exit 3) & sleep 1; wait %1; echo $?" prints 3 in bash.
9004 * We only retain one "dead" job, if it's the single job on the list.
9005 * This covers most of real-world scenarios where this is useful.
9006 */
9007                                if (pi != G.job_list)
9008                                        delete_finished_job(pi);
9009                        }
9010                }
9011        } else {
9012                /* child stopped */
9013                pi->stopped_cmds++;
9014        }
9015#endif
9016        return -1; /* this wasn't a process from fg_pipe */
9017}
9018
9019/* Check to see if any processes have exited -- if they have,
9020 * figure out why and see if a job has completed.
9021 *
9022 * If non-NULL fg_pipe: wait for its completion or stop.
9023 * Return its exitcode or zero if stopped.
9024 *
9025 * Alternatively (fg_pipe == NULL, waitfor_pid != 0):
9026 * waitpid(WNOHANG), if waitfor_pid exits or stops, return exitcode+1,
9027 * else return <0 if waitpid errors out (e.g. ECHILD: nothing to wait for)
9028 * or 0 if no children changed status.
9029 *
9030 * Alternatively (fg_pipe == NULL, waitfor_pid == 0),
9031 * return <0 if waitpid errors out (e.g. ECHILD: nothing to wait for)
9032 * or 0 if no children changed status.
9033 */
9034static int checkjobs(struct pipe *fg_pipe, pid_t waitfor_pid)
9035{
9036        int attributes;
9037        int status;
9038        int rcode = 0;
9039
9040        debug_printf_jobs("checkjobs %p\n", fg_pipe);
9041
9042        attributes = WUNTRACED;
9043        if (fg_pipe == NULL)
9044                attributes |= WNOHANG;
9045
9046        errno = 0;
9047#if ENABLE_HUSH_FAST
9048        if (G.handled_SIGCHLD == G.count_SIGCHLD) {
9049//bb_error_msg("[%d] checkjobs: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d children?:%d fg_pipe:%p",
9050//getpid(), G.count_SIGCHLD, G.handled_SIGCHLD, G.we_have_children, fg_pipe);
9051                /* There was neither fork nor SIGCHLD since last waitpid */
9052                /* Avoid doing waitpid syscall if possible */
9053                if (!G.we_have_children) {
9054                        errno = ECHILD;
9055                        return -1;
9056                }
9057                if (fg_pipe == NULL) { /* is WNOHANG set? */
9058                        /* We have children, but they did not exit
9059                         * or stop yet (we saw no SIGCHLD) */
9060                        return 0;
9061                }
9062                /* else: !WNOHANG, waitpid will block, can't short-circuit */
9063        }
9064#endif
9065
9066/* Do we do this right?
9067 * bash-3.00# sleep 20 | false
9068 * <ctrl-Z pressed>
9069 * [3]+  Stopped          sleep 20 | false
9070 * bash-3.00# echo $?
9071 * 1   <========== bg pipe is not fully done, but exitcode is already known!
9072 * [hush 1.14.0: yes we do it right]
9073 */
9074        while (1) {
9075                pid_t childpid;
9076#if ENABLE_HUSH_FAST
9077                int i;
9078                i = G.count_SIGCHLD;
9079#endif
9080                childpid = waitpid(-1, &status, attributes);
9081                if (childpid <= 0) {
9082                        if (childpid && errno != ECHILD)
9083                                bb_simple_perror_msg("waitpid");
9084#if ENABLE_HUSH_FAST
9085                        else { /* Until next SIGCHLD, waitpid's are useless */
9086                                G.we_have_children = (childpid == 0);
9087                                G.handled_SIGCHLD = i;
9088//bb_error_msg("[%d] checkjobs: waitpid returned <= 0, G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
9089                        }
9090#endif
9091                        /* ECHILD (no children), or 0 (no change in children status) */
9092                        rcode = childpid;
9093                        break;
9094                }
9095                rcode = process_wait_result(fg_pipe, childpid, status);
9096                if (rcode >= 0) {
9097                        /* fg_pipe exited or stopped */
9098                        break;
9099                }
9100                if (childpid == waitfor_pid) { /* "wait PID" */
9101                        debug_printf_exec("childpid==waitfor_pid:%d status:0x%08x\n", childpid, status);
9102                        rcode = WEXITSTATUS(status);
9103                        if (WIFSIGNALED(status))
9104                                rcode = 128 | WTERMSIG(status);
9105                        if (WIFSTOPPED(status))
9106                                /* bash: "cmd & wait $!" and cmd stops: $? = 128 | stopsig */
9107                                rcode = 128 | WSTOPSIG(status);
9108                        rcode++;
9109                        break; /* "wait PID" called us, give it exitcode+1 */
9110                }
9111#if ENABLE_HUSH_BASH_COMPAT
9112                if (-1 == waitfor_pid /* "wait -n" (wait for any one job) */
9113                 && G.dead_job_exitcode >= 0 /* some job did finish */
9114                ) {
9115                        debug_printf_exec("waitfor_pid:-1\n");
9116                        rcode = G.dead_job_exitcode + 1;
9117                        break;
9118                }
9119#endif
9120                /* This wasn't one of our processes, or */
9121                /* fg_pipe still has running processes, do waitpid again */
9122        } /* while (waitpid succeeds)... */
9123
9124        return rcode;
9125}
9126
9127#if ENABLE_HUSH_JOB
9128static int checkjobs_and_fg_shell(struct pipe *fg_pipe)
9129{
9130        pid_t p;
9131        int rcode = checkjobs(fg_pipe, 0 /*(no pid to wait for)*/);
9132        if (G_saved_tty_pgrp) {
9133                /* Job finished, move the shell to the foreground */
9134                p = getpgrp(); /* our process group id */
9135                debug_printf_jobs("fg'ing ourself: getpgrp()=%d\n", (int)p);
9136                tcsetpgrp(G_interactive_fd, p);
9137        }
9138        return rcode;
9139}
9140#endif
9141
9142/* Start all the jobs, but don't wait for anything to finish.
9143 * See checkjobs().
9144 *
9145 * Return code is normally -1, when the caller has to wait for children
9146 * to finish to determine the exit status of the pipe.  If the pipe
9147 * is a simple builtin command, however, the action is done by the
9148 * time run_pipe returns, and the exit code is provided as the
9149 * return value.
9150 *
9151 * Returns -1 only if started some children. IOW: we have to
9152 * mask out retvals of builtins etc with 0xff!
9153 *
9154 * The only case when we do not need to [v]fork is when the pipe
9155 * is single, non-backgrounded, non-subshell command. Examples:
9156 * cmd ; ...   { list } ; ...
9157 * cmd && ...  { list } && ...
9158 * cmd || ...  { list } || ...
9159 * If it is, then we can run cmd as a builtin, NOFORK,
9160 * or (if SH_STANDALONE) an applet, and we can run the { list }
9161 * with run_list. If it isn't one of these, we fork and exec cmd.
9162 *
9163 * Cases when we must fork:
9164 * non-single:   cmd | cmd
9165 * backgrounded: cmd &     { list } &
9166 * subshell:     ( list ) [&]
9167 */
9168#if !ENABLE_HUSH_MODE_X
9169#define redirect_and_varexp_helper(command, sqp, argv_expanded) \
9170        redirect_and_varexp_helper(command, sqp)
9171#endif
9172static int redirect_and_varexp_helper(
9173                struct command *command,
9174                struct squirrel **sqp,
9175                char **argv_expanded)
9176{
9177        /* Assignments occur before redirects. Try:
9178         * a=`sleep 1` sleep 2 3>/qwe/rty
9179         */
9180
9181        char **new_env = expand_assignments(command->argv, command->assignment_cnt);
9182        dump_cmd_in_x_mode(new_env);
9183        dump_cmd_in_x_mode(argv_expanded);
9184        /* this takes ownership of new_env[i] elements, and frees new_env: */
9185        set_vars_and_save_old(new_env);
9186
9187        return setup_redirects(command, sqp);
9188}
9189static NOINLINE int run_pipe(struct pipe *pi)
9190{
9191        static const char *const null_ptr = NULL;
9192
9193        int cmd_no;
9194        int next_infd;
9195        struct command *command;
9196        char **argv_expanded;
9197        char **argv;
9198        struct squirrel *squirrel = NULL;
9199        int rcode;
9200
9201        debug_printf_exec("run_pipe start: members:%d\n", pi->num_cmds);
9202        debug_enter();
9203
9204        /* Testcase: set -- q w e; (IFS='' echo "$*"; IFS=''; echo "$*"); echo "$*"
9205         * Result should be 3 lines: q w e, qwe, q w e
9206         */
9207        if (G.ifs_whitespace != G.ifs)
9208                free(G.ifs_whitespace);
9209        G.ifs = get_local_var_value("IFS");
9210        if (G.ifs) {
9211                char *p;
9212                G.ifs_whitespace = (char*)G.ifs;
9213                p = skip_whitespace(G.ifs);
9214                if (*p) {
9215                        /* Not all $IFS is whitespace */
9216                        char *d;
9217                        int len = p - G.ifs;
9218                        p = skip_non_whitespace(p);
9219                        G.ifs_whitespace = xmalloc(len + strlen(p) + 1); /* can overestimate */
9220                        d = mempcpy(G.ifs_whitespace, G.ifs, len);
9221                        while (*p) {
9222                                if (isspace(*p))
9223                                        *d++ = *p;
9224                                p++;
9225                        }
9226                        *d = '\0';
9227                }
9228        } else {
9229                G.ifs = defifs;
9230                G.ifs_whitespace = (char*)G.ifs;
9231        }
9232
9233        IF_HUSH_JOB(pi->pgrp = -1;)
9234        pi->stopped_cmds = 0;
9235        command = &pi->cmds[0];
9236        argv_expanded = NULL;
9237
9238        if (pi->num_cmds != 1
9239         || pi->followup == PIPE_BG
9240         || command->cmd_type == CMD_SUBSHELL
9241        ) {
9242                goto must_fork;
9243        }
9244
9245        pi->alive_cmds = 1;
9246
9247        debug_printf_exec(": group:%p argv:'%s'\n",
9248                command->group, command->argv ? command->argv[0] : "NONE");
9249
9250        if (command->group) {
9251#if ENABLE_HUSH_FUNCTIONS
9252                if (command->cmd_type == CMD_FUNCDEF) {
9253                        /* "executing" func () { list } */
9254                        struct function *funcp;
9255
9256                        funcp = new_function(command->argv[0]);
9257                        /* funcp->name is already set to argv[0] */
9258                        funcp->body = command->group;
9259# if !BB_MMU
9260                        funcp->body_as_string = command->group_as_string;
9261                        command->group_as_string = NULL;
9262# endif
9263                        command->group = NULL;
9264                        command->argv[0] = NULL;
9265                        debug_printf_exec("cmd %p has child func at %p\n", command, funcp);
9266                        funcp->parent_cmd = command;
9267                        command->child_func = funcp;
9268
9269                        debug_printf_exec("run_pipe: return EXIT_SUCCESS\n");
9270                        debug_leave();
9271                        return EXIT_SUCCESS;
9272                }
9273#endif
9274                /* { list } */
9275                debug_printf_exec("non-subshell group\n");
9276                rcode = 1; /* exitcode if redir failed */
9277                if (setup_redirects(command, &squirrel) == 0) {
9278                        debug_printf_exec(": run_list\n");
9279//FIXME: we need to pass squirrel down into run_list()
9280//for SH_STANDALONE case, or else this construct:
9281// { find /proc/self/fd; true; } >FILE; cmd2
9282//has no way of closing saved fd#1 for "find",
9283//and in SH_STANDALONE mode, "find" is not execed,
9284//therefore CLOEXEC on saved fd does not help.
9285                        rcode = run_list(command->group) & 0xff;
9286                }
9287                restore_redirects(squirrel);
9288                IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
9289                debug_leave();
9290                debug_printf_exec("run_pipe: return %d\n", rcode);
9291                return rcode;
9292        }
9293
9294        argv = command->argv ? command->argv : (char **) &null_ptr;
9295        {
9296                const struct built_in_command *x;
9297                IF_HUSH_FUNCTIONS(const struct function *funcp;)
9298                IF_NOT_HUSH_FUNCTIONS(enum { funcp = 0 };)
9299                struct variable **sv_shadowed;
9300                struct variable *old_vars;
9301
9302#if ENABLE_HUSH_LINENO_VAR
9303                G.execute_lineno = command->lineno;
9304#endif
9305
9306                if (argv[command->assignment_cnt] == NULL) {
9307                        /* Assignments, but no command.
9308                         * Ensure redirects take effect (that is, create files).
9309                         * Try "a=t >file"
9310                         */
9311                        unsigned i;
9312                        G.expand_exitcode = 0;
9313 only_assignments:
9314                        rcode = setup_redirects(command, &squirrel);
9315                        restore_redirects(squirrel);
9316
9317                        /* Set shell variables */
9318                        i = 0;
9319                        while (i < command->assignment_cnt) {
9320                                char *p = expand_string_to_string(argv[i],
9321                                                EXP_FLAG_ESC_GLOB_CHARS,
9322                                                /*unbackslash:*/ 1
9323                                );
9324#if ENABLE_HUSH_MODE_X
9325                                if (G_x_mode) {
9326                                        char *eq;
9327                                        if (i == 0)
9328                                                x_mode_prefix();
9329                                        x_mode_addchr(' ');
9330                                        eq = strchrnul(p, '=');
9331                                        if (*eq) eq++;
9332                                        x_mode_addblock(p, (eq - p));
9333                                        x_mode_print_optionally_squoted(eq);
9334                                        x_mode_flush();
9335                                }
9336#endif
9337                                debug_printf_env("set shell var:'%s'->'%s'\n", *argv, p);
9338                                if (set_local_var(p, /*flag:*/ 0)) {
9339                                        /* assignment to readonly var / putenv error? */
9340                                        rcode = 1;
9341                                }
9342                                i++;
9343                        }
9344                        /* Redirect error sets $? to 1. Otherwise,
9345                         * if evaluating assignment value set $?, retain it.
9346                         * Else, clear $?:
9347                         *  false; q=`exit 2`; echo $? - should print 2
9348                         *  false; x=1; echo $? - should print 0
9349                         * Because of the 2nd case, we can't just use G.last_exitcode.
9350                         */
9351                        if (rcode == 0)
9352                                rcode = G.expand_exitcode;
9353                        IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
9354                        debug_leave();
9355                        debug_printf_exec("run_pipe: return %d\n", rcode);
9356                        return rcode;
9357                }
9358
9359                /* Expand the rest into (possibly) many strings each */
9360#if defined(CMD_TEST2_SINGLEWORD_NOGLOB)
9361                if (command->cmd_type == CMD_TEST2_SINGLEWORD_NOGLOB)
9362                        argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt);
9363                else
9364#endif
9365#if defined(CMD_SINGLEWORD_NOGLOB)
9366                if (command->cmd_type == CMD_SINGLEWORD_NOGLOB)
9367                        argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt);
9368                else
9369#endif
9370                        argv_expanded = expand_strvec_to_strvec(argv + command->assignment_cnt);
9371
9372                /* If someone gives us an empty string: `cmd with empty output` */
9373                if (!argv_expanded[0]) {
9374                        free(argv_expanded);
9375                        /* `false` still has to set exitcode 1 */
9376                        G.expand_exitcode = G.last_exitcode;
9377                        goto only_assignments;
9378                }
9379
9380                old_vars = NULL;
9381                sv_shadowed = G.shadowed_vars_pp;
9382
9383                /* Check if argv[0] matches any functions (this goes before bltins) */
9384                IF_HUSH_FUNCTIONS(funcp = find_function(argv_expanded[0]);)
9385                IF_HUSH_FUNCTIONS(x = NULL;)
9386                IF_HUSH_FUNCTIONS(if (!funcp))
9387                        x = find_builtin(argv_expanded[0]);
9388                if (x || funcp) {
9389                        if (x && x->b_function == builtin_exec && argv_expanded[1] == NULL) {
9390                                debug_printf("exec with redirects only\n");
9391                                /*
9392                                 * Variable assignments are executed, but then "forgotten":
9393                                 *  a=`sleep 1;echo A` exec 3>&-; echo $a
9394                                 * sleeps, but prints nothing.
9395                                 */
9396                                enter_var_nest_level();
9397                                G.shadowed_vars_pp = &old_vars;
9398                                rcode = redirect_and_varexp_helper(command,
9399                                        /*squirrel:*/ ERR_PTR,
9400                                        argv_expanded
9401                                );
9402                                G.shadowed_vars_pp = sv_shadowed;
9403                                /* rcode=1 can be if redir file can't be opened */
9404
9405                                goto clean_up_and_ret1;
9406                        }
9407
9408                        /* Bump var nesting, or this will leak exported $a:
9409                         * a=b true; env | grep ^a=
9410                         */
9411                        enter_var_nest_level();
9412                        /* Collect all variables "shadowed" by helper
9413                         * (IOW: old vars overridden by "var1=val1 var2=val2 cmd..." syntax)
9414                         * into old_vars list:
9415                         */
9416                        G.shadowed_vars_pp = &old_vars;
9417                        rcode = redirect_and_varexp_helper(command, &squirrel, argv_expanded);
9418                        if (rcode == 0) {
9419                                if (!funcp) {
9420                                        /* Do not collect *to old_vars list* vars shadowed
9421                                         * by e.g. "local VAR" builtin (collect them
9422                                         * in the previously nested list instead):
9423                                         * don't want them to be restored immediately
9424                                         * after "local" completes.
9425                                         */
9426                                        G.shadowed_vars_pp = sv_shadowed;
9427
9428                                        debug_printf_exec(": builtin '%s' '%s'...\n",
9429                                                x->b_cmd, argv_expanded[1]);
9430                                        fflush_all();
9431                                        rcode = x->b_function(argv_expanded) & 0xff;
9432                                        fflush_all();
9433                                }
9434#if ENABLE_HUSH_FUNCTIONS
9435                                else {
9436                                        debug_printf_exec(": function '%s' '%s'...\n",
9437                                                funcp->name, argv_expanded[1]);
9438                                        rcode = run_function(funcp, argv_expanded) & 0xff;
9439                                        /*
9440                                         * But do collect *to old_vars list* vars shadowed
9441                                         * within function execution. To that end, restore
9442                                         * this pointer _after_ function run:
9443                                         */
9444                                        G.shadowed_vars_pp = sv_shadowed;
9445                                }
9446#endif
9447                        }
9448                } else
9449                if (ENABLE_FEATURE_SH_NOFORK && NUM_APPLETS > 1) {
9450                        int n = find_applet_by_name(argv_expanded[0]);
9451                        if (n < 0 || !APPLET_IS_NOFORK(n))
9452                                goto must_fork;
9453
9454                        enter_var_nest_level();
9455                        /* Collect all variables "shadowed" by helper into old_vars list */
9456                        G.shadowed_vars_pp = &old_vars;
9457                        rcode = redirect_and_varexp_helper(command, &squirrel, argv_expanded);
9458                        G.shadowed_vars_pp = sv_shadowed;
9459
9460                        if (rcode == 0) {
9461                                debug_printf_exec(": run_nofork_applet '%s' '%s'...\n",
9462                                        argv_expanded[0], argv_expanded[1]);
9463                                /*
9464                                 * Note: signals (^C) can't interrupt here.
9465                                 * We remember them and they will be acted upon
9466                                 * after applet returns.
9467                                 * This makes applets which can run for a long time
9468                                 * and/or wait for user input ineligible for NOFORK:
9469                                 * for example, "yes" or "rm" (rm -i waits for input).
9470                                 */
9471                                rcode = run_nofork_applet(n, argv_expanded);
9472                        }
9473                } else
9474                        goto must_fork;
9475
9476                restore_redirects(squirrel);
9477 clean_up_and_ret1:
9478                leave_var_nest_level();
9479                add_vars(old_vars);
9480
9481                /*
9482                 * Try "usleep 99999999" + ^C + "echo $?"
9483                 * with FEATURE_SH_NOFORK=y.
9484                 */
9485                if (!funcp) {
9486                        /* It was builtin or nofork.
9487                         * if this would be a real fork/execed program,
9488                         * it should have died if a fatal sig was received.
9489                         * But OTOH, there was no separate process,
9490                         * the sig was sent to _shell_, not to non-existing
9491                         * child.
9492                         * Let's just handle ^C only, this one is obvious:
9493                         * we aren't ok with exitcode 0 when ^C was pressed
9494                         * during builtin/nofork.
9495                         */
9496                        if (sigismember(&G.pending_set, SIGINT))
9497                                rcode = 128 | SIGINT;
9498                }
9499                free(argv_expanded);
9500                IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
9501                debug_leave();
9502                debug_printf_exec("run_pipe return %d\n", rcode);
9503                return rcode;
9504        }
9505
9506 must_fork:
9507        /* NB: argv_expanded may already be created, and that
9508         * might include `cmd` runs! Do not rerun it! We *must*
9509         * use argv_expanded if it's non-NULL */
9510
9511        /* Going to fork a child per each pipe member */
9512        pi->alive_cmds = 0;
9513        next_infd = 0;
9514
9515        cmd_no = 0;
9516        while (cmd_no < pi->num_cmds) {
9517                struct fd_pair pipefds;
9518#if !BB_MMU
9519                int sv_var_nest_level = G.var_nest_level;
9520                volatile nommu_save_t nommu_save;
9521                nommu_save.old_vars = NULL;
9522                nommu_save.argv = NULL;
9523                nommu_save.argv_from_re_execing = NULL;
9524#endif
9525                command = &pi->cmds[cmd_no];
9526                cmd_no++;
9527                if (command->argv) {
9528                        debug_printf_exec(": pipe member '%s' '%s'...\n",
9529                                        command->argv[0], command->argv[1]);
9530                } else {
9531                        debug_printf_exec(": pipe member with no argv\n");
9532                }
9533
9534                /* pipes are inserted between pairs of commands */
9535                pipefds.rd = 0;
9536                pipefds.wr = 1;
9537                if (cmd_no < pi->num_cmds)
9538                        xpiped_pair(pipefds);
9539
9540#if ENABLE_HUSH_LINENO_VAR
9541                G.execute_lineno = command->lineno;
9542#endif
9543
9544                command->pid = BB_MMU ? fork() : vfork();
9545                if (!command->pid) { /* child */
9546#if ENABLE_HUSH_JOB
9547                        disable_restore_tty_pgrp_on_exit();
9548                        CLEAR_RANDOM_T(&G.random_gen); /* or else $RANDOM repeats in child */
9549
9550                        /* Every child adds itself to new process group
9551                         * with pgid == pid_of_first_child_in_pipe */
9552                        if (G.run_list_level == 1 && G_interactive_fd) {
9553                                pid_t pgrp;
9554                                pgrp = pi->pgrp;
9555                                if (pgrp < 0) /* true for 1st process only */
9556                                        pgrp = getpid();
9557                                if (setpgid(0, pgrp) == 0
9558                                 && pi->followup != PIPE_BG
9559                                 && G_saved_tty_pgrp /* we have ctty */
9560                                ) {
9561                                        /* We do it in *every* child, not just first,
9562                                         * to avoid races */
9563                                        tcsetpgrp(G_interactive_fd, pgrp);
9564                                }
9565                        }
9566#endif
9567                        if (pi->alive_cmds == 0 && pi->followup == PIPE_BG) {
9568                                /* 1st cmd in backgrounded pipe
9569                                 * should have its stdin /dev/null'ed */
9570                                close(0);
9571                                if (open(bb_dev_null, O_RDONLY))
9572                                        xopen("/", O_RDONLY);
9573                        } else {
9574                                xmove_fd(next_infd, 0);
9575                        }
9576                        xmove_fd(pipefds.wr, 1);
9577                        if (pipefds.rd > 1)
9578                                close(pipefds.rd);
9579                        /* Like bash, explicit redirects override pipes,
9580                         * and the pipe fd (fd#1) is available for dup'ing:
9581                         * "cmd1 2>&1 | cmd2": fd#1 is duped to fd#2, thus stderr
9582                         * of cmd1 goes into pipe.
9583                         */
9584                        if (setup_redirects(command, NULL)) {
9585                                /* Happens when redir file can't be opened:
9586                                 * $ hush -c 'echo FOO >&2 | echo BAR 3>/qwe/rty; echo BAZ'
9587                                 * FOO
9588                                 * hush: can't open '/qwe/rty': No such file or directory
9589                                 * BAZ
9590                                 * (echo BAR is not executed, it hits _exit(1) below)
9591                                 */
9592                                _exit(1);
9593                        }
9594
9595                        /* Stores to nommu_save list of env vars putenv'ed
9596                         * (NOMMU, on MMU we don't need that) */
9597                        /* cast away volatility... */
9598                        pseudo_exec((nommu_save_t*) &nommu_save, command, argv_expanded);
9599                        /* pseudo_exec() does not return */
9600                }
9601
9602                /* parent or error */
9603#if ENABLE_HUSH_FAST
9604                G.count_SIGCHLD++;
9605//bb_error_msg("[%d] fork in run_pipe: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
9606#endif
9607                enable_restore_tty_pgrp_on_exit();
9608#if !BB_MMU
9609                /* Clean up after vforked child */
9610                free(nommu_save.argv);
9611                free(nommu_save.argv_from_re_execing);
9612                G.var_nest_level = sv_var_nest_level;
9613                remove_nested_vars();
9614                add_vars(nommu_save.old_vars);
9615#endif
9616                free(argv_expanded);
9617                argv_expanded = NULL;
9618                if (command->pid < 0) { /* [v]fork failed */
9619                        /* Clearly indicate, was it fork or vfork */
9620                        bb_simple_perror_msg(BB_MMU ? "vfork"+1 : "vfork");
9621                } else {
9622                        pi->alive_cmds++;
9623#if ENABLE_HUSH_JOB
9624                        /* Second and next children need to know pid of first one */
9625                        if (pi->pgrp < 0)
9626                                pi->pgrp = command->pid;
9627#endif
9628                }
9629
9630                if (cmd_no > 1)
9631                        close(next_infd);
9632                if (cmd_no < pi->num_cmds)
9633                        close(pipefds.wr);
9634                /* Pass read (output) pipe end to next iteration */
9635                next_infd = pipefds.rd;
9636        }
9637
9638        if (!pi->alive_cmds) {
9639                debug_leave();
9640                debug_printf_exec("run_pipe return 1 (all forks failed, no children)\n");
9641                return 1;
9642        }
9643
9644        debug_leave();
9645        debug_printf_exec("run_pipe return -1 (%u children started)\n", pi->alive_cmds);
9646        return -1;
9647}
9648
9649/* NB: called by pseudo_exec, and therefore must not modify any
9650 * global data until exec/_exit (we can be a child after vfork!) */
9651static int run_list(struct pipe *pi)
9652{
9653#if ENABLE_HUSH_CASE
9654        char *case_word = NULL;
9655#endif
9656#if ENABLE_HUSH_LOOPS
9657        struct pipe *loop_top = NULL;
9658        char **for_lcur = NULL;
9659        char **for_list = NULL;
9660#endif
9661        smallint last_followup;
9662        smalluint rcode;
9663#if ENABLE_HUSH_IF || ENABLE_HUSH_CASE
9664        smalluint cond_code = 0;
9665#else
9666        enum { cond_code = 0 };
9667#endif
9668#if HAS_KEYWORDS
9669        smallint rword;      /* RES_foo */
9670        smallint last_rword; /* ditto */
9671#endif
9672
9673        debug_printf_exec("run_list start lvl %d\n", G.run_list_level);
9674        debug_enter();
9675
9676#if ENABLE_HUSH_LOOPS
9677        /* Check syntax for "for" */
9678        {
9679                struct pipe *cpipe;
9680                for (cpipe = pi; cpipe; cpipe = cpipe->next) {
9681                        if (cpipe->res_word != RES_FOR && cpipe->res_word != RES_IN)
9682                                continue;
9683                        /* current word is FOR or IN (BOLD in comments below) */
9684                        if (cpipe->next == NULL) {
9685                                syntax_error("malformed for");
9686                                debug_leave();
9687                                debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level);
9688                                return 1;
9689                        }
9690                        /* "FOR v; do ..." and "for v IN a b; do..." are ok */
9691                        if (cpipe->next->res_word == RES_DO)
9692                                continue;
9693                        /* next word is not "do". It must be "in" then ("FOR v in ...") */
9694                        if (cpipe->res_word == RES_IN /* "for v IN a b; not_do..."? */
9695                         || cpipe->next->res_word != RES_IN /* FOR v not_do_and_not_in..."? */
9696                        ) {
9697                                syntax_error("malformed for");
9698                                debug_leave();
9699                                debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level);
9700                                return 1;
9701                        }
9702                }
9703        }
9704#endif
9705
9706        /* Past this point, all code paths should jump to ret: label
9707         * in order to return, no direct "return" statements please.
9708         * This helps to ensure that no memory is leaked. */
9709
9710#if ENABLE_HUSH_JOB
9711        G.run_list_level++;
9712#endif
9713
9714#if HAS_KEYWORDS
9715        rword = RES_NONE;
9716        last_rword = RES_XXXX;
9717#endif
9718        last_followup = PIPE_SEQ;
9719        rcode = G.last_exitcode;
9720
9721        /* Go through list of pipes, (maybe) executing them. */
9722        for (; pi; pi = IF_HUSH_LOOPS(rword == RES_DONE ? loop_top : ) pi->next) {
9723                int r;
9724                int sv_errexit_depth;
9725
9726                if (G.flag_SIGINT)
9727                        break;
9728                if (G_flag_return_in_progress == 1)
9729                        break;
9730
9731                IF_HAS_KEYWORDS(rword = pi->res_word;)
9732                debug_printf_exec(": rword=%d cond_code=%d last_rword=%d\n",
9733                                rword, cond_code, last_rword);
9734
9735                sv_errexit_depth = G.errexit_depth;
9736                if (
9737#if ENABLE_HUSH_IF
9738                    rword == RES_IF || rword == RES_ELIF ||
9739#endif
9740                    pi->followup != PIPE_SEQ
9741                ) {
9742                        G.errexit_depth++;
9743                }
9744#if ENABLE_HUSH_LOOPS
9745                if ((rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR)
9746                 && loop_top == NULL /* avoid bumping G.depth_of_loop twice */
9747                ) {
9748                        /* start of a loop: remember where loop starts */
9749                        loop_top = pi;
9750                        G.depth_of_loop++;
9751                }
9752#endif
9753                /* Still in the same "if...", "then..." or "do..." branch? */
9754                if (IF_HAS_KEYWORDS(rword == last_rword &&) 1) {
9755                        if ((rcode == 0 && last_followup == PIPE_OR)
9756                         || (rcode != 0 && last_followup == PIPE_AND)
9757                        ) {
9758                                /* It is "<true> || CMD" or "<false> && CMD"
9759                                 * and we should not execute CMD */
9760                                debug_printf_exec("skipped cmd because of || or &&\n");
9761                                last_followup = pi->followup;
9762                                goto dont_check_jobs_but_continue;
9763                        }
9764                }
9765                last_followup = pi->followup;
9766                IF_HAS_KEYWORDS(last_rword = rword;)
9767#if ENABLE_HUSH_IF
9768                if (cond_code) {
9769                        if (rword == RES_THEN) {
9770                                /* if false; then ... fi has exitcode 0! */
9771                                G.last_exitcode = rcode = EXIT_SUCCESS;
9772                                /* "if <false> THEN cmd": skip cmd */
9773                                continue;
9774                        }
9775                } else {
9776                        if (rword == RES_ELSE || rword == RES_ELIF) {
9777                                /* "if <true> then ... ELSE/ELIF cmd":
9778                                 * skip cmd and all following ones */
9779                                break;
9780                        }
9781                }
9782#endif
9783#if ENABLE_HUSH_LOOPS
9784                if (rword == RES_FOR) { /* && pi->num_cmds - always == 1 */
9785                        if (!for_lcur) {
9786                                /* first loop through for */
9787
9788                                static const char encoded_dollar_at[] ALIGN1 = {
9789                                        SPECIAL_VAR_SYMBOL, '@' | 0x80, SPECIAL_VAR_SYMBOL, '\0'
9790                                }; /* encoded representation of "$@" */
9791                                static const char *const encoded_dollar_at_argv[] = {
9792                                        encoded_dollar_at, NULL
9793                                }; /* argv list with one element: "$@" */
9794                                char **vals;
9795
9796                                G.last_exitcode = rcode = EXIT_SUCCESS;
9797                                vals = (char**)encoded_dollar_at_argv;
9798                                if (pi->next->res_word == RES_IN) {
9799                                        /* if no variable values after "in" we skip "for" */
9800                                        if (!pi->next->cmds[0].argv) {
9801                                                debug_printf_exec(": null FOR: exitcode EXIT_SUCCESS\n");
9802                                                break;
9803                                        }
9804                                        vals = pi->next->cmds[0].argv;
9805                                } /* else: "for var; do..." -> assume "$@" list */
9806                                /* create list of variable values */
9807                                debug_print_strings("for_list made from", vals);
9808                                for_list = expand_strvec_to_strvec(vals);
9809                                for_lcur = for_list;
9810                                debug_print_strings("for_list", for_list);
9811                        }
9812                        if (!*for_lcur) {
9813                                /* "for" loop is over, clean up */
9814                                free(for_list);
9815                                for_list = NULL;
9816                                for_lcur = NULL;
9817                                break;
9818                        }
9819                        /* Insert next value from for_lcur */
9820                        /* note: *for_lcur already has quotes removed, $var expanded, etc */
9821                        set_local_var(xasprintf("%s=%s", pi->cmds[0].argv[0], *for_lcur++), /*flag:*/ 0);
9822                        continue;
9823                }
9824                if (rword == RES_IN) {
9825                        continue; /* "for v IN list;..." - "in" has no cmds anyway */
9826                }
9827                if (rword == RES_DONE) {
9828                        continue; /* "done" has no cmds too */
9829                }
9830#endif
9831#if ENABLE_HUSH_CASE
9832                if (rword == RES_CASE) {
9833                        debug_printf_exec("CASE cond_code:%d\n", cond_code);
9834                        case_word = expand_string_to_string(pi->cmds->argv[0],
9835                                EXP_FLAG_ESC_GLOB_CHARS, /*unbackslash:*/ 1);
9836                        debug_printf_exec("CASE word1:'%s'\n", case_word);
9837                        //unbackslash(case_word);
9838                        //debug_printf_exec("CASE word2:'%s'\n", case_word);
9839                        continue;
9840                }
9841                if (rword == RES_MATCH) {
9842                        char **argv;
9843
9844                        debug_printf_exec("MATCH cond_code:%d\n", cond_code);
9845                        if (!case_word) /* "case ... matched_word) ... WORD)": we executed selected branch, stop */
9846                                break;
9847                        /* all prev words didn't match, does this one match? */
9848                        argv = pi->cmds->argv;
9849                        while (*argv) {
9850                                char *pattern;
9851                                debug_printf_exec("expand_string_to_string('%s')\n", *argv);
9852                                pattern = expand_string_to_string(*argv,
9853                                                EXP_FLAG_ESC_GLOB_CHARS,
9854                                                /*unbackslash:*/ 0
9855                                );
9856                                /* TODO: which FNM_xxx flags to use? */
9857                                cond_code = (fnmatch(pattern, case_word, /*flags:*/ 0) != 0);
9858                                debug_printf_exec("fnmatch(pattern:'%s',str:'%s'):%d\n",
9859                                                pattern, case_word, cond_code);
9860                                free(pattern);
9861                                if (cond_code == 0) {
9862                                        /* match! we will execute this branch */
9863                                        free(case_word);
9864                                        case_word = NULL; /* make future "word)" stop */
9865                                        break;
9866                                }
9867                                argv++;
9868                        }
9869                        continue;
9870                }
9871                if (rword == RES_CASE_BODY) { /* inside of a case branch */
9872                        debug_printf_exec("CASE_BODY cond_code:%d\n", cond_code);
9873                        if (cond_code != 0)
9874                                continue; /* not matched yet, skip this pipe */
9875                }
9876                if (rword == RES_ESAC) {
9877                        debug_printf_exec("ESAC cond_code:%d\n", cond_code);
9878                        if (case_word) {
9879                                /* "case" did not match anything: still set $? (to 0) */
9880                                G.last_exitcode = rcode = EXIT_SUCCESS;
9881                        }
9882                }
9883#endif
9884                /* Just pressing <enter> in shell should check for jobs.
9885                 * OTOH, in non-interactive shell this is useless
9886                 * and only leads to extra job checks */
9887                if (pi->num_cmds == 0) {
9888                        if (G_interactive_fd)
9889                                goto check_jobs_and_continue;
9890                        continue;
9891                }
9892
9893                /* After analyzing all keywords and conditions, we decided
9894                 * to execute this pipe. NB: have to do checkjobs(NULL)
9895                 * after run_pipe to collect any background children,
9896                 * even if list execution is to be stopped. */
9897                debug_printf_exec(": run_pipe with %d members\n", pi->num_cmds);
9898#if ENABLE_HUSH_LOOPS
9899                G.flag_break_continue = 0;
9900#endif
9901                rcode = r = run_pipe(pi); /* NB: rcode is a smalluint, r is int */
9902                if (r != -1) {
9903                        /* We ran a builtin, function, or group.
9904                         * rcode is already known
9905                         * and we don't need to wait for anything. */
9906                        debug_printf_exec(": builtin/func exitcode %d\n", rcode);
9907                        G.last_exitcode = rcode;
9908                        check_and_run_traps();
9909#if ENABLE_HUSH_TRAP && ENABLE_HUSH_FUNCTIONS
9910                        rcode = G.last_exitcode; /* "return" in trap can change it, read back */
9911#endif
9912#if ENABLE_HUSH_LOOPS
9913                        /* Was it "break" or "continue"? */
9914                        if (G.flag_break_continue) {
9915                                smallint fbc = G.flag_break_continue;
9916                                /* We might fall into outer *loop*,
9917                                 * don't want to break it too */
9918                                if (loop_top) {
9919                                        G.depth_break_continue--;
9920                                        if (G.depth_break_continue == 0)
9921                                                G.flag_break_continue = 0;
9922                                        /* else: e.g. "continue 2" should *break* once, *then* continue */
9923                                } /* else: "while... do... { we are here (innermost list is not a loop!) };...done" */
9924                                if (G.depth_break_continue != 0 || fbc == BC_BREAK) {
9925                                        checkjobs(NULL, 0 /*(no pid to wait for)*/);
9926                                        break;
9927                                }
9928                                /* "continue": simulate end of loop */
9929                                rword = RES_DONE;
9930                                continue;
9931                        }
9932#endif
9933                        if (G_flag_return_in_progress == 1) {
9934                                checkjobs(NULL, 0 /*(no pid to wait for)*/);
9935                                break;
9936                        }
9937                } else if (pi->followup == PIPE_BG) {
9938                        /* What does bash do with attempts to background builtins? */
9939                        /* even bash 3.2 doesn't do that well with nested bg:
9940                         * try "{ { sleep 10; echo DEEP; } & echo HERE; } &".
9941                         * I'm NOT treating inner &'s as jobs */
9942#if ENABLE_HUSH_JOB
9943                        if (G.run_list_level == 1)
9944                                insert_job_into_table(pi);
9945#endif
9946                        /* Last command's pid goes to $! */
9947                        G.last_bg_pid = pi->cmds[pi->num_cmds - 1].pid;
9948                        G.last_bg_pid_exitcode = 0;
9949                        debug_printf_exec(": cmd&: exitcode EXIT_SUCCESS\n");
9950/* Check pi->pi_inverted? "! sleep 1 & echo $?": bash says 1. dash and ash say 0 */
9951                        rcode = EXIT_SUCCESS;
9952                        goto check_traps;
9953                } else {
9954#if ENABLE_HUSH_JOB
9955                        if (G.run_list_level == 1 && G_interactive_fd) {
9956                                /* Waits for completion, then fg's main shell */
9957                                rcode = checkjobs_and_fg_shell(pi);
9958                                debug_printf_exec(": checkjobs_and_fg_shell exitcode %d\n", rcode);
9959                                goto check_traps;
9960                        }
9961#endif
9962                        /* This one just waits for completion */
9963                        rcode = checkjobs(pi, 0 /*(no pid to wait for)*/);
9964                        debug_printf_exec(": checkjobs exitcode %d\n", rcode);
9965 check_traps:
9966                        G.last_exitcode = rcode;
9967                        check_and_run_traps();
9968#if ENABLE_HUSH_TRAP && ENABLE_HUSH_FUNCTIONS
9969                        rcode = G.last_exitcode; /* "return" in trap can change it, read back */
9970#endif
9971                }
9972
9973                /* Handle "set -e" */
9974                if (rcode != 0 && G.o_opt[OPT_O_ERREXIT]) {
9975                        debug_printf_exec("ERREXIT:1 errexit_depth:%d\n", G.errexit_depth);
9976                        if (G.errexit_depth == 0)
9977                                hush_exit(rcode);
9978                }
9979                G.errexit_depth = sv_errexit_depth;
9980
9981                /* Analyze how result affects subsequent commands */
9982#if ENABLE_HUSH_IF
9983                if (rword == RES_IF || rword == RES_ELIF)
9984                        cond_code = rcode;
9985#endif
9986 check_jobs_and_continue:
9987                checkjobs(NULL, 0 /*(no pid to wait for)*/);
9988 dont_check_jobs_but_continue: ;
9989#if ENABLE_HUSH_LOOPS
9990                /* Beware of "while false; true; do ..."! */
9991                if (pi->next
9992                 && (pi->next->res_word == RES_DO || pi->next->res_word == RES_DONE)
9993                 /* check for RES_DONE is needed for "while ...; do \n done" case */
9994                ) {
9995                        if (rword == RES_WHILE) {
9996                                if (rcode) {
9997                                        /* "while false; do...done" - exitcode 0 */
9998                                        G.last_exitcode = rcode = EXIT_SUCCESS;
9999                                        debug_printf_exec(": while expr is false: breaking (exitcode:EXIT_SUCCESS)\n");
10000                                        break;
10001                                }
10002                        }
10003                        if (rword == RES_UNTIL) {
10004                                if (!rcode) {
10005                                        debug_printf_exec(": until expr is true: breaking\n");
10006                                        break;
10007                                }
10008                        }
10009                }
10010#endif
10011        } /* for (pi) */
10012
10013#if ENABLE_HUSH_JOB
10014        G.run_list_level--;
10015#endif
10016#if ENABLE_HUSH_LOOPS
10017        if (loop_top)
10018                G.depth_of_loop--;
10019        free(for_list);
10020#endif
10021#if ENABLE_HUSH_CASE
10022        free(case_word);
10023#endif
10024        debug_leave();
10025        debug_printf_exec("run_list lvl %d return %d\n", G.run_list_level + 1, rcode);
10026        return rcode;
10027}
10028
10029/* Select which version we will use */
10030static int run_and_free_list(struct pipe *pi)
10031{
10032        int rcode = 0;
10033        debug_printf_exec("run_and_free_list entered\n");
10034        if (!G.o_opt[OPT_O_NOEXEC]) {
10035                debug_printf_exec(": run_list: 1st pipe with %d cmds\n", pi->num_cmds);
10036                rcode = run_list(pi);
10037        }
10038        /* free_pipe_list has the side effect of clearing memory.
10039         * In the long run that function can be merged with run_list,
10040         * but doing that now would hobble the debugging effort. */
10041        free_pipe_list(pi);
10042        debug_printf_exec("run_and_free_list return %d\n", rcode);
10043        return rcode;
10044}
10045
10046
10047static void install_sighandlers(unsigned mask)
10048{
10049        sighandler_t old_handler;
10050        unsigned sig = 0;
10051        while ((mask >>= 1) != 0) {
10052                sig++;
10053                if (!(mask & 1))
10054                        continue;
10055                old_handler = install_sighandler(sig, pick_sighandler(sig));
10056                /* POSIX allows shell to re-enable SIGCHLD
10057                 * even if it was SIG_IGN on entry.
10058                 * Therefore we skip IGN check for it:
10059                 */
10060                if (sig == SIGCHLD)
10061                        continue;
10062                /* Interactive bash re-enables SIGHUP which is SIG_IGNed on entry.
10063                 * Try:
10064                 * trap '' hup; bash; echo RET  # type "kill -hup $$", see SIGHUP having effect
10065                 * trap '' hup; bash -c 'kill -hup $$; echo ALIVE'  # here SIGHUP is SIG_IGNed
10066                 */
10067                if (sig == SIGHUP && G_interactive_fd)
10068                        continue;
10069                /* Unless one of the above signals, is it SIG_IGN? */
10070                if (old_handler == SIG_IGN) {
10071                        /* oops... restore back to IGN, and record this fact */
10072                        install_sighandler(sig, old_handler);
10073#if ENABLE_HUSH_TRAP
10074                        if (!G_traps)
10075                                G_traps = xzalloc(sizeof(G_traps[0]) * NSIG);
10076                        free(G_traps[sig]);
10077                        G_traps[sig] = xzalloc(1); /* == xstrdup(""); */
10078#endif
10079                }
10080        }
10081}
10082
10083/* Called a few times only (or even once if "sh -c") */
10084static void install_special_sighandlers(void)
10085{
10086        unsigned mask;
10087
10088        /* Which signals are shell-special? */
10089        mask = (1 << SIGQUIT) | (1 << SIGCHLD);
10090        if (G_interactive_fd) {
10091                mask |= SPECIAL_INTERACTIVE_SIGS;
10092                if (G_saved_tty_pgrp) /* we have ctty, job control sigs work */
10093                        mask |= SPECIAL_JOBSTOP_SIGS;
10094        }
10095        /* Careful, do not re-install handlers we already installed */
10096        if (G.special_sig_mask != mask) {
10097                unsigned diff = mask & ~G.special_sig_mask;
10098                G.special_sig_mask = mask;
10099                install_sighandlers(diff);
10100        }
10101}
10102
10103#if ENABLE_HUSH_JOB
10104/* helper */
10105/* Set handlers to restore tty pgrp and exit */
10106static void install_fatal_sighandlers(void)
10107{
10108        unsigned mask;
10109
10110        /* We will restore tty pgrp on these signals */
10111        mask = 0
10112                /*+ (1 << SIGILL ) * HUSH_DEBUG*/
10113                /*+ (1 << SIGFPE ) * HUSH_DEBUG*/
10114                + (1 << SIGBUS ) * HUSH_DEBUG
10115                + (1 << SIGSEGV) * HUSH_DEBUG
10116                /*+ (1 << SIGTRAP) * HUSH_DEBUG*/
10117                + (1 << SIGABRT)
10118        /* bash 3.2 seems to handle these just like 'fatal' ones */
10119                + (1 << SIGPIPE)
10120                + (1 << SIGALRM)
10121        /* if we are interactive, SIGHUP, SIGTERM and SIGINT are special sigs.
10122         * if we aren't interactive... but in this case
10123         * we never want to restore pgrp on exit, and this fn is not called
10124         */
10125                /*+ (1 << SIGHUP )*/
10126                /*+ (1 << SIGTERM)*/
10127                /*+ (1 << SIGINT )*/
10128        ;
10129        G_fatal_sig_mask = mask;
10130
10131        install_sighandlers(mask);
10132}
10133#endif
10134
10135static int set_mode(int state, char mode, const char *o_opt)
10136{
10137        int idx;
10138        switch (mode) {
10139        case 'n':
10140                G.o_opt[OPT_O_NOEXEC] = state;
10141                break;
10142        case 'x':
10143                IF_HUSH_MODE_X(G_x_mode = state;)
10144                IF_HUSH_MODE_X(if (G.x_mode_fd <= 0) G.x_mode_fd = dup_CLOEXEC(2, 10);)
10145                break;
10146        case 'e':
10147                G.o_opt[OPT_O_ERREXIT] = state;
10148                break;
10149        case 'o':
10150                if (!o_opt) {
10151                        /* "set -o" or "set +o" without parameter.
10152                         * in bash, set -o produces this output:
10153                         *  pipefail        off
10154                         * and set +o:
10155                         *  set +o pipefail
10156                         * We always use the second form.
10157                         */
10158                        const char *p = o_opt_strings;
10159                        idx = 0;
10160                        while (*p) {
10161                                printf("set %co %s\n", (G.o_opt[idx] ? '-' : '+'), p);
10162                                idx++;
10163                                p += strlen(p) + 1;
10164                        }
10165                        break;
10166                }
10167                idx = index_in_strings(o_opt_strings, o_opt);
10168                if (idx >= 0) {
10169                        G.o_opt[idx] = state;
10170                        break;
10171                }
10172                /* fall through to error */
10173        default:
10174                return EXIT_FAILURE;
10175        }
10176        return EXIT_SUCCESS;
10177}
10178
10179int hush_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
10180int hush_main(int argc, char **argv)
10181{
10182        pid_t cached_getpid;
10183        enum {
10184                OPT_login = (1 << 0),
10185        };
10186        unsigned flags;
10187#if !BB_MMU
10188        unsigned builtin_argc = 0;
10189#endif
10190        char **e;
10191        struct variable *cur_var;
10192        struct variable *shell_ver;
10193
10194        INIT_G();
10195        if (EXIT_SUCCESS != 0) /* if EXIT_SUCCESS == 0, it is already done */
10196                G.last_exitcode = EXIT_SUCCESS;
10197#if ENABLE_HUSH_TRAP
10198# if ENABLE_HUSH_FUNCTIONS
10199        G.return_exitcode = -1;
10200# endif
10201        G.pre_trap_exitcode = -1;
10202#endif
10203
10204#if ENABLE_HUSH_FAST
10205        G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */
10206#endif
10207#if !BB_MMU
10208        G.argv0_for_re_execing = argv[0];
10209#endif
10210
10211        cached_getpid = getpid();   /* for tcsetpgrp() during init */
10212        G.root_pid = cached_getpid; /* for $PID  (NOMMU can override via -$HEXPID:HEXPPID:...) */
10213        G.root_ppid = getppid();    /* for $PPID (NOMMU can override)  */
10214
10215        /* Deal with HUSH_VERSION */
10216        debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION");
10217        unsetenv("HUSH_VERSION"); /* in case it exists in initial env */
10218        shell_ver = xzalloc(sizeof(*shell_ver));
10219        shell_ver->flg_export = 1;
10220        shell_ver->flg_read_only = 1;
10221        /* Code which handles ${var<op>...} needs writable values for all variables,
10222         * therefore we xstrdup: */
10223        shell_ver->varstr = xstrdup(hush_version_str);
10224
10225        /* Create shell local variables from the values
10226         * currently living in the environment */
10227        G.top_var = shell_ver;
10228        cur_var = G.top_var;
10229        e = environ;
10230        if (e) while (*e) {
10231                char *value = strchr(*e, '=');
10232                if (value) { /* paranoia */
10233                        cur_var->next = xzalloc(sizeof(*cur_var));
10234                        cur_var = cur_var->next;
10235                        cur_var->varstr = *e;
10236                        cur_var->max_len = strlen(*e);
10237                        cur_var->flg_export = 1;
10238                }
10239                e++;
10240        }
10241        /* (Re)insert HUSH_VERSION into env (AFTER we scanned the env!) */
10242        debug_printf_env("putenv '%s'\n", shell_ver->varstr);
10243        putenv(shell_ver->varstr);
10244
10245        /* Export PWD */
10246        set_pwd_var(SETFLAG_EXPORT);
10247
10248#if BASH_HOSTNAME_VAR
10249        /* Set (but not export) HOSTNAME unless already set */
10250        if (!get_local_var_value("HOSTNAME")) {
10251                struct utsname uts;
10252                uname(&uts);
10253                set_local_var_from_halves("HOSTNAME", uts.nodename);
10254        }
10255#endif
10256        /* IFS is not inherited from the parent environment */
10257        set_local_var_from_halves("IFS", defifs);
10258
10259        if (!get_local_var_value("PATH"))
10260                set_local_var_from_halves("PATH", bb_default_root_path);
10261
10262        /* PS1/PS2 are set later, if we determine that we are interactive */
10263
10264        /* bash also exports SHLVL and _,
10265         * and sets (but doesn't export) the following variables:
10266         * BASH=/bin/bash
10267         * BASH_VERSINFO=([0]="3" [1]="2" [2]="0" [3]="1" [4]="release" [5]="i386-pc-linux-gnu")
10268         * BASH_VERSION='3.2.0(1)-release'
10269         * HOSTTYPE=i386
10270         * MACHTYPE=i386-pc-linux-gnu
10271         * OSTYPE=linux-gnu
10272         * PPID=<NNNNN> - we also do it elsewhere
10273         * EUID=<NNNNN>
10274         * UID=<NNNNN>
10275         * GROUPS=()
10276         * LINES=<NNN>
10277         * COLUMNS=<NNN>
10278         * BASH_ARGC=()
10279         * BASH_ARGV=()
10280         * BASH_LINENO=()
10281         * BASH_SOURCE=()
10282         * DIRSTACK=()
10283         * PIPESTATUS=([0]="0")
10284         * HISTFILE=/<xxx>/.bash_history
10285         * HISTFILESIZE=500
10286         * HISTSIZE=500
10287         * MAILCHECK=60
10288         * PATH=/usr/gnu/bin:/usr/local/bin:/bin:/usr/bin:.
10289         * SHELL=/bin/bash
10290         * SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
10291         * TERM=dumb
10292         * OPTERR=1
10293         * OPTIND=1
10294         * PS4='+ '
10295         */
10296
10297#if NUM_SCRIPTS > 0
10298        if (argc < 0) {
10299                char *script = get_script_content(-argc - 1);
10300                G.global_argv = argv;
10301                G.global_argc = string_array_len(argv);
10302                //install_special_sighandlers(); - needed?
10303                parse_and_run_string(script);
10304                goto final_return;
10305        }
10306#endif
10307
10308        /* Initialize some more globals to non-zero values */
10309        die_func = restore_ttypgrp_and__exit;
10310
10311        /* Shell is non-interactive at first. We need to call
10312         * install_special_sighandlers() if we are going to execute "sh <script>",
10313         * "sh -c <cmds>" or login shell's /etc/profile and friends.
10314         * If we later decide that we are interactive, we run install_special_sighandlers()
10315         * in order to intercept (more) signals.
10316         */
10317
10318        /* Parse options */
10319        /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */
10320        flags = (argv[0] && argv[0][0] == '-') ? OPT_login : 0;
10321        while (1) {
10322                int opt = getopt(argc, argv, "+" /* stop at 1st non-option */
10323                                "cexinsl"
10324#if !BB_MMU
10325                                "<:$:R:V:"
10326# if ENABLE_HUSH_FUNCTIONS
10327                                "F:"
10328# endif
10329#endif
10330                );
10331                if (opt <= 0)
10332                        break;
10333                switch (opt) {
10334                case 'c':
10335                        /* Note: -c is not an option with param!
10336                         * "hush -c -l SCRIPT" is valid. "hush -cSCRIPT" is not.
10337                         */
10338                        G.opt_c = 1;
10339                        break;
10340                case 'i':
10341                        /* Well, we cannot just declare interactiveness,
10342                         * we have to have some stuff (ctty, etc) */
10343                        /* G_interactive_fd++; */
10344                        break;
10345                case 's':
10346                        G.opt_s = 1;
10347                        break;
10348                case 'l':
10349                        flags |= OPT_login;
10350                        break;
10351#if !BB_MMU
10352                case '<': /* "big heredoc" support */
10353                        full_write1_str(optarg);
10354                        _exit(0);
10355                case '$': {
10356                        unsigned long long empty_trap_mask;
10357
10358                        G.root_pid = bb_strtou(optarg, &optarg, 16);
10359                        optarg++;
10360                        G.root_ppid = bb_strtou(optarg, &optarg, 16);
10361                        optarg++;
10362                        G.last_bg_pid = bb_strtou(optarg, &optarg, 16);
10363                        optarg++;
10364                        G.last_exitcode = bb_strtou(optarg, &optarg, 16);
10365                        optarg++;
10366                        builtin_argc = bb_strtou(optarg, &optarg, 16);
10367                        optarg++;
10368                        empty_trap_mask = bb_strtoull(optarg, &optarg, 16);
10369                        if (empty_trap_mask != 0) {
10370                                IF_HUSH_TRAP(int sig;)
10371                                install_special_sighandlers();
10372# if ENABLE_HUSH_TRAP
10373                                G_traps = xzalloc(sizeof(G_traps[0]) * NSIG);
10374                                for (sig = 1; sig < NSIG; sig++) {
10375                                        if (empty_trap_mask & (1LL << sig)) {
10376                                                G_traps[sig] = xzalloc(1); /* == xstrdup(""); */
10377                                                install_sighandler(sig, SIG_IGN);
10378                                        }
10379                                }
10380# endif
10381                        }
10382# if ENABLE_HUSH_LOOPS
10383                        optarg++;
10384                        G.depth_of_loop = bb_strtou(optarg, &optarg, 16);
10385# endif
10386                        /* Suppress "killed by signal" message, -$ hack is used
10387                         * for subshells: echo `sh -c 'kill -9 $$'`
10388                         * should be silent.
10389                         */
10390                        IF_HUSH_JOB(G.run_list_level = 1;)
10391# if ENABLE_HUSH_FUNCTIONS
10392                        /* nommu uses re-exec trick for "... | func | ...",
10393                         * should allow "return".
10394                         * This accidentally allows returns in subshells.
10395                         */
10396                        G_flag_return_in_progress = -1;
10397# endif
10398                        break;
10399                }
10400                case 'R':
10401                case 'V':
10402                        set_local_var(xstrdup(optarg), opt == 'R' ? SETFLAG_MAKE_RO : 0);
10403                        break;
10404# if ENABLE_HUSH_FUNCTIONS
10405                case 'F': {
10406                        struct function *funcp = new_function(optarg);
10407                        /* funcp->name is already set to optarg */
10408                        /* funcp->body is set to NULL. It's a special case. */
10409                        funcp->body_as_string = argv[optind];
10410                        optind++;
10411                        break;
10412                }
10413# endif
10414#endif
10415                /*case '?': invalid option encountered (set_mode('?') will fail) */
10416                /*case 'n':*/
10417                /*case 'x':*/
10418                /*case 'e':*/
10419                default:
10420                        if (set_mode(1, opt, NULL) == 0) /* no error */
10421                                break;
10422                        bb_show_usage();
10423                }
10424        } /* option parsing loop */
10425
10426        /* Skip options. Try "hush -l": $1 should not be "-l"! */
10427        G.global_argc = argc - (optind - 1);
10428        G.global_argv = argv + (optind - 1);
10429        G.global_argv[0] = argv[0];
10430
10431        /* If we are login shell... */
10432        if (flags & OPT_login) {
10433                const char *hp = NULL;
10434                HFILE *input;
10435
10436                debug_printf("sourcing /etc/profile\n");
10437                input = hfopen("/etc/profile");
10438 run_profile:
10439                if (input != NULL) {
10440                        install_special_sighandlers();
10441                        parse_and_run_file(input);
10442                        hfclose(input);
10443                }
10444                /* bash: after sourcing /etc/profile,
10445                 * tries to source (in the given order):
10446                 * ~/.bash_profile, ~/.bash_login, ~/.profile,
10447                 * stopping on first found. --noprofile turns this off.
10448                 * bash also sources ~/.bash_logout on exit.
10449                 * If called as sh, skips .bash_XXX files.
10450                 */
10451                if (!hp) { /* unless we looped on the "goto" already */
10452                        hp = get_local_var_value("HOME");
10453                        if (hp && hp[0]) {
10454                                debug_printf("sourcing ~/.profile\n");
10455                                hp = concat_path_file(hp, ".profile");
10456                                input = hfopen(hp);
10457                                free((char*)hp);
10458                                goto run_profile;
10459                        }
10460                }
10461        }
10462
10463        /* -c takes effect *after* -l */
10464        if (G.opt_c) {
10465                /* Possibilities:
10466                 * sh ... -c 'script'
10467                 * sh ... -c 'script' ARG0 [ARG1...]
10468                 * On NOMMU, if builtin_argc != 0,
10469                 * sh ... -c 'builtin' BARGV... "" ARG0 [ARG1...]
10470                 * "" needs to be replaced with NULL
10471                 * and BARGV vector fed to builtin function.
10472                 * Note: the form without ARG0 never happens:
10473                 * sh ... -c 'builtin' BARGV... ""
10474                 */
10475                char *script;
10476
10477                install_special_sighandlers();
10478
10479                G.global_argc--;
10480                G.global_argv++;
10481#if !BB_MMU
10482                if (builtin_argc) {
10483                        /* -c 'builtin' [BARGV...] "" ARG0 [ARG1...] */
10484                        const struct built_in_command *x;
10485                        x = find_builtin(G.global_argv[0]);
10486                        if (x) { /* paranoia */
10487                                argv = G.global_argv;
10488                                G.global_argc -= builtin_argc + 1; /* skip [BARGV...] "" */
10489                                G.global_argv += builtin_argc + 1;
10490                                G.global_argv[-1] = NULL; /* replace "" */
10491                                G.last_exitcode = x->b_function(argv);
10492                        }
10493                        goto final_return;
10494                }
10495#endif
10496
10497                script = G.global_argv[0];
10498                if (!script)
10499                        bb_error_msg_and_die(bb_msg_requires_arg, "-c");
10500                if (!G.global_argv[1]) {
10501                        /* -c 'script' (no params): prevent empty $0 */
10502                        G.global_argv[0] = argv[0];
10503                } else { /* else -c 'script' ARG0 [ARG1...]: $0 is ARG0 */
10504                        G.global_argc--;
10505                        G.global_argv++;
10506                }
10507                parse_and_run_string(script);
10508                goto final_return;
10509        }
10510
10511        /* -s is: hush -s ARGV1 ARGV2 (no SCRIPT) */
10512        if (!G.opt_s && G.global_argv[1]) {
10513                HFILE *input;
10514                /*
10515                 * "bash <script>" (which is never interactive (unless -i?))
10516                 * sources $BASH_ENV here (without scanning $PATH).
10517                 * If called as sh, does the same but with $ENV.
10518                 * Also NB, per POSIX, $ENV should undergo parameter expansion.
10519                 */
10520                G.global_argc--;
10521                G.global_argv++;
10522                debug_printf("running script '%s'\n", G.global_argv[0]);
10523                xfunc_error_retval = 127; /* for "hush /does/not/exist" case */
10524                input = hfopen(G.global_argv[0]);
10525                if (!input) {
10526                        bb_simple_perror_msg_and_die(G.global_argv[0]);
10527                }
10528                xfunc_error_retval = 1;
10529                install_special_sighandlers();
10530                parse_and_run_file(input);
10531#if ENABLE_FEATURE_CLEAN_UP
10532                hfclose(input);
10533#endif
10534                goto final_return;
10535        }
10536        /* "implicit" -s: bare interactive hush shows 's' in $- */
10537        G.opt_s = 1;
10538
10539        /* Up to here, shell was non-interactive. Now it may become one.
10540         * NB: don't forget to (re)run install_special_sighandlers() as needed.
10541         */
10542
10543        /* A shell is interactive if the '-i' flag was given,
10544         * or if all of the following conditions are met:
10545         *    no -c command
10546         *    no arguments remaining or the -s flag given
10547         *    standard input is a terminal
10548         *    standard output is a terminal
10549         * Refer to Posix.2, the description of the 'sh' utility.
10550         */
10551#if ENABLE_HUSH_JOB
10552        if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
10553                G_saved_tty_pgrp = tcgetpgrp(STDIN_FILENO);
10554                debug_printf("saved_tty_pgrp:%d\n", G_saved_tty_pgrp);
10555                if (G_saved_tty_pgrp < 0)
10556                        G_saved_tty_pgrp = 0;
10557
10558                /* try to dup stdin to high fd#, >= 255 */
10559                G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, 254);
10560                if (G_interactive_fd < 0) {
10561                        /* try to dup to any fd */
10562                        G_interactive_fd = dup(STDIN_FILENO);
10563                        if (G_interactive_fd < 0) {
10564                                /* give up */
10565                                G_interactive_fd = 0;
10566                                G_saved_tty_pgrp = 0;
10567                        }
10568                }
10569        }
10570        debug_printf("interactive_fd:%d\n", G_interactive_fd);
10571        if (G_interactive_fd) {
10572                close_on_exec_on(G_interactive_fd);
10573
10574                if (G_saved_tty_pgrp) {
10575                        /* If we were run as 'hush &', sleep until we are
10576                         * in the foreground (tty pgrp == our pgrp).
10577                         * If we get started under a job aware app (like bash),
10578                         * make sure we are now in charge so we don't fight over
10579                         * who gets the foreground */
10580                        while (1) {
10581                                pid_t shell_pgrp = getpgrp();
10582                                G_saved_tty_pgrp = tcgetpgrp(G_interactive_fd);
10583                                if (G_saved_tty_pgrp == shell_pgrp)
10584                                        break;
10585                                /* send TTIN to ourself (should stop us) */
10586                                kill(- shell_pgrp, SIGTTIN);
10587                        }
10588                }
10589
10590                /* Install more signal handlers */
10591                install_special_sighandlers();
10592
10593                if (G_saved_tty_pgrp) {
10594                        /* Set other signals to restore saved_tty_pgrp */
10595                        install_fatal_sighandlers();
10596                        /* Put ourselves in our own process group
10597                         * (bash, too, does this only if ctty is available) */
10598                        bb_setpgrp(); /* is the same as setpgid(our_pid, our_pid); */
10599                        /* Grab control of the terminal */
10600                        tcsetpgrp(G_interactive_fd, cached_getpid);
10601                }
10602                enable_restore_tty_pgrp_on_exit();
10603
10604# if ENABLE_FEATURE_EDITING
10605                G.line_input_state = new_line_input_t(FOR_SHELL);
10606#  if EDITING_HAS_get_exe_name
10607                G.line_input_state->get_exe_name = get_builtin_name;
10608#  endif
10609# endif
10610# if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0
10611                {
10612                        const char *hp = get_local_var_value("HISTFILE");
10613                        if (!hp) {
10614                                hp = get_local_var_value("HOME");
10615                                if (hp)
10616                                        hp = concat_path_file(hp, ".hush_history");
10617                        } else {
10618                                hp = xstrdup(hp);
10619                        }
10620                        if (hp) {
10621                                G.line_input_state->hist_file = hp;
10622                                //set_local_var(xasprintf("HISTFILE=%s", ...));
10623                        }
10624#  if ENABLE_FEATURE_SH_HISTFILESIZE
10625                        hp = get_local_var_value("HISTFILESIZE");
10626                        G.line_input_state->max_history = size_from_HISTFILESIZE(hp);
10627#  endif
10628                }
10629# endif
10630        } else {
10631                install_special_sighandlers();
10632        }
10633#elif ENABLE_HUSH_INTERACTIVE
10634        /* No job control compiled in, only prompt/line editing */
10635        if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
10636                G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, 254);
10637                if (G_interactive_fd < 0) {
10638                        /* try to dup to any fd */
10639                        G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, -1);
10640                        if (G_interactive_fd < 0)
10641                                /* give up */
10642                                G_interactive_fd = 0;
10643                }
10644        }
10645        if (G_interactive_fd) {
10646                close_on_exec_on(G_interactive_fd);
10647        }
10648        install_special_sighandlers();
10649#else
10650        /* We have interactiveness code disabled */
10651        install_special_sighandlers();
10652#endif
10653        /* bash:
10654         * if interactive but not a login shell, sources ~/.bashrc
10655         * (--norc turns this off, --rcfile <file> overrides)
10656         */
10657
10658        if (G_interactive_fd) {
10659#if ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT
10660                /* Set (but not export) PS1/2 unless already set */
10661                if (!get_local_var_value("PS1"))
10662                        set_local_var_from_halves("PS1", "\\w \\$ ");
10663                if (!get_local_var_value("PS2"))
10664                        set_local_var_from_halves("PS2", "> ");
10665#endif
10666                if (!ENABLE_FEATURE_SH_EXTRA_QUIET) {
10667                        /* note: ash and hush share this string */
10668                        printf("\n\n%s %s\n"
10669                                IF_HUSH_HELP("Enter 'help' for a list of built-in commands.\n")
10670                                "\n",
10671                                bb_banner,
10672                                "hush - the humble shell"
10673                        );
10674                }
10675        }
10676
10677        parse_and_run_file(hfopen(NULL)); /* stdin */
10678
10679 final_return:
10680        hush_exit(G.last_exitcode);
10681}
10682
10683
10684/*
10685 * Built-ins
10686 */
10687static int FAST_FUNC builtin_true(char **argv UNUSED_PARAM)
10688{
10689        return 0;
10690}
10691
10692#if ENABLE_HUSH_TEST || ENABLE_HUSH_ECHO || ENABLE_HUSH_PRINTF || ENABLE_HUSH_KILL
10693static NOINLINE int run_applet_main(char **argv, int (*applet_main_func)(int argc, char **argv))
10694{
10695        int argc = string_array_len(argv);
10696        return applet_main_func(argc, argv);
10697}
10698#endif
10699#if ENABLE_HUSH_TEST || BASH_TEST2
10700static int FAST_FUNC builtin_test(char **argv)
10701{
10702        return run_applet_main(argv, test_main);
10703}
10704#endif
10705#if ENABLE_HUSH_ECHO
10706static int FAST_FUNC builtin_echo(char **argv)
10707{
10708        return run_applet_main(argv, echo_main);
10709}
10710#endif
10711#if ENABLE_HUSH_PRINTF
10712static int FAST_FUNC builtin_printf(char **argv)
10713{
10714        return run_applet_main(argv, printf_main);
10715}
10716#endif
10717
10718#if ENABLE_HUSH_HELP
10719static int FAST_FUNC builtin_help(char **argv UNUSED_PARAM)
10720{
10721        const struct built_in_command *x;
10722
10723        printf(
10724                "Built-in commands:\n"
10725                "------------------\n");
10726        for (x = bltins1; x != &bltins1[ARRAY_SIZE(bltins1)]; x++) {
10727                if (x->b_descr)
10728                        printf("%-10s%s\n", x->b_cmd, x->b_descr);
10729        }
10730        return EXIT_SUCCESS;
10731}
10732#endif
10733
10734#if MAX_HISTORY && ENABLE_FEATURE_EDITING
10735static int FAST_FUNC builtin_history(char **argv UNUSED_PARAM)
10736{
10737        show_history(G.line_input_state);
10738        return EXIT_SUCCESS;
10739}
10740#endif
10741
10742static char **skip_dash_dash(char **argv)
10743{
10744        argv++;
10745        if (argv[0] && argv[0][0] == '-' && argv[0][1] == '-' && argv[0][2] == '\0')
10746                argv++;
10747        return argv;
10748}
10749
10750static int FAST_FUNC builtin_cd(char **argv)
10751{
10752        const char *newdir;
10753
10754        argv = skip_dash_dash(argv);
10755        newdir = argv[0];
10756        if (newdir == NULL) {
10757                /* bash does nothing (exitcode 0) if HOME is ""; if it's unset,
10758                 * bash says "bash: cd: HOME not set" and does nothing
10759                 * (exitcode 1)
10760                 */
10761                const char *home = get_local_var_value("HOME");
10762                newdir = home ? home : "/";
10763        }
10764        if (chdir(newdir)) {
10765                /* Mimic bash message exactly */
10766                bb_perror_msg("cd: %s", newdir);
10767                return EXIT_FAILURE;
10768        }
10769        /* Read current dir (get_cwd(1) is inside) and set PWD.
10770         * Note: do not enforce exporting. If PWD was unset or unexported,
10771         * set it again, but do not export. bash does the same.
10772         */
10773        set_pwd_var(/*flag:*/ 0);
10774        return EXIT_SUCCESS;
10775}
10776
10777static int FAST_FUNC builtin_pwd(char **argv UNUSED_PARAM)
10778{
10779        puts(get_cwd(0));
10780        return EXIT_SUCCESS;
10781}
10782
10783static int FAST_FUNC builtin_eval(char **argv)
10784{
10785        argv = skip_dash_dash(argv);
10786
10787        if (!argv[0])
10788                return EXIT_SUCCESS;
10789
10790        IF_HUSH_MODE_X(G.x_mode_depth++;)
10791        //bb_error_msg("%s: ++x_mode_depth=%d", __func__, G.x_mode_depth);
10792        if (!argv[1]) {
10793                /* bash:
10794                 * eval "echo Hi; done" ("done" is syntax error):
10795                 * "echo Hi" will not execute too.
10796                 */
10797                parse_and_run_string(argv[0]);
10798        } else {
10799                /* "The eval utility shall construct a command by
10800                 * concatenating arguments together, separating
10801                 * each with a <space> character."
10802                 */
10803                char *str, *p;
10804                unsigned len = 0;
10805                char **pp = argv;
10806                do
10807                        len += strlen(*pp) + 1;
10808                while (*++pp);
10809                str = p = xmalloc(len);
10810                pp = argv;
10811                for (;;) {
10812                        p = stpcpy(p, *pp);
10813                        pp++;
10814                        if (!*pp)
10815                                break;
10816                        *p++ = ' ';
10817                }
10818                parse_and_run_string(str);
10819                free(str);
10820        }
10821        IF_HUSH_MODE_X(G.x_mode_depth--;)
10822        //bb_error_msg("%s: --x_mode_depth=%d", __func__, G.x_mode_depth);
10823        return G.last_exitcode;
10824}
10825
10826static int FAST_FUNC builtin_exec(char **argv)
10827{
10828        argv = skip_dash_dash(argv);
10829        if (argv[0] == NULL)
10830                return EXIT_SUCCESS; /* bash does this */
10831
10832        /* Careful: we can end up here after [v]fork. Do not restore
10833         * tty pgrp then, only top-level shell process does that */
10834        if (G_saved_tty_pgrp && getpid() == G.root_pid)
10835                tcsetpgrp(G_interactive_fd, G_saved_tty_pgrp);
10836
10837        /* Saved-redirect fds, script fds and G_interactive_fd are still
10838         * open here. However, they are all CLOEXEC, and execv below
10839         * closes them. Try interactive "exec ls -l /proc/self/fd",
10840         * it should show no extra open fds in the "ls" process.
10841         * If we'd try to run builtins/NOEXECs, this would need improving.
10842         */
10843        //close_saved_fds_and_FILE_fds();
10844
10845        /* TODO: if exec fails, bash does NOT exit! We do.
10846         * We'll need to undo trap cleanup (it's inside execvp_or_die)
10847         * and tcsetpgrp, and this is inherently racy.
10848         */
10849        execvp_or_die(argv);
10850}
10851
10852static int FAST_FUNC builtin_exit(char **argv)
10853{
10854        debug_printf_exec("%s()\n", __func__);
10855
10856        /* interactive bash:
10857         * # trap "echo EEE" EXIT
10858         * # exit
10859         * exit
10860         * There are stopped jobs.
10861         * (if there are _stopped_ jobs, running ones don't count)
10862         * # exit
10863         * exit
10864         * EEE (then bash exits)
10865         *
10866         * TODO: we can use G.exiting = -1 as indicator "last cmd was exit"
10867         */
10868
10869        /* note: EXIT trap is run by hush_exit */
10870        argv = skip_dash_dash(argv);
10871        if (argv[0] == NULL) {
10872#if ENABLE_HUSH_TRAP
10873                if (G.pre_trap_exitcode >= 0) /* "exit" in trap uses $? from before the trap */
10874                        hush_exit(G.pre_trap_exitcode);
10875#endif
10876                hush_exit(G.last_exitcode);
10877        }
10878        /* mimic bash: exit 123abc == exit 255 + error msg */
10879        xfunc_error_retval = 255;
10880        /* bash: exit -2 == exit 254, no error msg */
10881        hush_exit(xatoi(argv[0]) & 0xff);
10882}
10883
10884#if ENABLE_HUSH_TYPE
10885/* http://www.opengroup.org/onlinepubs/9699919799/utilities/type.html */
10886static int FAST_FUNC builtin_type(char **argv)
10887{
10888        int ret = EXIT_SUCCESS;
10889
10890        while (*++argv) {
10891                const char *type;
10892                char *path = NULL;
10893
10894                if (0) {} /* make conditional compile easier below */
10895                /*else if (find_alias(*argv))
10896                        type = "an alias";*/
10897# if ENABLE_HUSH_FUNCTIONS
10898                else if (find_function(*argv))
10899                        type = "a function";
10900# endif
10901                else if (find_builtin(*argv))
10902                        type = "a shell builtin";
10903                else if ((path = find_in_path(*argv)) != NULL)
10904                        type = path;
10905                else {
10906                        bb_error_msg("type: %s: not found", *argv);
10907                        ret = EXIT_FAILURE;
10908                        continue;
10909                }
10910
10911                printf("%s is %s\n", *argv, type);
10912                free(path);
10913        }
10914
10915        return ret;
10916}
10917#endif
10918
10919#if ENABLE_HUSH_READ
10920/* Interruptibility of read builtin in bash
10921 * (tested on bash-4.2.8 by sending signals (not by ^C)):
10922 *
10923 * Empty trap makes read ignore corresponding signal, for any signal.
10924 *
10925 * SIGINT:
10926 * - terminates non-interactive shell;
10927 * - interrupts read in interactive shell;
10928 * if it has non-empty trap:
10929 * - executes trap and returns to command prompt in interactive shell;
10930 * - executes trap and returns to read in non-interactive shell;
10931 * SIGTERM:
10932 * - is ignored (does not interrupt) read in interactive shell;
10933 * - terminates non-interactive shell;
10934 * if it has non-empty trap:
10935 * - executes trap and returns to read;
10936 * SIGHUP:
10937 * - terminates shell (regardless of interactivity);
10938 * if it has non-empty trap:
10939 * - executes trap and returns to read;
10940 * SIGCHLD from children:
10941 * - does not interrupt read regardless of interactivity:
10942 *   try: sleep 1 & read x; echo $x
10943 */
10944static int FAST_FUNC builtin_read(char **argv)
10945{
10946        const char *r;
10947        struct builtin_read_params params;
10948
10949        memset(&params, 0, sizeof(params));
10950
10951        /* "!": do not abort on errors.
10952         * Option string must start with "sr" to match BUILTIN_READ_xxx
10953         */
10954        params.read_flags = getopt32(argv,
10955# if BASH_READ_D
10956                IF_NOT_HUSH_BASH_COMPAT("^")
10957                "!srn:p:t:u:d:" IF_NOT_HUSH_BASH_COMPAT("\0" "-1"/*min 1 arg*/),
10958                &params.opt_n, &params.opt_p, &params.opt_t, &params.opt_u, &params.opt_d
10959# else
10960                IF_NOT_HUSH_BASH_COMPAT("^")
10961                "!srn:p:t:u:" IF_NOT_HUSH_BASH_COMPAT("\0" "-1"/*min 1 arg*/),
10962                &params.opt_n, &params.opt_p, &params.opt_t, &params.opt_u
10963# endif
10964//TODO: print "read: need variable name"
10965//for the case of !BASH "read" with no args (now it fails silently)
10966//(or maybe extend getopt32() to emit a message if "-1" fails)
10967        );
10968        if ((uint32_t)params.read_flags == (uint32_t)-1)
10969                return EXIT_FAILURE;
10970        argv += optind;
10971        params.argv = argv;
10972        params.setvar = set_local_var_from_halves;
10973        params.ifs = get_local_var_value("IFS"); /* can be NULL */
10974
10975 again:
10976        r = shell_builtin_read(&params);
10977
10978        if ((uintptr_t)r == 1 && errno == EINTR) {
10979                unsigned sig = check_and_run_traps();
10980                if (sig != SIGINT)
10981                        goto again;
10982        }
10983
10984        if ((uintptr_t)r > 1) {
10985                bb_simple_error_msg(r);
10986                r = (char*)(uintptr_t)1;
10987        }
10988
10989        return (uintptr_t)r;
10990}
10991#endif
10992
10993#if ENABLE_HUSH_UMASK
10994static int FAST_FUNC builtin_umask(char **argv)
10995{
10996        int rc;
10997        mode_t mask;
10998
10999        rc = 1;
11000        mask = umask(0);
11001        argv = skip_dash_dash(argv);
11002        if (argv[0]) {
11003                mode_t old_mask = mask;
11004
11005                /* numeric umasks are taken as-is */
11006                /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
11007                if (!isdigit(argv[0][0]))
11008                        mask ^= 0777;
11009                mask = bb_parse_mode(argv[0], mask);
11010                if (!isdigit(argv[0][0]))
11011                        mask ^= 0777;
11012                if ((unsigned)mask > 0777) {
11013                        mask = old_mask;
11014                        /* bash messages:
11015                         * bash: umask: 'q': invalid symbolic mode operator
11016                         * bash: umask: 999: octal number out of range
11017                         */
11018                        bb_error_msg("%s: invalid mode '%s'", "umask", argv[0]);
11019                        rc = 0;
11020                }
11021        } else {
11022                /* Mimic bash */
11023                printf("%04o\n", (unsigned) mask);
11024                /* fall through and restore mask which we set to 0 */
11025        }
11026        umask(mask);
11027
11028        return !rc; /* rc != 0 - success */
11029}
11030#endif
11031
11032#if ENABLE_HUSH_EXPORT || ENABLE_HUSH_TRAP
11033static void print_escaped(const char *s)
11034{
11035        if (*s == '\'')
11036                goto squote;
11037        do {
11038                const char *p = strchrnul(s, '\'');
11039                /* print 'xxxx', possibly just '' */
11040                printf("'%.*s'", (int)(p - s), s);
11041                if (*p == '\0')
11042                        break;
11043                s = p;
11044 squote:
11045                /* s points to '; print "'''...'''" */
11046                putchar('"');
11047                do putchar('\''); while (*++s == '\'');
11048                putchar('"');
11049        } while (*s);
11050}
11051#endif
11052
11053#if ENABLE_HUSH_EXPORT || ENABLE_HUSH_LOCAL || ENABLE_HUSH_READONLY
11054static int helper_export_local(char **argv, unsigned flags)
11055{
11056        do {
11057                char *name = *argv;
11058                const char *name_end = endofname(name);
11059
11060                if (*name_end == '\0') {
11061                        struct variable *var, **vpp;
11062
11063                        vpp = get_ptr_to_local_var(name, name_end - name);
11064                        var = vpp ? *vpp : NULL;
11065
11066                        if (flags & SETFLAG_UNEXPORT) {
11067                                /* export -n NAME (without =VALUE) */
11068                                if (var) {
11069                                        var->flg_export = 0;
11070                                        debug_printf_env("%s: unsetenv '%s'\n", __func__, name);
11071                                        unsetenv(name);
11072                                } /* else: export -n NOT_EXISTING_VAR: no-op */
11073                                continue;
11074                        }
11075                        if (flags & SETFLAG_EXPORT) {
11076                                /* export NAME (without =VALUE) */
11077                                if (var) {
11078                                        var->flg_export = 1;
11079                                        debug_printf_env("%s: putenv '%s'\n", __func__, var->varstr);
11080                                        putenv(var->varstr);
11081                                        continue;
11082                                }
11083                        }
11084                        if (flags & SETFLAG_MAKE_RO) {
11085                                /* readonly NAME (without =VALUE) */
11086                                if (var) {
11087                                        var->flg_read_only = 1;
11088                                        continue;
11089                                }
11090                        }
11091# if ENABLE_HUSH_LOCAL
11092                        /* Is this "local" bltin? */
11093                        if (!(flags & (SETFLAG_EXPORT|SETFLAG_UNEXPORT|SETFLAG_MAKE_RO))) {
11094                                unsigned lvl = flags >> SETFLAG_VARLVL_SHIFT;
11095                                if (var && var->var_nest_level == lvl) {
11096                                        /* "local x=abc; ...; local x" - ignore second local decl */
11097                                        continue;
11098                                }
11099                        }
11100# endif
11101                        /* Exporting non-existing variable.
11102                         * bash does not put it in environment,
11103                         * but remembers that it is exported,
11104                         * and does put it in env when it is set later.
11105                         * We just set it to "" and export.
11106                         */
11107                        /* Or, it's "local NAME" (without =VALUE).
11108                         * bash sets the value to "".
11109                         */
11110                        /* Or, it's "readonly NAME" (without =VALUE).
11111                         * bash remembers NAME and disallows its creation
11112                         * in the future.
11113                         */
11114                        name = xasprintf("%s=", name);
11115                } else {
11116                        if (*name_end != '=') {
11117                                bb_error_msg("'%s': bad variable name", name);
11118                                /* do not parse following argv[]s: */
11119                                return 1;
11120                        }
11121                        /* (Un)exporting/making local NAME=VALUE */
11122                        name = xstrdup(name);
11123                        /* Testcase: export PS1='\w \$ ' */
11124                        unbackslash(name);
11125                }
11126                debug_printf_env("%s: set_local_var('%s')\n", __func__, name);
11127                if (set_local_var(name, flags))
11128                        return EXIT_FAILURE;
11129        } while (*++argv);
11130        return EXIT_SUCCESS;
11131}
11132#endif
11133
11134#if ENABLE_HUSH_EXPORT
11135static int FAST_FUNC builtin_export(char **argv)
11136{
11137        unsigned opt_unexport;
11138
11139# if ENABLE_HUSH_EXPORT_N
11140        /* "!": do not abort on errors */
11141        opt_unexport = getopt32(argv, "!n");
11142        if (opt_unexport == (uint32_t)-1)
11143                return EXIT_FAILURE;
11144        argv += optind;
11145# else
11146        opt_unexport = 0;
11147        argv++;
11148# endif
11149
11150        if (argv[0] == NULL) {
11151                char **e = environ;
11152                if (e) {
11153                        while (*e) {
11154# if 0
11155                                puts(*e++);
11156# else
11157                                /* ash emits: export VAR='VAL'
11158                                 * bash: declare -x VAR="VAL"
11159                                 * we follow ash example */
11160                                const char *s = *e++;
11161                                const char *p = strchr(s, '=');
11162
11163                                if (!p) /* wtf? take next variable */
11164                                        continue;
11165                                /* export var= */
11166                                printf("export %.*s", (int)(p - s) + 1, s);
11167                                print_escaped(p + 1);
11168                                putchar('\n');
11169# endif
11170                        }
11171                        /*fflush_all(); - done after each builtin anyway */
11172                }
11173                return EXIT_SUCCESS;
11174        }
11175
11176        return helper_export_local(argv, opt_unexport ? SETFLAG_UNEXPORT : SETFLAG_EXPORT);
11177}
11178#endif
11179
11180#if ENABLE_HUSH_LOCAL
11181static int FAST_FUNC builtin_local(char **argv)
11182{
11183        if (G.func_nest_level == 0) {
11184                bb_error_msg("%s: not in a function", argv[0]);
11185                return EXIT_FAILURE; /* bash compat */
11186        }
11187        argv++;
11188        /* Since all builtins run in a nested variable level,
11189         * need to use level - 1 here. Or else the variable will be removed at once
11190         * after builtin returns.
11191         */
11192        return helper_export_local(argv, (G.var_nest_level - 1) << SETFLAG_VARLVL_SHIFT);
11193}
11194#endif
11195
11196#if ENABLE_HUSH_READONLY
11197static int FAST_FUNC builtin_readonly(char **argv)
11198{
11199        argv++;
11200        if (*argv == NULL) {
11201                /* bash: readonly [-p]: list all readonly VARs
11202                 * (-p has no effect in bash)
11203                 */
11204                struct variable *e;
11205                for (e = G.top_var; e; e = e->next) {
11206                        if (e->flg_read_only) {
11207//TODO: quote value: readonly VAR='VAL'
11208                                printf("readonly %s\n", e->varstr);
11209                        }
11210                }
11211                return EXIT_SUCCESS;
11212        }
11213        return helper_export_local(argv, SETFLAG_MAKE_RO);
11214}
11215#endif
11216
11217#if ENABLE_HUSH_UNSET
11218/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#unset */
11219static int FAST_FUNC builtin_unset(char **argv)
11220{
11221        int ret;
11222        unsigned opts;
11223
11224        /* "!": do not abort on errors */
11225        /* "+": stop at 1st non-option */
11226        opts = getopt32(argv, "!+vf");
11227        if (opts == (unsigned)-1)
11228                return EXIT_FAILURE;
11229        if (opts == 3) {
11230                bb_simple_error_msg("unset: -v and -f are exclusive");
11231                return EXIT_FAILURE;
11232        }
11233        argv += optind;
11234
11235        ret = EXIT_SUCCESS;
11236        while (*argv) {
11237                if (!(opts & 2)) { /* not -f */
11238                        if (unset_local_var(*argv)) {
11239                                /* unset <nonexistent_var> doesn't fail.
11240                                 * Error is when one tries to unset RO var.
11241                                 * Message was printed by unset_local_var. */
11242                                ret = EXIT_FAILURE;
11243                        }
11244                }
11245# if ENABLE_HUSH_FUNCTIONS
11246                else {
11247                        unset_func(*argv);
11248                }
11249# endif
11250                argv++;
11251        }
11252        return ret;
11253}
11254#endif
11255
11256#if ENABLE_HUSH_SET
11257/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set
11258 * built-in 'set' handler
11259 * SUSv3 says:
11260 * set [-abCefhmnuvx] [-o option] [argument...]
11261 * set [+abCefhmnuvx] [+o option] [argument...]
11262 * set -- [argument...]
11263 * set -o
11264 * set +o
11265 * Implementations shall support the options in both their hyphen and
11266 * plus-sign forms. These options can also be specified as options to sh.
11267 * Examples:
11268 * Write out all variables and their values: set
11269 * Set $1, $2, and $3 and set "$#" to 3: set c a b
11270 * Turn on the -x and -v options: set -xv
11271 * Unset all positional parameters: set --
11272 * Set $1 to the value of x, even if it begins with '-' or '+': set -- "$x"
11273 * Set the positional parameters to the expansion of x, even if x expands
11274 * with a leading '-' or '+': set -- $x
11275 *
11276 * So far, we only support "set -- [argument...]" and some of the short names.
11277 */
11278static int FAST_FUNC builtin_set(char **argv)
11279{
11280        int n;
11281        char **pp, **g_argv;
11282        char *arg = *++argv;
11283
11284        if (arg == NULL) {
11285                struct variable *e;
11286                for (e = G.top_var; e; e = e->next)
11287                        puts(e->varstr);
11288                return EXIT_SUCCESS;
11289        }
11290
11291        do {
11292                if (strcmp(arg, "--") == 0) {
11293                        ++argv;
11294                        goto set_argv;
11295                }
11296                if (arg[0] != '+' && arg[0] != '-')
11297                        break;
11298                for (n = 1; arg[n]; ++n) {
11299                        if (set_mode((arg[0] == '-'), arg[n], argv[1])) {
11300                                bb_error_msg("%s: %s: invalid option", "set", arg);
11301                                return EXIT_FAILURE;
11302                        }
11303                        if (arg[n] == 'o' && argv[1])
11304                                argv++;
11305                }
11306        } while ((arg = *++argv) != NULL);
11307        /* Now argv[0] is 1st argument */
11308
11309        if (arg == NULL)
11310                return EXIT_SUCCESS;
11311 set_argv:
11312
11313        /* NB: G.global_argv[0] ($0) is never freed/changed */
11314        g_argv = G.global_argv;
11315        if (G.global_args_malloced) {
11316                pp = g_argv;
11317                while (*++pp)
11318                        free(*pp);
11319                g_argv[1] = NULL;
11320        } else {
11321                G.global_args_malloced = 1;
11322                pp = xzalloc(sizeof(pp[0]) * 2);
11323                pp[0] = g_argv[0]; /* retain $0 */
11324                g_argv = pp;
11325        }
11326        /* This realloc's G.global_argv */
11327        G.global_argv = pp = add_strings_to_strings(g_argv, argv, /*dup:*/ 1);
11328
11329        G.global_argc = 1 + string_array_len(pp + 1);
11330
11331        return EXIT_SUCCESS;
11332}
11333#endif
11334
11335static int FAST_FUNC builtin_shift(char **argv)
11336{
11337        int n = 1;
11338        argv = skip_dash_dash(argv);
11339        if (argv[0]) {
11340                n = bb_strtou(argv[0], NULL, 10);
11341                if (errno || n < 0) {
11342                        /* shared string with ash.c */
11343                        bb_error_msg("Illegal number: %s", argv[0]);
11344                        /*
11345                         * ash aborts in this case.
11346                         * bash prints error message and set $? to 1.
11347                         * Interestingly, for "shift 99999" bash does not
11348                         * print error message, but does set $? to 1
11349                         * (and does no shifting at all).
11350                         */
11351                }
11352        }
11353        if (n >= 0 && n < G.global_argc) {
11354                if (G_global_args_malloced) {
11355                        int m = 1;
11356                        while (m <= n)
11357                                free(G.global_argv[m++]);
11358                }
11359                G.global_argc -= n;
11360                memmove(&G.global_argv[1], &G.global_argv[n+1],
11361                                G.global_argc * sizeof(G.global_argv[0]));
11362                return EXIT_SUCCESS;
11363        }
11364        return EXIT_FAILURE;
11365}
11366
11367#if ENABLE_HUSH_GETOPTS
11368static int FAST_FUNC builtin_getopts(char **argv)
11369{
11370/* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getopts.html
11371
11372TODO:
11373If a required argument is not found, and getopts is not silent,
11374a question mark (?) is placed in VAR, OPTARG is unset, and a
11375diagnostic message is printed.  If getopts is silent, then a
11376colon (:) is placed in VAR and OPTARG is set to the option
11377character found.
11378
11379Test that VAR is a valid variable name?
11380
11381"Whenever the shell is invoked, OPTIND shall be initialized to 1"
11382*/
11383        char cbuf[2];
11384        const char *cp, *optstring, *var;
11385        int c, n, exitcode, my_opterr;
11386        unsigned count;
11387
11388        optstring = *++argv;
11389        if (!optstring || !(var = *++argv)) {
11390                bb_simple_error_msg("usage: getopts OPTSTRING VAR [ARGS]");
11391                return EXIT_FAILURE;
11392        }
11393
11394        if (argv[1])
11395                argv[0] = G.global_argv[0]; /* for error messages in getopt() */
11396        else
11397                argv = G.global_argv;
11398        cbuf[1] = '\0';
11399
11400        my_opterr = 0;
11401        if (optstring[0] != ':') {
11402                cp = get_local_var_value("OPTERR");
11403                /* 0 if "OPTERR=0", 1 otherwise */
11404                my_opterr = (!cp || NOT_LONE_CHAR(cp, '0'));
11405        }
11406
11407        /* getopts stops on first non-option. Add "+" to force that */
11408        /*if (optstring[0] != '+')*/ {
11409                char *s = alloca(strlen(optstring) + 2);
11410                sprintf(s, "+%s", optstring);
11411                optstring = s;
11412        }
11413
11414        /* Naively, now we should just
11415         *      cp = get_local_var_value("OPTIND");
11416         *      optind = cp ? atoi(cp) : 0;
11417         *      optarg = NULL;
11418         *      opterr = my_opterr;
11419         *      c = getopt(string_array_len(argv), argv, optstring);
11420         * and be done? Not so fast...
11421         * Unlike normal getopt() usage in C programs, here
11422         * each successive call will (usually) have the same argv[] CONTENTS,
11423         * but not the ADDRESSES. Worse yet, it's possible that between
11424         * invocations of "getopts", there will be calls to shell builtins
11425         * which use getopt() internally. Example:
11426         *      while getopts "abc" RES -a -bc -abc de; do
11427         *              unset -ff func
11428         *      done
11429         * This would not work correctly: getopt() call inside "unset"
11430         * modifies internal libc state which is tracking position in
11431         * multi-option strings ("-abc"). At best, it can skip options
11432         * or return the same option infinitely. With glibc implementation
11433         * of getopt(), it would use outright invalid pointers and return
11434         * garbage even _without_ "unset" mangling internal state.
11435         *
11436         * We resort to resetting getopt() state and calling it N times,
11437         * until we get Nth result (or failure).
11438         * (N == G.getopt_count is reset to 0 whenever OPTIND is [un]set).
11439         */
11440        GETOPT_RESET();
11441        count = 0;
11442        n = string_array_len(argv);
11443        do {
11444                optarg = NULL;
11445                opterr = (count < G.getopt_count) ? 0 : my_opterr;
11446                c = getopt(n, argv, optstring);
11447                if (c < 0)
11448                        break;
11449                count++;
11450        } while (count <= G.getopt_count);
11451
11452        /* Set OPTIND. Prevent resetting of the magic counter! */
11453        set_local_var_from_halves("OPTIND", utoa(optind));
11454        G.getopt_count = count; /* "next time, give me N+1'th result" */
11455        GETOPT_RESET(); /* just in case */
11456
11457        /* Set OPTARG */
11458        /* Always set or unset, never left as-is, even on exit/error:
11459         * "If no option was found, or if the option that was found
11460         * does not have an option-argument, OPTARG shall be unset."
11461         */
11462        cp = optarg;
11463        if (c == '?') {
11464                /* If ":optstring" and unknown option is seen,
11465                 * it is stored to OPTARG.
11466                 */
11467                if (optstring[1] == ':') {
11468                        cbuf[0] = optopt;
11469                        cp = cbuf;
11470                }
11471        }
11472        if (cp)
11473                set_local_var_from_halves("OPTARG", cp);
11474        else
11475                unset_local_var("OPTARG");
11476
11477        /* Convert -1 to "?" */
11478        exitcode = EXIT_SUCCESS;
11479        if (c < 0) { /* -1: end of options */
11480                exitcode = EXIT_FAILURE;
11481                c = '?';
11482        }
11483
11484        /* Set VAR */
11485        cbuf[0] = c;
11486        set_local_var_from_halves(var, cbuf);
11487
11488        return exitcode;
11489}
11490#endif
11491
11492static int FAST_FUNC builtin_source(char **argv)
11493{
11494        char *arg_path, *filename;
11495        HFILE *input;
11496        save_arg_t sv;
11497        char *args_need_save;
11498#if ENABLE_HUSH_FUNCTIONS
11499        smallint sv_flg;
11500#endif
11501
11502        argv = skip_dash_dash(argv);
11503        filename = argv[0];
11504        if (!filename) {
11505                /* bash says: "bash: .: filename argument required" */
11506                return 2; /* bash compat */
11507        }
11508        arg_path = NULL;
11509        if (!strchr(filename, '/')) {
11510                arg_path = find_in_path(filename);
11511                if (arg_path)
11512                        filename = arg_path;
11513                else if (!ENABLE_HUSH_BASH_SOURCE_CURDIR) {
11514                        errno = ENOENT;
11515                        bb_simple_perror_msg(filename);
11516                        return EXIT_FAILURE;
11517                }
11518        }
11519        input = hfopen(filename);
11520        free(arg_path);
11521        if (!input) {
11522                bb_perror_msg("%s", filename);
11523                /* POSIX: non-interactive shell should abort here,
11524                 * not merely fail. So far no one complained :)
11525                 */
11526                return EXIT_FAILURE;
11527        }
11528
11529#if ENABLE_HUSH_FUNCTIONS
11530        sv_flg = G_flag_return_in_progress;
11531        /* "we are inside sourced file, ok to use return" */
11532        G_flag_return_in_progress = -1;
11533#endif
11534        args_need_save = argv[1]; /* used as a boolean variable */
11535        if (args_need_save)
11536                save_and_replace_G_args(&sv, argv);
11537
11538        /* "false; . ./empty_line; echo Zero:$?" should print 0 */
11539        G.last_exitcode = 0;
11540        parse_and_run_file(input);
11541        hfclose(input);
11542
11543        if (args_need_save) /* can't use argv[1] instead: "shift" can mangle it */
11544                restore_G_args(&sv, argv);
11545#if ENABLE_HUSH_FUNCTIONS
11546        G_flag_return_in_progress = sv_flg;
11547#endif
11548
11549        return G.last_exitcode;
11550}
11551
11552#if ENABLE_HUSH_TRAP
11553static int FAST_FUNC builtin_trap(char **argv)
11554{
11555        int sig;
11556        char *new_cmd;
11557
11558        if (!G_traps)
11559                G_traps = xzalloc(sizeof(G_traps[0]) * NSIG);
11560
11561        argv++;
11562        if (!*argv) {
11563                int i;
11564                /* No args: print all trapped */
11565                for (i = 0; i < NSIG; ++i) {
11566                        if (G_traps[i]) {
11567                                printf("trap -- ");
11568                                print_escaped(G_traps[i]);
11569                                /* note: bash adds "SIG", but only if invoked
11570                                 * as "bash". If called as "sh", or if set -o posix,
11571                                 * then it prints short signal names.
11572                                 * We are printing short names: */
11573                                printf(" %s\n", get_signame(i));
11574                        }
11575                }
11576                /*fflush_all(); - done after each builtin anyway */
11577                return EXIT_SUCCESS;
11578        }
11579
11580        new_cmd = NULL;
11581        /* If first arg is a number: reset all specified signals */
11582        sig = bb_strtou(*argv, NULL, 10);
11583        if (errno == 0) {
11584                int ret;
11585 process_sig_list:
11586                ret = EXIT_SUCCESS;
11587                while (*argv) {
11588                        sighandler_t handler;
11589
11590                        sig = get_signum(*argv++);
11591                        if (sig < 0) {
11592                                ret = EXIT_FAILURE;
11593                                /* Mimic bash message exactly */
11594                                bb_error_msg("trap: %s: invalid signal specification", argv[-1]);
11595                                continue;
11596                        }
11597
11598                        free(G_traps[sig]);
11599                        G_traps[sig] = xstrdup(new_cmd);
11600
11601                        debug_printf("trap: setting SIG%s (%i) to '%s'\n",
11602                                get_signame(sig), sig, G_traps[sig]);
11603
11604                        /* There is no signal for 0 (EXIT) */
11605                        if (sig == 0)
11606                                continue;
11607
11608                        if (new_cmd)
11609                                handler = (new_cmd[0] ? record_pending_signo : SIG_IGN);
11610                        else
11611                                /* We are removing trap handler */
11612                                handler = pick_sighandler(sig);
11613                        install_sighandler(sig, handler);
11614                }
11615                return ret;
11616        }
11617
11618        if (!argv[1]) { /* no second arg */
11619                bb_simple_error_msg("trap: invalid arguments");
11620                return EXIT_FAILURE;
11621        }
11622
11623        /* First arg is "-": reset all specified to default */
11624        /* First arg is "--": skip it, the rest is "handler SIGs..." */
11625        /* Everything else: set arg as signal handler
11626         * (includes "" case, which ignores signal) */
11627        if (argv[0][0] == '-') {
11628                if (argv[0][1] == '\0') { /* "-" */
11629                        /* new_cmd remains NULL: "reset these sigs" */
11630                        goto reset_traps;
11631                }
11632                if (argv[0][1] == '-' && argv[0][2] == '\0') { /* "--" */
11633                        argv++;
11634                }
11635                /* else: "-something", no special meaning */
11636        }
11637        new_cmd = *argv;
11638 reset_traps:
11639        argv++;
11640        goto process_sig_list;
11641}
11642#endif
11643
11644#if ENABLE_HUSH_JOB
11645static struct pipe *parse_jobspec(const char *str)
11646{
11647        struct pipe *pi;
11648        unsigned jobnum;
11649
11650        if (sscanf(str, "%%%u", &jobnum) != 1) {
11651                if (str[0] != '%'
11652                 || (str[1] != '%' && str[1] != '+' && str[1] != '\0')
11653                ) {
11654                        bb_error_msg("bad argument '%s'", str);
11655                        return NULL;
11656                }
11657                /* It is "%%", "%+" or "%" - current job */
11658                jobnum = G.last_jobid;
11659                if (jobnum == 0) {
11660                        bb_simple_error_msg("no current job");
11661                        return NULL;
11662                }
11663        }
11664        for (pi = G.job_list; pi; pi = pi->next) {
11665                if (pi->jobid == jobnum) {
11666                        return pi;
11667                }
11668        }
11669        bb_error_msg("%u: no such job", jobnum);
11670        return NULL;
11671}
11672
11673static int FAST_FUNC builtin_jobs(char **argv UNUSED_PARAM)
11674{
11675        struct pipe *job;
11676        const char *status_string;
11677
11678        checkjobs(NULL, 0 /*(no pid to wait for)*/);
11679        for (job = G.job_list; job; job = job->next) {
11680                if (job->alive_cmds == job->stopped_cmds)
11681                        status_string = "Stopped";
11682                else
11683                        status_string = "Running";
11684
11685                printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->cmdtext);
11686        }
11687
11688        clean_up_last_dead_job();
11689
11690        return EXIT_SUCCESS;
11691}
11692
11693/* built-in 'fg' and 'bg' handler */
11694static int FAST_FUNC builtin_fg_bg(char **argv)
11695{
11696        int i;
11697        struct pipe *pi;
11698
11699        if (!G_interactive_fd)
11700                return EXIT_FAILURE;
11701
11702        /* If they gave us no args, assume they want the last backgrounded task */
11703        if (!argv[1]) {
11704                for (pi = G.job_list; pi; pi = pi->next) {
11705                        if (pi->jobid == G.last_jobid) {
11706                                goto found;
11707                        }
11708                }
11709                bb_error_msg("%s: no current job", argv[0]);
11710                return EXIT_FAILURE;
11711        }
11712
11713        pi = parse_jobspec(argv[1]);
11714        if (!pi)
11715                return EXIT_FAILURE;
11716 found:
11717        /* TODO: bash prints a string representation
11718         * of job being foregrounded (like "sleep 1 | cat") */
11719        if (argv[0][0] == 'f' && G_saved_tty_pgrp) {
11720                /* Put the job into the foreground.  */
11721                tcsetpgrp(G_interactive_fd, pi->pgrp);
11722        }
11723
11724        /* Restart the processes in the job */
11725        debug_printf_jobs("reviving %d procs, pgrp %d\n", pi->num_cmds, pi->pgrp);
11726        for (i = 0; i < pi->num_cmds; i++) {
11727                debug_printf_jobs("reviving pid %d\n", pi->cmds[i].pid);
11728        }
11729        pi->stopped_cmds = 0;
11730
11731        i = kill(- pi->pgrp, SIGCONT);
11732        if (i < 0) {
11733                if (errno == ESRCH) {
11734                        delete_finished_job(pi);
11735                        return EXIT_SUCCESS;
11736                }
11737                bb_simple_perror_msg("kill (SIGCONT)");
11738        }
11739
11740        if (argv[0][0] == 'f') {
11741                remove_job_from_table(pi); /* FG job shouldn't be in job table */
11742                return checkjobs_and_fg_shell(pi);
11743        }
11744        return EXIT_SUCCESS;
11745}
11746#endif
11747
11748#if ENABLE_HUSH_KILL
11749static int FAST_FUNC builtin_kill(char **argv)
11750{
11751        int ret = 0;
11752
11753# if ENABLE_HUSH_JOB
11754        if (argv[1] && strcmp(argv[1], "-l") != 0) {
11755                int i = 1;
11756
11757                do {
11758                        struct pipe *pi;
11759                        char *dst;
11760                        int j, n;
11761
11762                        if (argv[i][0] != '%')
11763                                continue;
11764                        /*
11765                         * "kill %N" - job kill
11766                         * Converting to pgrp / pid kill
11767                         */
11768                        pi = parse_jobspec(argv[i]);
11769                        if (!pi) {
11770                                /* Eat bad jobspec */
11771                                j = i;
11772                                do {
11773                                        j++;
11774                                        argv[j - 1] = argv[j];
11775                                } while (argv[j]);
11776                                ret = 1;
11777                                i--;
11778                                continue;
11779                        }
11780                        /*
11781                         * In jobs started under job control, we signal
11782                         * entire process group by kill -PGRP_ID.
11783                         * This happens, f.e., in interactive shell.
11784                         *
11785                         * Otherwise, we signal each child via
11786                         * kill PID1 PID2 PID3.
11787                         * Testcases:
11788                         * sh -c 'sleep 1|sleep 1 & kill %1'
11789                         * sh -c 'true|sleep 2 & sleep 1; kill %1'
11790                         * sh -c 'true|sleep 1 & sleep 2; kill %1'
11791                         */
11792                        n = G_interactive_fd ? 1 : pi->num_cmds;
11793                        dst = alloca(n * sizeof(int)*4);
11794                        argv[i] = dst;
11795                        if (G_interactive_fd)
11796                                dst += sprintf(dst, " -%u", (int)pi->pgrp);
11797                        else for (j = 0; j < n; j++) {
11798                                struct command *cmd = &pi->cmds[j];
11799                                /* Skip exited members of the job */
11800                                if (cmd->pid == 0)
11801                                        continue;
11802                                /*
11803                                 * kill_main has matching code to expect
11804                                 * leading space. Needed to not confuse
11805                                 * negative pids with "kill -SIGNAL_NO" syntax
11806                                 */
11807                                dst += sprintf(dst, " %u", (int)cmd->pid);
11808                        }
11809                        *dst = '\0';
11810                } while (argv[++i]);
11811        }
11812# endif
11813
11814        if (argv[1] || ret == 0) {
11815                ret = run_applet_main(argv, kill_main);
11816        }
11817        /* else: ret = 1, "kill %bad_jobspec" case */
11818        return ret;
11819}
11820#endif
11821
11822#if ENABLE_HUSH_WAIT
11823/* http://www.opengroup.org/onlinepubs/9699919799/utilities/wait.html */
11824# if !ENABLE_HUSH_JOB
11825#  define wait_for_child_or_signal(pipe,pid) wait_for_child_or_signal(pid)
11826# endif
11827static int wait_for_child_or_signal(struct pipe *waitfor_pipe, pid_t waitfor_pid)
11828{
11829        int ret = 0;
11830        for (;;) {
11831                int sig;
11832                sigset_t oldset;
11833
11834                if (!sigisemptyset(&G.pending_set))
11835                        goto check_sig;
11836
11837                /* waitpid is not interruptible by SA_RESTARTed
11838                 * signals which we use. Thus, this ugly dance:
11839                 */
11840
11841                /* Make sure possible SIGCHLD is stored in kernel's
11842                 * pending signal mask before we call waitpid.
11843                 * Or else we may race with SIGCHLD, lose it,
11844                 * and get stuck in sigsuspend...
11845                 */
11846                sigfillset(&oldset); /* block all signals, remember old set */
11847                sigprocmask2(SIG_SETMASK, &oldset);
11848
11849                if (!sigisemptyset(&G.pending_set)) {
11850                        /* Crap! we raced with some signal! */
11851                        goto restore;
11852                }
11853
11854                /*errno = 0; - checkjobs does this */
11855/* Can't pass waitfor_pipe into checkjobs(): it won't be interruptible */
11856                ret = checkjobs(NULL, waitfor_pid); /* waitpid(WNOHANG) inside */
11857                debug_printf_exec("checkjobs:%d\n", ret);
11858# if ENABLE_HUSH_JOB
11859                if (waitfor_pipe) {
11860                        int rcode = job_exited_or_stopped(waitfor_pipe);
11861                        debug_printf_exec("job_exited_or_stopped:%d\n", rcode);
11862                        if (rcode >= 0) {
11863                                ret = rcode;
11864                                sigprocmask(SIG_SETMASK, &oldset, NULL);
11865                                break;
11866                        }
11867                }
11868# endif
11869                /* if ECHILD, there are no children (ret is -1 or 0) */
11870                /* if ret == 0, no children changed state */
11871                /* if ret != 0, it's exitcode+1 of exited waitfor_pid child */
11872                if (errno == ECHILD || ret) {
11873                        ret--;
11874                        if (ret < 0) /* if ECHILD, may need to fix "ret" */
11875                                ret = 0;
11876# if ENABLE_HUSH_BASH_COMPAT
11877                        if (waitfor_pid == -1 && errno == ECHILD) {
11878                                /* exitcode of "wait -n" with no children is 127, not 0 */
11879                                ret = 127;
11880                        }
11881# endif
11882                        sigprocmask(SIG_SETMASK, &oldset, NULL);
11883                        break;
11884                }
11885                /* Wait for SIGCHLD or any other signal */
11886                /* It is vitally important for sigsuspend that SIGCHLD has non-DFL handler! */
11887                /* Note: sigsuspend invokes signal handler */
11888                sigsuspend(&oldset);
11889                /* ^^^ add "sigdelset(&oldset, SIGCHLD)" before sigsuspend
11890                 * to make sure SIGCHLD is not masked off?
11891                 * It was reported that this:
11892                 *      fn() { : | return; }
11893                 *      shopt -s lastpipe
11894                 *      fn
11895                 *      exec hush SCRIPT
11896                 * under bash 4.4.23 runs SCRIPT with SIGCHLD masked,
11897                 * making "wait" commands in SCRIPT block forever.
11898                 */
11899 restore:
11900                sigprocmask(SIG_SETMASK, &oldset, NULL);
11901 check_sig:
11902                /* So, did we get a signal? */
11903                sig = check_and_run_traps();
11904                if (sig /*&& sig != SIGCHLD - always true */) {
11905                        /* Do this for any (non-ignored) signal, not only for ^C */
11906                        ret = 128 | sig;
11907                        break;
11908                }
11909                /* SIGCHLD, or no signal, or ignored one, such as SIGQUIT. Repeat */
11910        }
11911        return ret;
11912}
11913
11914static int FAST_FUNC builtin_wait(char **argv)
11915{
11916        int ret;
11917        int status;
11918
11919        argv = skip_dash_dash(argv);
11920# if ENABLE_HUSH_BASH_COMPAT
11921        if (argv[0] && strcmp(argv[0], "-n") == 0) {
11922                /* wait -n */
11923                /* (bash accepts "wait -n PID" too and ignores PID) */
11924                G.dead_job_exitcode = -1;
11925                return wait_for_child_or_signal(NULL, -1 /*no job, wait for one job*/);
11926        }
11927# endif
11928        if (argv[0] == NULL) {
11929                /* Don't care about wait results */
11930                /* Note 1: must wait until there are no more children */
11931                /* Note 2: must be interruptible */
11932                /* Examples:
11933                 * $ sleep 3 & sleep 6 & wait
11934                 * [1] 30934 sleep 3
11935                 * [2] 30935 sleep 6
11936                 * [1] Done                   sleep 3
11937                 * [2] Done                   sleep 6
11938                 * $ sleep 3 & sleep 6 & wait
11939                 * [1] 30936 sleep 3
11940                 * [2] 30937 sleep 6
11941                 * [1] Done                   sleep 3
11942                 * ^C <-- after ~4 sec from keyboard
11943                 * $
11944                 */
11945                return wait_for_child_or_signal(NULL, 0 /*no job and no pid to wait for*/);
11946        }
11947
11948        do {
11949                pid_t pid = bb_strtou(*argv, NULL, 10);
11950                if (errno || pid <= 0) {
11951# if ENABLE_HUSH_JOB
11952                        if (argv[0][0] == '%') {
11953                                struct pipe *wait_pipe;
11954                                ret = 127; /* bash compat for bad jobspecs */
11955                                wait_pipe = parse_jobspec(*argv);
11956                                if (wait_pipe) {
11957                                        ret = job_exited_or_stopped(wait_pipe);
11958                                        if (ret < 0) {
11959                                                ret = wait_for_child_or_signal(wait_pipe, 0);
11960                                        } else {
11961                                                /* waiting on "last dead job" removes it */
11962                                                clean_up_last_dead_job();
11963                                        }
11964                                }
11965                                /* else: parse_jobspec() already emitted error msg */
11966                                continue;
11967                        }
11968# endif
11969                        /* mimic bash message */
11970                        bb_error_msg("wait: '%s': not a pid or valid job spec", *argv);
11971                        ret = EXIT_FAILURE;
11972                        continue; /* bash checks all argv[] */
11973                }
11974
11975                /* Do we have such child? */
11976                ret = waitpid(pid, &status, WNOHANG);
11977                if (ret < 0) {
11978                        /* No */
11979                        ret = 127;
11980                        if (errno == ECHILD) {
11981                                if (pid == G.last_bg_pid) {
11982                                        /* "wait $!" but last bg task has already exited. Try:
11983                                         * (sleep 1; exit 3) & sleep 2; echo $?; wait $!; echo $?
11984                                         * In bash it prints exitcode 0, then 3.
11985                                         * In dash, it is 127.
11986                                         */
11987                                        ret = G.last_bg_pid_exitcode;
11988                                } else {
11989                                        /* Example: "wait 1". mimic bash message */
11990                                        bb_error_msg("wait: pid %u is not a child of this shell", (unsigned)pid);
11991                                }
11992                        } else {
11993                                /* ??? */
11994                                bb_perror_msg("wait %s", *argv);
11995                        }
11996                        continue; /* bash checks all argv[] */
11997                }
11998                if (ret == 0) {
11999                        /* Yes, and it still runs */
12000                        ret = wait_for_child_or_signal(NULL, pid);
12001                } else {
12002                        /* Yes, and it just exited */
12003                        process_wait_result(NULL, pid, status);
12004                        ret = WEXITSTATUS(status);
12005                        if (WIFSIGNALED(status))
12006                                ret = 128 | WTERMSIG(status);
12007                }
12008        } while (*++argv);
12009
12010        return ret;
12011}
12012#endif
12013
12014#if ENABLE_HUSH_LOOPS || ENABLE_HUSH_FUNCTIONS
12015static unsigned parse_numeric_argv1(char **argv, unsigned def, unsigned def_min)
12016{
12017        if (argv[1]) {
12018                def = bb_strtou(argv[1], NULL, 10);
12019                if (errno || def < def_min || argv[2]) {
12020                        bb_error_msg("%s: bad arguments", argv[0]);
12021                        def = UINT_MAX;
12022                }
12023        }
12024        return def;
12025}
12026#endif
12027
12028#if ENABLE_HUSH_LOOPS
12029static int FAST_FUNC builtin_break(char **argv)
12030{
12031        unsigned depth;
12032        if (G.depth_of_loop == 0) {
12033                bb_error_msg("%s: only meaningful in a loop", argv[0]);
12034                /* if we came from builtin_continue(), need to undo "= 1" */
12035                G.flag_break_continue = 0;
12036                return EXIT_SUCCESS; /* bash compat */
12037        }
12038        G.flag_break_continue++; /* BC_BREAK = 1, or BC_CONTINUE = 2 */
12039
12040        G.depth_break_continue = depth = parse_numeric_argv1(argv, 1, 1);
12041        if (depth == UINT_MAX)
12042                G.flag_break_continue = BC_BREAK;
12043        if (G.depth_of_loop < depth)
12044                G.depth_break_continue = G.depth_of_loop;
12045
12046        return EXIT_SUCCESS;
12047}
12048
12049static int FAST_FUNC builtin_continue(char **argv)
12050{
12051        G.flag_break_continue = 1; /* BC_CONTINUE = 2 = 1+1 */
12052        return builtin_break(argv);
12053}
12054#endif
12055
12056#if ENABLE_HUSH_FUNCTIONS
12057static int FAST_FUNC builtin_return(char **argv)
12058{
12059        int rc;
12060
12061        if (G_flag_return_in_progress != -1) {
12062                bb_error_msg("%s: not in a function or sourced script", argv[0]);
12063                return EXIT_FAILURE; /* bash compat */
12064        }
12065
12066        G_flag_return_in_progress = 1;
12067
12068        /* bash:
12069         * out of range: wraps around at 256, does not error out
12070         * non-numeric param:
12071         * f() { false; return qwe; }; f; echo $?
12072         * bash: return: qwe: numeric argument required  <== we do this
12073         * 255  <== we also do this
12074         */
12075        rc = parse_numeric_argv1(argv, G.last_exitcode, 0);
12076# if ENABLE_HUSH_TRAP
12077        if (argv[1]) { /* "return ARG" inside a running trap sets $? */
12078                debug_printf_exec("G.return_exitcode=%d\n", rc);
12079                G.return_exitcode = rc;
12080        }
12081# endif
12082        return rc;
12083}
12084#endif
12085
12086#if ENABLE_HUSH_TIMES
12087static int FAST_FUNC builtin_times(char **argv UNUSED_PARAM)
12088{
12089        static const uint8_t times_tbl[] ALIGN1 = {
12090                ' ',  offsetof(struct tms, tms_utime),
12091                '\n', offsetof(struct tms, tms_stime),
12092                ' ',  offsetof(struct tms, tms_cutime),
12093                '\n', offsetof(struct tms, tms_cstime),
12094                0
12095        };
12096        const uint8_t *p;
12097        unsigned clk_tck;
12098        struct tms buf;
12099
12100        clk_tck = bb_clk_tck();
12101
12102        times(&buf);
12103        p = times_tbl;
12104        do {
12105                unsigned sec, frac;
12106                unsigned long t;
12107                t = *(clock_t *)(((char *) &buf) + p[1]);
12108                sec = t / clk_tck;
12109                frac = t % clk_tck;
12110                printf("%um%u.%03us%c",
12111                        sec / 60, sec % 60,
12112                        (frac * 1000) / clk_tck,
12113                        p[0]);
12114                p += 2;
12115        } while (*p);
12116
12117        return EXIT_SUCCESS;
12118}
12119#endif
12120
12121#if ENABLE_HUSH_MEMLEAK
12122static int FAST_FUNC builtin_memleak(char **argv UNUSED_PARAM)
12123{
12124        void *p;
12125        unsigned long l;
12126
12127# ifdef M_TRIM_THRESHOLD
12128        /* Optional. Reduces probability of false positives */
12129        malloc_trim(0);
12130# endif
12131        /* Crude attempt to find where "free memory" starts,
12132         * sans fragmentation. */
12133        p = malloc(240);
12134        l = (unsigned long)p;
12135        free(p);
12136        p = malloc(3400);
12137        if (l < (unsigned long)p) l = (unsigned long)p;
12138        free(p);
12139
12140
12141# if 0  /* debug */
12142        {
12143                struct mallinfo mi = mallinfo();
12144                printf("top alloc:0x%lx malloced:%d+%d=%d\n", l,
12145                        mi.arena, mi.hblkhd, mi.arena + mi.hblkhd);
12146        }
12147# endif
12148
12149        if (!G.memleak_value)
12150                G.memleak_value = l;
12151
12152        l -= G.memleak_value;
12153        if ((long)l < 0)
12154                l = 0;
12155        l /= 1024;
12156        if (l > 127)
12157                l = 127;
12158
12159        /* Exitcode is "how many kilobytes we leaked since 1st call" */
12160        return l;
12161}
12162#endif
12163