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_SHELL_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#if ENABLE_HUSH_LINENO_VAR
2757                        if (ch == '\n') {
2758                                G.parse_lineno++;
2759                                debug_printf_parse("G.parse_lineno++ = %u\n", G.parse_lineno);
2760                        }
2761#endif
2762                        return ch;
2763                }
2764                return EOF;
2765        }
2766
2767        /* FILE-based in_str */
2768
2769#if ENABLE_FEATURE_EDITING
2770        /* This can be stdin, check line editing char[] buffer */
2771        if (i->p && *i->p != '\0') {
2772                ch = (unsigned char)*i->p++;
2773                goto out;
2774        }
2775#endif
2776        /* peek_buf[] is an int array, not char. Can contain EOF. */
2777        ch = i->peek_buf[0];
2778        if (ch != 0) {
2779                int ch2 = i->peek_buf[1];
2780                i->peek_buf[0] = ch2;
2781                if (ch2 == 0) /* very likely, avoid redundant write */
2782                        goto out;
2783                i->peek_buf[1] = 0;
2784                goto out;
2785        }
2786
2787        ch = fgetc_interactive(i);
2788 out:
2789        debug_printf("file_get: got '%c' %d\n", ch, ch);
2790        i->last_char = ch;
2791#if ENABLE_HUSH_LINENO_VAR
2792        if (ch == '\n') {
2793                G.parse_lineno++;
2794                debug_printf_parse("G.parse_lineno++ = %u\n", G.parse_lineno);
2795        }
2796#endif
2797        return ch;
2798}
2799
2800static int i_peek(struct in_str *i)
2801{
2802        int ch;
2803
2804        if (!i->file) {
2805                /* string-based in_str */
2806                /* Doesn't report EOF on NUL. None of the callers care. */
2807                return (unsigned char)*i->p;
2808        }
2809
2810        /* FILE-based in_str */
2811
2812#if ENABLE_FEATURE_EDITING && ENABLE_HUSH_INTERACTIVE
2813        /* This can be stdin, check line editing char[] buffer */
2814        if (i->p && *i->p != '\0')
2815                return (unsigned char)*i->p;
2816#endif
2817        /* peek_buf[] is an int array, not char. Can contain EOF. */
2818        ch = i->peek_buf[0];
2819        if (ch != 0)
2820                return ch;
2821
2822        /* Need to get a new char */
2823        ch = fgetc_interactive(i);
2824        debug_printf("file_peek: got '%c' %d\n", ch, ch);
2825
2826        /* Save it by either rolling back line editing buffer, or in i->peek_buf[0] */
2827#if ENABLE_FEATURE_EDITING && ENABLE_HUSH_INTERACTIVE
2828        if (i->p) {
2829                i->p -= 1;
2830                return ch;
2831        }
2832#endif
2833        i->peek_buf[0] = ch;
2834        /*i->peek_buf[1] = 0; - already is */
2835        return ch;
2836}
2837
2838/* Only ever called if i_peek() was called, and did not return EOF.
2839 * IOW: we know the previous peek saw an ordinary char, not EOF, not NUL,
2840 * not end-of-line. Therefore we never need to read a new editing line here.
2841 */
2842static int i_peek2(struct in_str *i)
2843{
2844        int ch;
2845
2846        /* There are two cases when i->p[] buffer exists.
2847         * (1) it's a string in_str.
2848         * (2) It's a file, and we have a saved line editing buffer.
2849         * In both cases, we know that i->p[0] exists and not NUL, and
2850         * the peek2 result is in i->p[1].
2851         */
2852        if (i->p)
2853                return (unsigned char)i->p[1];
2854
2855        /* Now we know it is a file-based in_str. */
2856
2857        /* peek_buf[] is an int array, not char. Can contain EOF. */
2858        /* Is there 2nd char? */
2859        ch = i->peek_buf[1];
2860        if (ch == 0) {
2861                /* We did not read it yet, get it now */
2862                do ch = hfgetc(i->file); while (ch == '\0');
2863                i->peek_buf[1] = ch;
2864        }
2865
2866        debug_printf("file_peek2: got '%c' %d\n", ch, ch);
2867        return ch;
2868}
2869
2870static int i_getch_and_eat_bkslash_nl(struct in_str *input)
2871{
2872        for (;;) {
2873                int ch, ch2;
2874
2875                ch = i_getch(input);
2876                if (ch != '\\')
2877                        return ch;
2878                ch2 = i_peek(input);
2879                if (ch2 != '\n')
2880                        return ch;
2881                /* backslash+newline, skip it */
2882                i_getch(input);
2883        }
2884}
2885
2886/* Note: this function _eats_ \<newline> pairs, safe to use plain
2887 * i_getch() after it instead of i_getch_and_eat_bkslash_nl().
2888 */
2889static int i_peek_and_eat_bkslash_nl(struct in_str *input)
2890{
2891        for (;;) {
2892                int ch, ch2;
2893
2894                ch = i_peek(input);
2895                if (ch != '\\')
2896                        return ch;
2897                ch2 = i_peek2(input);
2898                if (ch2 != '\n')
2899                        return ch;
2900                /* backslash+newline, skip it */
2901                i_getch(input);
2902                i_getch(input);
2903        }
2904}
2905
2906static void setup_file_in_str(struct in_str *i, HFILE *fp)
2907{
2908        memset(i, 0, sizeof(*i));
2909        i->file = fp;
2910        /* i->p = NULL; */
2911}
2912
2913static void setup_string_in_str(struct in_str *i, const char *s)
2914{
2915        memset(i, 0, sizeof(*i));
2916        /*i->file = NULL */;
2917        i->p = s;
2918}
2919
2920
2921/*
2922 * o_string support
2923 */
2924#define B_CHUNK  (32 * sizeof(char*))
2925
2926static void o_reset_to_empty_unquoted(o_string *o)
2927{
2928        o->length = 0;
2929        o->has_quoted_part = 0;
2930        if (o->data)
2931                o->data[0] = '\0';
2932}
2933
2934static void o_free_and_set_NULL(o_string *o)
2935{
2936        free(o->data);
2937        memset(o, 0, sizeof(*o));
2938}
2939
2940static ALWAYS_INLINE void o_free(o_string *o)
2941{
2942        free(o->data);
2943}
2944
2945static void o_grow_by(o_string *o, int len)
2946{
2947        if (o->length + len > o->maxlen) {
2948                o->maxlen += (2 * len) | (B_CHUNK-1);
2949                o->data = xrealloc(o->data, 1 + o->maxlen);
2950        }
2951}
2952
2953static void o_addchr(o_string *o, int ch)
2954{
2955        debug_printf("o_addchr: '%c' o->length=%d o=%p\n", ch, o->length, o);
2956        if (o->length < o->maxlen) {
2957                /* likely. avoid o_grow_by() call */
2958 add:
2959                o->data[o->length] = ch;
2960                o->length++;
2961                o->data[o->length] = '\0';
2962                return;
2963        }
2964        o_grow_by(o, 1);
2965        goto add;
2966}
2967
2968#if 0
2969/* Valid only if we know o_string is not empty */
2970static void o_delchr(o_string *o)
2971{
2972        o->length--;
2973        o->data[o->length] = '\0';
2974}
2975#endif
2976
2977static void o_addblock(o_string *o, const char *str, int len)
2978{
2979        o_grow_by(o, len);
2980        ((char*)mempcpy(&o->data[o->length], str, len))[0] = '\0';
2981        o->length += len;
2982}
2983
2984static void o_addstr(o_string *o, const char *str)
2985{
2986        o_addblock(o, str, strlen(str));
2987}
2988
2989static void o_addstr_with_NUL(o_string *o, const char *str)
2990{
2991        o_addblock(o, str, strlen(str) + 1);
2992}
2993
2994#if !BB_MMU
2995static void nommu_addchr(o_string *o, int ch)
2996{
2997        if (o)
2998                o_addchr(o, ch);
2999}
3000#else
3001# define nommu_addchr(o, str) ((void)0)
3002#endif
3003
3004#if ENABLE_HUSH_MODE_X
3005static void x_mode_addchr(int ch)
3006{
3007        o_addchr(&G.x_mode_buf, ch);
3008}
3009static void x_mode_addstr(const char *str)
3010{
3011        o_addstr(&G.x_mode_buf, str);
3012}
3013static void x_mode_addblock(const char *str, int len)
3014{
3015        o_addblock(&G.x_mode_buf, str, len);
3016}
3017static void x_mode_prefix(void)
3018{
3019        int n = G.x_mode_depth;
3020        do x_mode_addchr('+'); while (--n >= 0);
3021}
3022static void x_mode_flush(void)
3023{
3024        int len = G.x_mode_buf.length;
3025        if (len <= 0)
3026                return;
3027        if (G.x_mode_fd > 0) {
3028                G.x_mode_buf.data[len] = '\n';
3029                full_write(G.x_mode_fd, G.x_mode_buf.data, len + 1);
3030        }
3031        G.x_mode_buf.length = 0;
3032}
3033#endif
3034
3035/*
3036 * HUSH_BRACE_EXPANSION code needs corresponding quoting on variable expansion side.
3037 * Currently, "v='{q,w}'; echo $v" erroneously expands braces in $v.
3038 * Apparently, on unquoted $v bash still does globbing
3039 * ("v='*.txt'; echo $v" prints all .txt files),
3040 * but NOT brace expansion! Thus, there should be TWO independent
3041 * quoting mechanisms on $v expansion side: one protects
3042 * $v from brace expansion, and other additionally protects "$v" against globbing.
3043 * We have only second one.
3044 */
3045
3046#if ENABLE_HUSH_BRACE_EXPANSION
3047# define MAYBE_BRACES "{}"
3048#else
3049# define MAYBE_BRACES ""
3050#endif
3051
3052/* My analysis of quoting semantics tells me that state information
3053 * is associated with a destination, not a source.
3054 */
3055static void o_addqchr(o_string *o, int ch)
3056{
3057        int sz = 1;
3058        /* '-' is included because of this case:
3059         * >filename0 >filename1 >filename9; v='-'; echo filename[0"$v"9]
3060         */
3061        char *found = strchr("*?[-\\" MAYBE_BRACES, ch);
3062        if (found)
3063                sz++;
3064        o_grow_by(o, sz);
3065        if (found) {
3066                o->data[o->length] = '\\';
3067                o->length++;
3068        }
3069        o->data[o->length] = ch;
3070        o->length++;
3071        o->data[o->length] = '\0';
3072}
3073
3074static void o_addQchr(o_string *o, int ch)
3075{
3076        int sz = 1;
3077        if ((o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)
3078         && strchr("*?[-\\" MAYBE_BRACES, ch)
3079        ) {
3080                sz++;
3081                o->data[o->length] = '\\';
3082                o->length++;
3083        }
3084        o_grow_by(o, sz);
3085        o->data[o->length] = ch;
3086        o->length++;
3087        o->data[o->length] = '\0';
3088}
3089
3090static void o_addqblock(o_string *o, const char *str, int len)
3091{
3092        while (len) {
3093                char ch;
3094                int sz;
3095                int ordinary_cnt = strcspn(str, "*?[-\\" MAYBE_BRACES);
3096                if (ordinary_cnt > len) /* paranoia */
3097                        ordinary_cnt = len;
3098                o_addblock(o, str, ordinary_cnt);
3099                if (ordinary_cnt == len)
3100                        return; /* NUL is already added by o_addblock */
3101                str += ordinary_cnt;
3102                len -= ordinary_cnt + 1; /* we are processing + 1 char below */
3103
3104                ch = *str++;
3105                sz = 1;
3106                if (ch) { /* it is necessarily one of "*?[-\\" MAYBE_BRACES */
3107                        sz++;
3108                        o->data[o->length] = '\\';
3109                        o->length++;
3110                }
3111                o_grow_by(o, sz);
3112                o->data[o->length] = ch;
3113                o->length++;
3114        }
3115        o->data[o->length] = '\0';
3116}
3117
3118static void o_addQblock(o_string *o, const char *str, int len)
3119{
3120        if (!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)) {
3121                o_addblock(o, str, len);
3122                return;
3123        }
3124        o_addqblock(o, str, len);
3125}
3126
3127static void o_addQstr(o_string *o, const char *str)
3128{
3129        o_addQblock(o, str, strlen(str));
3130}
3131
3132/* A special kind of o_string for $VAR and `cmd` expansion.
3133 * It contains char* list[] at the beginning, which is grown in 16 element
3134 * increments. Actual string data starts at the next multiple of 16 * (char*).
3135 * list[i] contains an INDEX (int!) into this string data.
3136 * It means that if list[] needs to grow, data needs to be moved higher up
3137 * but list[i]'s need not be modified.
3138 * NB: remembering how many list[i]'s you have there is crucial.
3139 * o_finalize_list() operation post-processes this structure - calculates
3140 * and stores actual char* ptrs in list[]. Oh, it NULL terminates it as well.
3141 */
3142#if DEBUG_EXPAND || DEBUG_GLOB
3143static void debug_print_list(const char *prefix, o_string *o, int n)
3144{
3145        char **list = (char**)o->data;
3146        int string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
3147        int i = 0;
3148
3149        indent();
3150        fdprintf(2, "%s: list:%p n:%d string_start:%d length:%d maxlen:%d glob:%d quoted:%d escape:%d\n",
3151                        prefix, list, n, string_start, o->length, o->maxlen,
3152                        !!(o->o_expflags & EXP_FLAG_GLOB),
3153                        o->has_quoted_part,
3154                        !!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
3155        while (i < n) {
3156                indent();
3157                fdprintf(2, " list[%d]=%d '%s' %p\n", i, (int)(uintptr_t)list[i],
3158                                o->data + (int)(uintptr_t)list[i] + string_start,
3159                                o->data + (int)(uintptr_t)list[i] + string_start);
3160                i++;
3161        }
3162        if (n) {
3163                const char *p = o->data + (int)(uintptr_t)list[n - 1] + string_start;
3164                indent();
3165                fdprintf(2, " total_sz:%ld\n", (long)((p + strlen(p) + 1) - o->data));
3166        }
3167}
3168#else
3169# define debug_print_list(prefix, o, n) ((void)0)
3170#endif
3171
3172/* n = o_save_ptr_helper(str, n) "starts new string" by storing an index value
3173 * in list[n] so that it points past last stored byte so far.
3174 * It returns n+1. */
3175static int o_save_ptr_helper(o_string *o, int n)
3176{
3177        char **list = (char**)o->data;
3178        int string_start;
3179        int string_len;
3180
3181        if (!o->has_empty_slot) {
3182                string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
3183                string_len = o->length - string_start;
3184                if (!(n & 0xf)) { /* 0, 0x10, 0x20...? */
3185                        debug_printf_list("list[%d]=%d string_start=%d (growing)\n", n, string_len, string_start);
3186                        /* list[n] points to string_start, make space for 16 more pointers */
3187                        o->maxlen += 0x10 * sizeof(list[0]);
3188                        o->data = xrealloc(o->data, o->maxlen + 1);
3189                        list = (char**)o->data;
3190                        memmove(list + n + 0x10, list + n, string_len);
3191                        /*
3192                         * expand_on_ifs() has a "previous argv[] ends in IFS?"
3193                         * check. (grep for -prev-ifs-check-).
3194                         * Ensure that argv[-1][last] is not garbage
3195                         * but zero bytes, to save index check there.
3196                         */
3197                        list[n + 0x10 - 1] = 0;
3198                        o->length += 0x10 * sizeof(list[0]);
3199                } else {
3200                        debug_printf_list("list[%d]=%d string_start=%d\n",
3201                                        n, string_len, string_start);
3202                }
3203        } else {
3204                /* We have empty slot at list[n], reuse without growth */
3205                string_start = ((n+1 + 0xf) & ~0xf) * sizeof(list[0]); /* NB: n+1! */
3206                string_len = o->length - string_start;
3207                debug_printf_list("list[%d]=%d string_start=%d (empty slot)\n",
3208                                n, string_len, string_start);
3209                o->has_empty_slot = 0;
3210        }
3211        o->has_quoted_part = 0;
3212        list[n] = (char*)(uintptr_t)string_len;
3213        return n + 1;
3214}
3215
3216/* "What was our last o_save_ptr'ed position (byte offset relative o->data)?" */
3217static int o_get_last_ptr(o_string *o, int n)
3218{
3219        char **list = (char**)o->data;
3220        int string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
3221
3222        return ((int)(uintptr_t)list[n-1]) + string_start;
3223}
3224
3225/*
3226 * Globbing routines.
3227 *
3228 * Most words in commands need to be globbed, even ones which are
3229 * (single or double) quoted. This stems from the possiblity of
3230 * constructs like "abc"* and 'abc'* - these should be globbed.
3231 * Having a different code path for fully-quoted strings ("abc",
3232 * 'abc') would only help performance-wise, but we still need
3233 * code for partially-quoted strings.
3234 *
3235 * Unfortunately, if we want to match bash and ash behavior in all cases,
3236 * the logic can't be "shell-syntax argument is first transformed
3237 * to a string, then globbed, and if globbing does not match anything,
3238 * it is used verbatim". Here are two examples where it fails:
3239 *
3240 *      echo 'b\*'?
3241 *
3242 * The globbing can't be avoided (because of '?' at the end).
3243 * The glob pattern is: b\\\*? - IOW, both \ and * are literals
3244 * and are glob-escaped. If this does not match, bash/ash print b\*?
3245 * - IOW: they "unbackslash" the glob pattern.
3246 * Now, look at this:
3247 *
3248 *      v='\\\*'; echo b$v?
3249 *
3250 * The glob pattern is the same here: b\\\*? - the unquoted $v expansion
3251 * should be used as glob pattern with no changes. However, if glob
3252 * does not match, bash/ash print b\\\*? - NOT THE SAME as first example!
3253 *
3254 * ash implements this by having an encoded representation of the word
3255 * to glob, which IS NOT THE SAME as the glob pattern - it has more data.
3256 * Glob pattern is derived from it. If glob fails, the decision what result
3257 * should be is made using that encoded representation. Not glob pattern.
3258 */
3259
3260#if ENABLE_HUSH_BRACE_EXPANSION
3261/* There in a GNU extension, GLOB_BRACE, but it is not usable:
3262 * first, it processes even {a} (no commas), second,
3263 * I didn't manage to make it return strings when they don't match
3264 * existing files. Need to re-implement it.
3265 */
3266
3267/* Helper */
3268static int glob_needed(const char *s)
3269{
3270        while (*s) {
3271                if (*s == '\\') {
3272                        if (!s[1])
3273                                return 0;
3274                        s += 2;
3275                        continue;
3276                }
3277                if (*s == '*' || *s == '[' || *s == '?' || *s == '{')
3278                        return 1;
3279                s++;
3280        }
3281        return 0;
3282}
3283/* Return pointer to next closing brace or to comma */
3284static const char *next_brace_sub(const char *cp)
3285{
3286        unsigned depth = 0;
3287        cp++;
3288        while (*cp != '\0') {
3289                if (*cp == '\\') {
3290                        if (*++cp == '\0')
3291                                break;
3292                        cp++;
3293                        continue;
3294                }
3295                if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0))
3296                        break;
3297                if (*cp++ == '{')
3298                        depth++;
3299        }
3300
3301        return *cp != '\0' ? cp : NULL;
3302}
3303/* Recursive brace globber. Note: may garble pattern[]. */
3304static int glob_brace(char *pattern, o_string *o, int n)
3305{
3306        char *new_pattern_buf;
3307        const char *begin;
3308        const char *next;
3309        const char *rest;
3310        const char *p;
3311        size_t rest_len;
3312
3313        debug_printf_glob("glob_brace('%s')\n", pattern);
3314
3315        begin = pattern;
3316        while (1) {
3317                if (*begin == '\0')
3318                        goto simple_glob;
3319                if (*begin == '{') {
3320                        /* Find the first sub-pattern and at the same time
3321                         * find the rest after the closing brace */
3322                        next = next_brace_sub(begin);
3323                        if (next == NULL) {
3324                                /* An illegal expression */
3325                                goto simple_glob;
3326                        }
3327                        if (*next == '}') {
3328                                /* "{abc}" with no commas - illegal
3329                                 * brace expr, disregard and skip it */
3330                                begin = next + 1;
3331                                continue;
3332                        }
3333                        break;
3334                }
3335                if (*begin == '\\' && begin[1] != '\0')
3336                        begin++;
3337                begin++;
3338        }
3339        debug_printf_glob("begin:%s\n", begin);
3340        debug_printf_glob("next:%s\n", next);
3341
3342        /* Now find the end of the whole brace expression */
3343        rest = next;
3344        while (*rest != '}') {
3345                rest = next_brace_sub(rest);
3346                if (rest == NULL) {
3347                        /* An illegal expression */
3348                        goto simple_glob;
3349                }
3350                debug_printf_glob("rest:%s\n", rest);
3351        }
3352        rest_len = strlen(++rest) + 1;
3353
3354        /* We are sure the brace expression is well-formed */
3355
3356        /* Allocate working buffer large enough for our work */
3357        new_pattern_buf = xmalloc(strlen(pattern));
3358
3359        /* We have a brace expression.  BEGIN points to the opening {,
3360         * NEXT points past the terminator of the first element, and REST
3361         * points past the final }.  We will accumulate result names from
3362         * recursive runs for each brace alternative in the buffer using
3363         * GLOB_APPEND. */
3364
3365        p = begin + 1;
3366        while (1) {
3367                /* Construct the new glob expression */
3368                memcpy(
3369                        mempcpy(
3370                                mempcpy(new_pattern_buf,
3371                                        /* We know the prefix for all sub-patterns */
3372                                        pattern, begin - pattern),
3373                                p, next - p),
3374                        rest, rest_len);
3375
3376                /* Note: glob_brace() may garble new_pattern_buf[].
3377                 * That's why we re-copy prefix every time (1st memcpy above).
3378                 */
3379                n = glob_brace(new_pattern_buf, o, n);
3380                if (*next == '}') {
3381                        /* We saw the last entry */
3382                        break;
3383                }
3384                p = next + 1;
3385                next = next_brace_sub(next);
3386        }
3387        free(new_pattern_buf);
3388        return n;
3389
3390 simple_glob:
3391        {
3392                int gr;
3393                glob_t globdata;
3394
3395                memset(&globdata, 0, sizeof(globdata));
3396                gr = glob(pattern, 0, NULL, &globdata);
3397                debug_printf_glob("glob('%s'):%d\n", pattern, gr);
3398                if (gr != 0) {
3399                        if (gr == GLOB_NOMATCH) {
3400                                globfree(&globdata);
3401                                /* NB: garbles parameter */
3402                                unbackslash(pattern);
3403                                o_addstr_with_NUL(o, pattern);
3404                                debug_printf_glob("glob pattern '%s' is literal\n", pattern);
3405                                return o_save_ptr_helper(o, n);
3406                        }
3407                        if (gr == GLOB_NOSPACE)
3408                                bb_die_memory_exhausted();
3409                        /* GLOB_ABORTED? Only happens with GLOB_ERR flag,
3410                         * but we didn't specify it. Paranoia again. */
3411                        bb_error_msg_and_die("glob error %d on '%s'", gr, pattern);
3412                }
3413                if (globdata.gl_pathv && globdata.gl_pathv[0]) {
3414                        char **argv = globdata.gl_pathv;
3415                        while (1) {
3416                                o_addstr_with_NUL(o, *argv);
3417                                n = o_save_ptr_helper(o, n);
3418                                argv++;
3419                                if (!*argv)
3420                                        break;
3421                        }
3422                }
3423                globfree(&globdata);
3424        }
3425        return n;
3426}
3427/* Performs globbing on last list[],
3428 * saving each result as a new list[].
3429 */
3430static int perform_glob(o_string *o, int n)
3431{
3432        char *pattern, *copy;
3433
3434        debug_printf_glob("start perform_glob: n:%d o->data:%p\n", n, o->data);
3435        if (!o->data)
3436                return o_save_ptr_helper(o, n);
3437        pattern = o->data + o_get_last_ptr(o, n);
3438        debug_printf_glob("glob pattern '%s'\n", pattern);
3439        if (!glob_needed(pattern)) {
3440                /* unbackslash last string in o in place, fix length */
3441                o->length = unbackslash(pattern) - o->data;
3442                debug_printf_glob("glob pattern '%s' is literal\n", pattern);
3443                return o_save_ptr_helper(o, n);
3444        }
3445
3446        copy = xstrdup(pattern);
3447        /* "forget" pattern in o */
3448        o->length = pattern - o->data;
3449        n = glob_brace(copy, o, n);
3450        free(copy);
3451        if (DEBUG_GLOB)
3452                debug_print_list("perform_glob returning", o, n);
3453        return n;
3454}
3455
3456#else /* !HUSH_BRACE_EXPANSION */
3457
3458/* Helper */
3459static int glob_needed(const char *s)
3460{
3461        while (*s) {
3462                if (*s == '\\') {
3463                        if (!s[1])
3464                                return 0;
3465                        s += 2;
3466                        continue;
3467                }
3468                if (*s == '*' || *s == '[' || *s == '?')
3469                        return 1;
3470                s++;
3471        }
3472        return 0;
3473}
3474/* Performs globbing on last list[],
3475 * saving each result as a new list[].
3476 */
3477static int perform_glob(o_string *o, int n)
3478{
3479        glob_t globdata;
3480        int gr;
3481        char *pattern;
3482
3483        debug_printf_glob("start perform_glob: n:%d o->data:%p\n", n, o->data);
3484        if (!o->data)
3485                return o_save_ptr_helper(o, n);
3486        pattern = o->data + o_get_last_ptr(o, n);
3487        debug_printf_glob("glob pattern '%s'\n", pattern);
3488        if (!glob_needed(pattern)) {
3489 literal:
3490                /* unbackslash last string in o in place, fix length */
3491                o->length = unbackslash(pattern) - o->data;
3492                debug_printf_glob("glob pattern '%s' is literal\n", pattern);
3493                return o_save_ptr_helper(o, n);
3494        }
3495
3496        memset(&globdata, 0, sizeof(globdata));
3497        /* Can't use GLOB_NOCHECK: it does not unescape the string.
3498         * If we glob "*.\*" and don't find anything, we need
3499         * to fall back to using literal "*.*", but GLOB_NOCHECK
3500         * will return "*.\*"!
3501         */
3502        gr = glob(pattern, 0, NULL, &globdata);
3503        debug_printf_glob("glob('%s'):%d\n", pattern, gr);
3504        if (gr != 0) {
3505                if (gr == GLOB_NOMATCH) {
3506                        globfree(&globdata);
3507                        goto literal;
3508                }
3509                if (gr == GLOB_NOSPACE)
3510                        bb_die_memory_exhausted();
3511                /* GLOB_ABORTED? Only happens with GLOB_ERR flag,
3512                 * but we didn't specify it. Paranoia again. */
3513                bb_error_msg_and_die("glob error %d on '%s'", gr, pattern);
3514        }
3515        if (globdata.gl_pathv && globdata.gl_pathv[0]) {
3516                char **argv = globdata.gl_pathv;
3517                /* "forget" pattern in o */
3518                o->length = pattern - o->data;
3519                while (1) {
3520                        o_addstr_with_NUL(o, *argv);
3521                        n = o_save_ptr_helper(o, n);
3522                        argv++;
3523                        if (!*argv)
3524                                break;
3525                }
3526        }
3527        globfree(&globdata);
3528        if (DEBUG_GLOB)
3529                debug_print_list("perform_glob returning", o, n);
3530        return n;
3531}
3532
3533#endif /* !HUSH_BRACE_EXPANSION */
3534
3535/* If o->o_expflags & EXP_FLAG_GLOB, glob the string so far remembered.
3536 * Otherwise, just finish current list[] and start new */
3537static int o_save_ptr(o_string *o, int n)
3538{
3539        if (o->o_expflags & EXP_FLAG_GLOB) {
3540                /* If o->has_empty_slot, list[n] was already globbed
3541                 * (if it was requested back then when it was filled)
3542                 * so don't do that again! */
3543                if (!o->has_empty_slot)
3544                        return perform_glob(o, n); /* o_save_ptr_helper is inside */
3545        }
3546        return o_save_ptr_helper(o, n);
3547}
3548
3549/* "Please convert list[n] to real char* ptrs, and NULL terminate it." */
3550static char **o_finalize_list(o_string *o, int n)
3551{
3552        char **list;
3553        int string_start;
3554
3555        if (DEBUG_EXPAND)
3556                debug_print_list("finalized", o, n);
3557        debug_printf_expand("finalized n:%d\n", n);
3558        list = (char**)o->data;
3559        string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
3560        list[--n] = NULL;
3561        while (n) {
3562                n--;
3563                list[n] = o->data + (int)(uintptr_t)list[n] + string_start;
3564        }
3565        return list;
3566}
3567
3568static void free_pipe_list(struct pipe *pi);
3569
3570/* Returns pi->next - next pipe in the list */
3571static struct pipe *free_pipe(struct pipe *pi)
3572{
3573        struct pipe *next;
3574        int i;
3575
3576        debug_printf_clean("free_pipe (pid %d)\n", getpid());
3577        for (i = 0; i < pi->num_cmds; i++) {
3578                struct command *command;
3579                struct redir_struct *r, *rnext;
3580
3581                command = &pi->cmds[i];
3582                debug_printf_clean("  command %d:\n", i);
3583                if (command->argv) {
3584                        if (DEBUG_CLEAN) {
3585                                int a;
3586                                char **p;
3587                                for (a = 0, p = command->argv; *p; a++, p++) {
3588                                        debug_printf_clean("   argv[%d] = %s\n", a, *p);
3589                                }
3590                        }
3591                        free_strings(command->argv);
3592                        //command->argv = NULL;
3593                }
3594                /* not "else if": on syntax error, we may have both! */
3595                if (command->group) {
3596                        debug_printf_clean("   begin group (cmd_type:%d)\n",
3597                                        command->cmd_type);
3598                        free_pipe_list(command->group);
3599                        debug_printf_clean("   end group\n");
3600                        //command->group = NULL;
3601                }
3602                /* else is crucial here.
3603                 * If group != NULL, child_func is meaningless */
3604#if ENABLE_HUSH_FUNCTIONS
3605                else if (command->child_func) {
3606                        debug_printf_exec("cmd %p releases child func at %p\n", command, command->child_func);
3607                        command->child_func->parent_cmd = NULL;
3608                }
3609#endif
3610#if !BB_MMU
3611                free(command->group_as_string);
3612                //command->group_as_string = NULL;
3613#endif
3614                for (r = command->redirects; r; r = rnext) {
3615                        debug_printf_clean("   redirect %d%s",
3616                                        r->rd_fd, redir_table[r->rd_type].descrip);
3617                        /* guard against the case >$FOO, where foo is unset or blank */
3618                        if (r->rd_filename) {
3619                                debug_printf_clean(" fname:'%s'\n", r->rd_filename);
3620                                free(r->rd_filename);
3621                                //r->rd_filename = NULL;
3622                        }
3623                        debug_printf_clean(" rd_dup:%d\n", r->rd_dup);
3624                        rnext = r->next;
3625                        free(r);
3626                }
3627                //command->redirects = NULL;
3628        }
3629        free(pi->cmds);   /* children are an array, they get freed all at once */
3630        //pi->cmds = NULL;
3631#if ENABLE_HUSH_JOB
3632        free(pi->cmdtext);
3633        //pi->cmdtext = NULL;
3634#endif
3635
3636        next = pi->next;
3637        free(pi);
3638        return next;
3639}
3640
3641static void free_pipe_list(struct pipe *pi)
3642{
3643        while (pi) {
3644#if HAS_KEYWORDS
3645                debug_printf_clean("pipe reserved word %d\n", pi->res_word);
3646#endif
3647                debug_printf_clean("pipe followup code %d\n", pi->followup);
3648                pi = free_pipe(pi);
3649        }
3650}
3651
3652
3653/*** Parsing routines ***/
3654
3655#ifndef debug_print_tree
3656static void debug_print_tree(struct pipe *pi, int lvl)
3657{
3658        static const char *const PIPE[] = {
3659                [PIPE_SEQ] = "SEQ",
3660                [PIPE_AND] = "AND",
3661                [PIPE_OR ] = "OR" ,
3662                [PIPE_BG ] = "BG" ,
3663        };
3664        static const char *RES[] = {
3665                [RES_NONE ] = "NONE" ,
3666# if ENABLE_HUSH_IF
3667                [RES_IF   ] = "IF"   ,
3668                [RES_THEN ] = "THEN" ,
3669                [RES_ELIF ] = "ELIF" ,
3670                [RES_ELSE ] = "ELSE" ,
3671                [RES_FI   ] = "FI"   ,
3672# endif
3673# if ENABLE_HUSH_LOOPS
3674                [RES_FOR  ] = "FOR"  ,
3675                [RES_WHILE] = "WHILE",
3676                [RES_UNTIL] = "UNTIL",
3677                [RES_DO   ] = "DO"   ,
3678                [RES_DONE ] = "DONE" ,
3679# endif
3680# if ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
3681                [RES_IN   ] = "IN"   ,
3682# endif
3683# if ENABLE_HUSH_CASE
3684                [RES_CASE ] = "CASE" ,
3685                [RES_CASE_IN ] = "CASE_IN" ,
3686                [RES_MATCH] = "MATCH",
3687                [RES_CASE_BODY] = "CASE_BODY",
3688                [RES_ESAC ] = "ESAC" ,
3689# endif
3690                [RES_XXXX ] = "XXXX" ,
3691                [RES_SNTX ] = "SNTX" ,
3692        };
3693        static const char *const CMDTYPE[] = {
3694                "{}",
3695                "()",
3696                "[noglob]",
3697# if ENABLE_HUSH_FUNCTIONS
3698                "func()",
3699# endif
3700        };
3701
3702        int pin, prn;
3703
3704        pin = 0;
3705        while (pi) {
3706                fdprintf(2, "%*spipe %d #cmds:%d %sres_word=%s followup=%d %s\n",
3707                                lvl*2, "",
3708                                pin,
3709                                pi->num_cmds,
3710                                (IF_HAS_KEYWORDS(pi->pi_inverted ? "! " :) ""),
3711                                RES[pi->res_word],
3712                                pi->followup, PIPE[pi->followup]
3713                );
3714                prn = 0;
3715                while (prn < pi->num_cmds) {
3716                        struct command *command = &pi->cmds[prn];
3717                        char **argv = command->argv;
3718
3719                        fdprintf(2, "%*s cmd %d assignment_cnt:%d",
3720                                        lvl*2, "", prn,
3721                                        command->assignment_cnt);
3722# if ENABLE_HUSH_LINENO_VAR
3723                        fdprintf(2, " LINENO:%u", command->lineno);
3724# endif
3725                        if (command->group) {
3726                                fdprintf(2, " group %s: (argv=%p)%s%s\n",
3727                                                CMDTYPE[command->cmd_type],
3728                                                argv
3729# if !BB_MMU
3730                                                , " group_as_string:", command->group_as_string
3731# else
3732                                                , "", ""
3733# endif
3734                                );
3735                                debug_print_tree(command->group, lvl+1);
3736                                prn++;
3737                                continue;
3738                        }
3739                        if (argv) while (*argv) {
3740                                fdprintf(2, " '%s'", *argv);
3741                                argv++;
3742                        }
3743                        if (command->redirects)
3744                                fdprintf(2, " {redir}");
3745                        fdprintf(2, "\n");
3746                        prn++;
3747                }
3748                pi = pi->next;
3749                pin++;
3750        }
3751}
3752#endif /* debug_print_tree */
3753
3754static struct pipe *new_pipe(void)
3755{
3756        struct pipe *pi;
3757        pi = xzalloc(sizeof(struct pipe));
3758        /*pi->res_word = RES_NONE; - RES_NONE is 0 anyway */
3759        return pi;
3760}
3761
3762/* Command (member of a pipe) is complete, or we start a new pipe
3763 * if ctx->command is NULL.
3764 * No errors possible here.
3765 */
3766static int done_command(struct parse_context *ctx)
3767{
3768        /* The command is really already in the pipe structure, so
3769         * advance the pipe counter and make a new, null command. */
3770        struct pipe *pi = ctx->pipe;
3771        struct command *command = ctx->command;
3772
3773#if 0   /* Instead we emit error message at run time */
3774        if (ctx->pending_redirect) {
3775                /* For example, "cmd >" (no filename to redirect to) */
3776                syntax_error("invalid redirect");
3777                ctx->pending_redirect = NULL;
3778        }
3779#endif
3780
3781        if (command) {
3782                if (IS_NULL_CMD(command)) {
3783                        debug_printf_parse("done_command: skipping null cmd, num_cmds=%d\n", pi->num_cmds);
3784                        goto clear_and_ret;
3785                }
3786                pi->num_cmds++;
3787                debug_printf_parse("done_command: ++num_cmds=%d\n", pi->num_cmds);
3788                //debug_print_tree(ctx->list_head, 20);
3789        } else {
3790                debug_printf_parse("done_command: initializing, num_cmds=%d\n", pi->num_cmds);
3791        }
3792
3793        /* Only real trickiness here is that the uncommitted
3794         * command structure is not counted in pi->num_cmds. */
3795        pi->cmds = xrealloc(pi->cmds, sizeof(*pi->cmds) * (pi->num_cmds+1));
3796        ctx->command = command = &pi->cmds[pi->num_cmds];
3797 clear_and_ret:
3798        memset(command, 0, sizeof(*command));
3799#if ENABLE_HUSH_LINENO_VAR
3800        command->lineno = G.parse_lineno;
3801        debug_printf_parse("command->lineno = G.parse_lineno (%u)\n", G.parse_lineno);
3802#endif
3803        return pi->num_cmds; /* used only for 0/nonzero check */
3804}
3805
3806static void done_pipe(struct parse_context *ctx, pipe_style type)
3807{
3808        int not_null;
3809
3810        debug_printf_parse("done_pipe entered, followup %d\n", type);
3811        /* Close previous command */
3812        not_null = done_command(ctx);
3813#if HAS_KEYWORDS
3814        ctx->pipe->pi_inverted = ctx->ctx_inverted;
3815        ctx->ctx_inverted = 0;
3816        ctx->pipe->res_word = ctx->ctx_res_w;
3817#endif
3818        if (type == PIPE_BG && ctx->list_head != ctx->pipe) {
3819                /* Necessary since && and || have precedence over &:
3820                 * "cmd1 && cmd2 &" must spawn both cmds, not only cmd2,
3821                 * in a backgrounded subshell.
3822                 */
3823                struct pipe *pi;
3824                struct command *command;
3825
3826                /* Is this actually this construct, all pipes end with && or ||? */
3827                pi = ctx->list_head;
3828                while (pi != ctx->pipe) {
3829                        if (pi->followup != PIPE_AND && pi->followup != PIPE_OR)
3830                                goto no_conv;
3831                        pi = pi->next;
3832                }
3833
3834                debug_printf_parse("BG with more than one pipe, converting to { p1 &&...pN; } &\n");
3835                pi->followup = PIPE_SEQ; /* close pN _not_ with "&"! */
3836                pi = xzalloc(sizeof(*pi));
3837                pi->followup = PIPE_BG;
3838                pi->num_cmds = 1;
3839                pi->cmds = xzalloc(sizeof(pi->cmds[0]));
3840                command = &pi->cmds[0];
3841                if (CMD_NORMAL != 0) /* "if xzalloc didn't do that already" */
3842                        command->cmd_type = CMD_NORMAL;
3843                command->group = ctx->list_head;
3844#if !BB_MMU
3845                command->group_as_string = xstrndup(
3846                            ctx->as_string.data,
3847                            ctx->as_string.length - 1 /* do not copy last char, "&" */
3848                );
3849#endif
3850                /* Replace all pipes in ctx with one newly created */
3851                ctx->list_head = ctx->pipe = pi;
3852                /* for cases like "cmd && &", do not be tricked by last command
3853                 * being null - the entire {...} & is NOT null! */
3854                not_null = 1;
3855        } else {
3856 no_conv:
3857                ctx->pipe->followup = type;
3858        }
3859
3860        /* Without this check, even just <enter> on command line generates
3861         * tree of three NOPs (!). Which is harmless but annoying.
3862         * IOW: it is safe to do it unconditionally. */
3863        if (not_null
3864#if ENABLE_HUSH_IF
3865         || ctx->ctx_res_w == RES_FI
3866#endif
3867#if ENABLE_HUSH_LOOPS
3868         || ctx->ctx_res_w == RES_DONE
3869         || ctx->ctx_res_w == RES_FOR
3870         || ctx->ctx_res_w == RES_IN
3871#endif
3872#if ENABLE_HUSH_CASE
3873         || ctx->ctx_res_w == RES_ESAC
3874#endif
3875        ) {
3876                struct pipe *new_p;
3877                debug_printf_parse("done_pipe: adding new pipe: "
3878                                "not_null:%d ctx->ctx_res_w:%d\n",
3879                                not_null, ctx->ctx_res_w);
3880                new_p = new_pipe();
3881                ctx->pipe->next = new_p;
3882                ctx->pipe = new_p;
3883                /* RES_THEN, RES_DO etc are "sticky" -
3884                 * they remain set for pipes inside if/while.
3885                 * This is used to control execution.
3886                 * RES_FOR and RES_IN are NOT sticky (needed to support
3887                 * cases where variable or value happens to match a keyword):
3888                 */
3889#if ENABLE_HUSH_LOOPS
3890                if (ctx->ctx_res_w == RES_FOR
3891                 || ctx->ctx_res_w == RES_IN)
3892                        ctx->ctx_res_w = RES_NONE;
3893#endif
3894#if ENABLE_HUSH_CASE
3895                if (ctx->ctx_res_w == RES_MATCH)
3896                        ctx->ctx_res_w = RES_CASE_BODY;
3897                if (ctx->ctx_res_w == RES_CASE)
3898                        ctx->ctx_res_w = RES_CASE_IN;
3899#endif
3900                ctx->command = NULL; /* trick done_command below */
3901                /* Create the memory for command, roughly:
3902                 * ctx->pipe->cmds = new struct command;
3903                 * ctx->command = &ctx->pipe->cmds[0];
3904                 */
3905                done_command(ctx);
3906                //debug_print_tree(ctx->list_head, 10);
3907        }
3908        debug_printf_parse("done_pipe return\n");
3909}
3910
3911static void initialize_context(struct parse_context *ctx)
3912{
3913        memset(ctx, 0, sizeof(*ctx));
3914        if (MAYBE_ASSIGNMENT != 0)
3915                ctx->is_assignment = MAYBE_ASSIGNMENT;
3916        ctx->pipe = ctx->list_head = new_pipe();
3917        /* Create the memory for command, roughly:
3918         * ctx->pipe->cmds = new struct command;
3919         * ctx->command = &ctx->pipe->cmds[0];
3920         */
3921        done_command(ctx);
3922}
3923
3924/* If a reserved word is found and processed, parse context is modified
3925 * and 1 is returned.
3926 */
3927#if HAS_KEYWORDS
3928struct reserved_combo {
3929        char literal[6];
3930        unsigned char res;
3931        unsigned char assignment_flag;
3932        uint32_t flag;
3933};
3934enum {
3935        FLAG_END   = (1 << RES_NONE ),
3936# if ENABLE_HUSH_IF
3937        FLAG_IF    = (1 << RES_IF   ),
3938        FLAG_THEN  = (1 << RES_THEN ),
3939        FLAG_ELIF  = (1 << RES_ELIF ),
3940        FLAG_ELSE  = (1 << RES_ELSE ),
3941        FLAG_FI    = (1 << RES_FI   ),
3942# endif
3943# if ENABLE_HUSH_LOOPS
3944        FLAG_FOR   = (1 << RES_FOR  ),
3945        FLAG_WHILE = (1 << RES_WHILE),
3946        FLAG_UNTIL = (1 << RES_UNTIL),
3947        FLAG_DO    = (1 << RES_DO   ),
3948        FLAG_DONE  = (1 << RES_DONE ),
3949        FLAG_IN    = (1 << RES_IN   ),
3950# endif
3951# if ENABLE_HUSH_CASE
3952        FLAG_MATCH = (1 << RES_MATCH),
3953        FLAG_ESAC  = (1 << RES_ESAC ),
3954# endif
3955        FLAG_START = (1 << RES_XXXX ),
3956};
3957
3958static const struct reserved_combo* match_reserved_word(o_string *word)
3959{
3960        /* Mostly a list of accepted follow-up reserved words.
3961         * FLAG_END means we are done with the sequence, and are ready
3962         * to turn the compound list into a command.
3963         * FLAG_START means the word must start a new compound list.
3964         */
3965        static const struct reserved_combo reserved_list[] ALIGN4 = {
3966# if ENABLE_HUSH_IF
3967                { "!",     RES_NONE,  NOT_ASSIGNMENT  , 0 },
3968                { "if",    RES_IF,    MAYBE_ASSIGNMENT, FLAG_THEN | FLAG_START },
3969                { "then",  RES_THEN,  MAYBE_ASSIGNMENT, FLAG_ELIF | FLAG_ELSE | FLAG_FI },
3970                { "elif",  RES_ELIF,  MAYBE_ASSIGNMENT, FLAG_THEN },
3971                { "else",  RES_ELSE,  MAYBE_ASSIGNMENT, FLAG_FI   },
3972                { "fi",    RES_FI,    NOT_ASSIGNMENT  , FLAG_END  },
3973# endif
3974# if ENABLE_HUSH_LOOPS
3975                { "for",   RES_FOR,   NOT_ASSIGNMENT  , FLAG_IN | FLAG_DO | FLAG_START },
3976                { "while", RES_WHILE, MAYBE_ASSIGNMENT, FLAG_DO | FLAG_START },
3977                { "until", RES_UNTIL, MAYBE_ASSIGNMENT, FLAG_DO | FLAG_START },
3978                { "in",    RES_IN,    NOT_ASSIGNMENT  , FLAG_DO   },
3979                { "do",    RES_DO,    MAYBE_ASSIGNMENT, FLAG_DONE },
3980                { "done",  RES_DONE,  NOT_ASSIGNMENT  , FLAG_END  },
3981# endif
3982# if ENABLE_HUSH_CASE
3983                { "case",  RES_CASE,  NOT_ASSIGNMENT  , FLAG_MATCH | FLAG_START },
3984                { "esac",  RES_ESAC,  NOT_ASSIGNMENT  , FLAG_END  },
3985# endif
3986        };
3987        const struct reserved_combo *r;
3988
3989        for (r = reserved_list; r < reserved_list + ARRAY_SIZE(reserved_list); r++) {
3990                if (strcmp(word->data, r->literal) == 0)
3991                        return r;
3992        }
3993        return NULL;
3994}
3995/* Return NULL: not a keyword, else: keyword
3996 */
3997static const struct reserved_combo* reserved_word(struct parse_context *ctx)
3998{
3999# if ENABLE_HUSH_CASE
4000        static const struct reserved_combo reserved_match = {
4001                "",        RES_MATCH, NOT_ASSIGNMENT , FLAG_MATCH | FLAG_ESAC
4002        };
4003# endif
4004        const struct reserved_combo *r;
4005
4006        if (ctx->word.has_quoted_part)
4007                return 0;
4008        r = match_reserved_word(&ctx->word);
4009        if (!r)
4010                return r; /* NULL */
4011
4012        debug_printf("found reserved word %s, res %d\n", r->literal, r->res);
4013# if ENABLE_HUSH_CASE
4014        if (r->res == RES_IN && ctx->ctx_res_w == RES_CASE_IN) {
4015                /* "case word IN ..." - IN part starts first MATCH part */
4016                r = &reserved_match;
4017        } else
4018# endif
4019        if (r->flag == 0) { /* '!' */
4020                if (ctx->ctx_inverted) { /* bash doesn't accept '! ! true' */
4021                        syntax_error("! ! command");
4022                        ctx->ctx_res_w = RES_SNTX;
4023                }
4024                ctx->ctx_inverted = 1;
4025                return r;
4026        }
4027        if (r->flag & FLAG_START) {
4028                struct parse_context *old;
4029
4030                old = xmemdup(ctx, sizeof(*ctx));
4031                debug_printf_parse("push stack %p\n", old);
4032                initialize_context(ctx);
4033                ctx->stack = old;
4034        } else if (/*ctx->ctx_res_w == RES_NONE ||*/ !(ctx->old_flag & (1 << r->res))) {
4035                syntax_error_at(ctx->word.data);
4036                ctx->ctx_res_w = RES_SNTX;
4037                return r;
4038        } else {
4039                /* "{...} fi" is ok. "{...} if" is not
4040                 * Example:
4041                 * if { echo foo; } then { echo bar; } fi */
4042                if (ctx->command->group)
4043                        done_pipe(ctx, PIPE_SEQ);
4044        }
4045
4046        ctx->ctx_res_w = r->res;
4047        ctx->old_flag = r->flag;
4048        ctx->is_assignment = r->assignment_flag;
4049        debug_printf_parse("ctx->is_assignment='%s'\n", assignment_flag[ctx->is_assignment]);
4050
4051        if (ctx->old_flag & FLAG_END) {
4052                struct parse_context *old;
4053
4054                done_pipe(ctx, PIPE_SEQ);
4055                debug_printf_parse("pop stack %p\n", ctx->stack);
4056                old = ctx->stack;
4057                old->command->group = ctx->list_head;
4058                old->command->cmd_type = CMD_NORMAL;
4059# if !BB_MMU
4060                /* At this point, the compound command's string is in
4061                 * ctx->as_string... except for the leading keyword!
4062                 * Consider this example: "echo a | if true; then echo a; fi"
4063                 * ctx->as_string will contain "true; then echo a; fi",
4064                 * with "if " remaining in old->as_string!
4065                 */
4066                {
4067                        char *str;
4068                        int len = old->as_string.length;
4069                        /* Concatenate halves */
4070                        o_addstr(&old->as_string, ctx->as_string.data);
4071                        o_free(&ctx->as_string);
4072                        /* Find where leading keyword starts in first half */
4073                        str = old->as_string.data + len;
4074                        if (str > old->as_string.data)
4075                                str--; /* skip whitespace after keyword */
4076                        while (str > old->as_string.data && isalpha(str[-1]))
4077                                str--;
4078                        /* Ugh, we're done with this horrid hack */
4079                        old->command->group_as_string = xstrdup(str);
4080                        debug_printf_parse("pop, remembering as:'%s'\n",
4081                                        old->command->group_as_string);
4082                }
4083# endif
4084                *ctx = *old;   /* physical copy */
4085                free(old);
4086        }
4087        return r;
4088}
4089#endif /* HAS_KEYWORDS */
4090
4091/* Word is complete, look at it and update parsing context.
4092 * Normal return is 0. Syntax errors return 1.
4093 * Note: on return, word is reset, but not o_free'd!
4094 */
4095static int done_word(struct parse_context *ctx)
4096{
4097        struct command *command = ctx->command;
4098
4099        debug_printf_parse("done_word entered: '%s' %p\n", ctx->word.data, command);
4100        if (ctx->word.length == 0 && !ctx->word.has_quoted_part) {
4101                debug_printf_parse("done_word return 0: true null, ignored\n");
4102                return 0;
4103        }
4104
4105        if (ctx->pending_redirect) {
4106                /* We do not glob in e.g. >*.tmp case. bash seems to glob here
4107                 * only if run as "bash", not "sh" */
4108                /* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
4109                 * "2.7 Redirection
4110                 * If the redirection operator is "<<" or "<<-", the word
4111                 * that follows the redirection operator shall be
4112                 * subjected to quote removal; it is unspecified whether
4113                 * any of the other expansions occur. For the other
4114                 * redirection operators, the word that follows the
4115                 * redirection operator shall be subjected to tilde
4116                 * expansion, parameter expansion, command substitution,
4117                 * arithmetic expansion, and quote removal.
4118                 * Pathname expansion shall not be performed
4119                 * on the word by a non-interactive shell; an interactive
4120                 * shell may perform it, but shall do so only when
4121                 * the expansion would result in one word."
4122                 */
4123//bash does not do parameter/command substitution or arithmetic expansion
4124//for _heredoc_ redirection word: these constructs look for exact eof marker
4125// as written:
4126// <<EOF$t
4127// <<EOF$((1))
4128// <<EOF`true`  [this case also makes heredoc "quoted", a-la <<"EOF". Probably bash-4.3.43 bug]
4129
4130                ctx->pending_redirect->rd_filename = xstrdup(ctx->word.data);
4131                /* Cater for >\file case:
4132                 * >\a creates file a; >\\a, >"\a", >"\\a" create file \a
4133                 * Same with heredocs:
4134                 * for <<\H delim is H; <<\\H, <<"\H", <<"\\H" - \H
4135                 */
4136                if (ctx->pending_redirect->rd_type == REDIRECT_HEREDOC) {
4137                        unbackslash(ctx->pending_redirect->rd_filename);
4138                        /* Is it <<"HEREDOC"? */
4139                        if (ctx->word.has_quoted_part) {
4140                                ctx->pending_redirect->rd_dup |= HEREDOC_QUOTED;
4141                        }
4142                }
4143                debug_printf_parse("word stored in rd_filename: '%s'\n", ctx->word.data);
4144                ctx->pending_redirect = NULL;
4145        } else {
4146#if HAS_KEYWORDS
4147# if ENABLE_HUSH_CASE
4148                if (ctx->ctx_dsemicolon
4149                 && strcmp(ctx->word.data, "esac") != 0 /* not "... pattern) cmd;; esac" */
4150                ) {
4151                        /* already done when ctx_dsemicolon was set to 1: */
4152                        /* ctx->ctx_res_w = RES_MATCH; */
4153                        ctx->ctx_dsemicolon = 0;
4154                } else
4155# endif
4156# if defined(CMD_TEST2_SINGLEWORD_NOGLOB)
4157                if (command->cmd_type == CMD_TEST2_SINGLEWORD_NOGLOB
4158                 && strcmp(ctx->word.data, "]]") == 0
4159                ) {
4160                        /* allow "[[ ]] >file" etc */
4161                        command->cmd_type = CMD_SINGLEWORD_NOGLOB;
4162                } else
4163# endif
4164                if (!command->argv /* if it's the first word... */
4165# if ENABLE_HUSH_LOOPS
4166                 && ctx->ctx_res_w != RES_FOR /* ...not after FOR or IN */
4167                 && ctx->ctx_res_w != RES_IN
4168# endif
4169# if ENABLE_HUSH_CASE
4170                 && ctx->ctx_res_w != RES_CASE
4171# endif
4172                ) {
4173                        const struct reserved_combo *reserved;
4174                        reserved = reserved_word(ctx);
4175                        debug_printf_parse("checking for reserved-ness: %d\n", !!reserved);
4176                        if (reserved) {
4177# if ENABLE_HUSH_LINENO_VAR
4178/* Case:
4179 * "while ...; do
4180 *      cmd ..."
4181 * If we don't close the pipe _now_, immediately after "do", lineno logic
4182 * sees "cmd" as starting at "do" - i.e., at the previous line.
4183 */
4184                                if (0
4185                                 IF_HUSH_IF(|| reserved->res == RES_THEN)
4186                                 IF_HUSH_IF(|| reserved->res == RES_ELIF)
4187                                 IF_HUSH_IF(|| reserved->res == RES_ELSE)
4188                                 IF_HUSH_LOOPS(|| reserved->res == RES_DO)
4189                                ) {
4190                                        done_pipe(ctx, PIPE_SEQ);
4191                                }
4192# endif
4193                                o_reset_to_empty_unquoted(&ctx->word);
4194                                debug_printf_parse("done_word return %d\n",
4195                                                (ctx->ctx_res_w == RES_SNTX));
4196                                return (ctx->ctx_res_w == RES_SNTX);
4197                        }
4198# if defined(CMD_TEST2_SINGLEWORD_NOGLOB)
4199                        if (strcmp(ctx->word.data, "[[") == 0) {
4200                                command->cmd_type = CMD_TEST2_SINGLEWORD_NOGLOB;
4201                        } else
4202# endif
4203# if defined(CMD_SINGLEWORD_NOGLOB)
4204                        if (0
4205                        /* In bash, local/export/readonly are special, args
4206                         * are assignments and therefore expansion of them
4207                         * should be "one-word" expansion:
4208                         *  $ export i=`echo 'a  b'` # one arg: "i=a  b"
4209                         * compare with:
4210                         *  $ ls i=`echo 'a  b'`     # two args: "i=a" and "b"
4211                         *  ls: cannot access i=a: No such file or directory
4212                         *  ls: cannot access b: No such file or directory
4213                         * Note: bash 3.2.33(1) does this only if export word
4214                         * itself is not quoted:
4215                         *  $ export i=`echo 'aaa  bbb'`; echo "$i"
4216                         *  aaa  bbb
4217                         *  $ "export" i=`echo 'aaa  bbb'`; echo "$i"
4218                         *  aaa
4219                         */
4220                         IF_HUSH_LOCAL(   || strcmp(ctx->word.data, "local") == 0)
4221                         IF_HUSH_EXPORT(  || strcmp(ctx->word.data, "export") == 0)
4222                         IF_HUSH_READONLY(|| strcmp(ctx->word.data, "readonly") == 0)
4223                        ) {
4224                                command->cmd_type = CMD_SINGLEWORD_NOGLOB;
4225                        }
4226# else
4227                        { /* empty block to pair "if ... else" */ }
4228# endif
4229                }
4230#endif /* HAS_KEYWORDS */
4231
4232                if (command->group) {
4233                        /* "{ echo foo; } echo bar" - bad */
4234                        syntax_error_at(ctx->word.data);
4235                        debug_printf_parse("done_word return 1: syntax error, "
4236                                        "groups and arglists don't mix\n");
4237                        return 1;
4238                }
4239
4240                /* If this word wasn't an assignment, next ones definitely
4241                 * can't be assignments. Even if they look like ones. */
4242                if (ctx->is_assignment != DEFINITELY_ASSIGNMENT
4243                 && ctx->is_assignment != WORD_IS_KEYWORD
4244                ) {
4245                        ctx->is_assignment = NOT_ASSIGNMENT;
4246                } else {
4247                        if (ctx->is_assignment == DEFINITELY_ASSIGNMENT) {
4248                                command->assignment_cnt++;
4249                                debug_printf_parse("++assignment_cnt=%d\n", command->assignment_cnt);
4250                        }
4251                        debug_printf_parse("ctx->is_assignment was:'%s'\n", assignment_flag[ctx->is_assignment]);
4252                        ctx->is_assignment = MAYBE_ASSIGNMENT;
4253                }
4254                debug_printf_parse("ctx->is_assignment='%s'\n", assignment_flag[ctx->is_assignment]);
4255                command->argv = add_string_to_strings(command->argv, xstrdup(ctx->word.data));
4256                debug_print_strings("word appended to argv", command->argv);
4257        }
4258
4259#if ENABLE_HUSH_LOOPS
4260        if (ctx->ctx_res_w == RES_FOR) {
4261                if (ctx->word.has_quoted_part
4262                 || endofname(command->argv[0])[0] != '\0'
4263                ) {
4264                        /* bash says just "not a valid identifier" */
4265                        syntax_error("bad variable name in for");
4266                        return 1;
4267                }
4268                /* Force FOR to have just one word (variable name) */
4269                /* NB: basically, this makes hush see "for v in ..."
4270                 * syntax as if it is "for v; in ...". FOR and IN become
4271                 * two pipe structs in parse tree. */
4272                done_pipe(ctx, PIPE_SEQ);
4273        }
4274#endif
4275#if ENABLE_HUSH_CASE
4276        /* Force CASE to have just one word */
4277        if (ctx->ctx_res_w == RES_CASE) {
4278                done_pipe(ctx, PIPE_SEQ);
4279        }
4280#endif
4281
4282        o_reset_to_empty_unquoted(&ctx->word);
4283
4284        debug_printf_parse("done_word return 0\n");
4285        return 0;
4286}
4287
4288
4289/* Peek ahead in the input to find out if we have a "&n" construct,
4290 * as in "2>&1", that represents duplicating a file descriptor.
4291 * Return:
4292 * REDIRFD_CLOSE if >&- "close fd" construct is seen,
4293 * REDIRFD_SYNTAX_ERR if syntax error,
4294 * REDIRFD_TO_FILE if no & was seen,
4295 * or the number found.
4296 */
4297#if BB_MMU
4298#define parse_redir_right_fd(as_string, input) \
4299        parse_redir_right_fd(input)
4300#endif
4301static int parse_redir_right_fd(o_string *as_string, struct in_str *input)
4302{
4303        int ch, d, ok;
4304
4305        ch = i_peek(input);
4306        if (ch != '&')
4307                return REDIRFD_TO_FILE;
4308
4309        ch = i_getch(input);  /* get the & */
4310        nommu_addchr(as_string, ch);
4311        ch = i_peek(input);
4312        if (ch == '-') {
4313                ch = i_getch(input);
4314                nommu_addchr(as_string, ch);
4315                return REDIRFD_CLOSE;
4316        }
4317        d = 0;
4318        ok = 0;
4319        while (ch != EOF && isdigit(ch)) {
4320                d = d*10 + (ch-'0');
4321                ok = 1;
4322                ch = i_getch(input);
4323                nommu_addchr(as_string, ch);
4324                ch = i_peek(input);
4325        }
4326        if (ok) return d;
4327
4328//TODO: this is the place to catch ">&file" bashism (redirect both fd 1 and 2)
4329
4330        bb_simple_error_msg("ambiguous redirect");
4331        return REDIRFD_SYNTAX_ERR;
4332}
4333
4334/* Return code is 0 normal, 1 if a syntax error is detected
4335 */
4336static int parse_redirect(struct parse_context *ctx,
4337                int fd,
4338                redir_type style,
4339                struct in_str *input)
4340{
4341        struct command *command = ctx->command;
4342        struct redir_struct *redir;
4343        struct redir_struct **redirp;
4344        int dup_num;
4345
4346        dup_num = REDIRFD_TO_FILE;
4347        if (style != REDIRECT_HEREDOC) {
4348                /* Check for a '>&1' type redirect */
4349                dup_num = parse_redir_right_fd(&ctx->as_string, input);
4350                if (dup_num == REDIRFD_SYNTAX_ERR)
4351                        return 1;
4352        } else {
4353                int ch = i_peek_and_eat_bkslash_nl(input);
4354                dup_num = (ch == '-'); /* HEREDOC_SKIPTABS bit is 1 */
4355                if (dup_num) { /* <<-... */
4356                        ch = i_getch(input);
4357                        nommu_addchr(&ctx->as_string, ch);
4358                        ch = i_peek(input);
4359                }
4360        }
4361
4362        if (style == REDIRECT_OVERWRITE && dup_num == REDIRFD_TO_FILE) {
4363                int ch = i_peek_and_eat_bkslash_nl(input);
4364                if (ch == '|') {
4365                        /* >|FILE redirect ("clobbering" >).
4366                         * Since we do not support "set -o noclobber" yet,
4367                         * >| and > are the same for now. Just eat |.
4368                         */
4369                        ch = i_getch(input);
4370                        nommu_addchr(&ctx->as_string, ch);
4371                }
4372        }
4373
4374        /* Create a new redir_struct and append it to the linked list */
4375        redirp = &command->redirects;
4376        while ((redir = *redirp) != NULL) {
4377                redirp = &(redir->next);
4378        }
4379        *redirp = redir = xzalloc(sizeof(*redir));
4380        /* redir->next = NULL; */
4381        /* redir->rd_filename = NULL; */
4382        redir->rd_type = style;
4383        redir->rd_fd = (fd == -1) ? redir_table[style].default_fd : fd;
4384
4385        debug_printf_parse("redirect type %d %s\n", redir->rd_fd,
4386                                redir_table[style].descrip);
4387
4388        redir->rd_dup = dup_num;
4389        if (style != REDIRECT_HEREDOC && dup_num != REDIRFD_TO_FILE) {
4390                /* Erik had a check here that the file descriptor in question
4391                 * is legit; I postpone that to "run time"
4392                 * A "-" representation of "close me" shows up as a -3 here */
4393                debug_printf_parse("duplicating redirect '%d>&%d'\n",
4394                                redir->rd_fd, redir->rd_dup);
4395        } else {
4396#if 0           /* Instead we emit error message at run time */
4397                if (ctx->pending_redirect) {
4398                        /* For example, "cmd > <file" */
4399                        syntax_error("invalid redirect");
4400                }
4401#endif
4402                /* Set ctx->pending_redirect, so we know what to do at the
4403                 * end of the next parsed word. */
4404                ctx->pending_redirect = redir;
4405        }
4406        return 0;
4407}
4408
4409/* If a redirect is immediately preceded by a number, that number is
4410 * supposed to tell which file descriptor to redirect.  This routine
4411 * looks for such preceding numbers.  In an ideal world this routine
4412 * needs to handle all the following classes of redirects...
4413 *     echo 2>foo     # redirects fd  2 to file "foo", nothing passed to echo
4414 *     echo 49>foo    # redirects fd 49 to file "foo", nothing passed to echo
4415 *     echo -2>foo    # redirects fd  1 to file "foo",    "-2" passed to echo
4416 *     echo 49x>foo   # redirects fd  1 to file "foo",   "49x" passed to echo
4417 *
4418 * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
4419 * "2.7 Redirection
4420 * ... If n is quoted, the number shall not be recognized as part of
4421 * the redirection expression. For example:
4422 * echo \2>a
4423 * writes the character 2 into file a"
4424 * We are getting it right by setting ->has_quoted_part on any \<char>
4425 *
4426 * A -1 return means no valid number was found,
4427 * the caller should use the appropriate default for this redirection.
4428 */
4429static int redirect_opt_num(o_string *o)
4430{
4431        int num;
4432
4433        if (o->data == NULL)
4434                return -1;
4435        num = bb_strtou(o->data, NULL, 10);
4436        if (errno || num < 0)
4437                return -1;
4438        o_reset_to_empty_unquoted(o);
4439        return num;
4440}
4441
4442#if BB_MMU
4443#define fetch_till_str(as_string, input, word, skip_tabs) \
4444        fetch_till_str(input, word, skip_tabs)
4445#endif
4446static char *fetch_till_str(o_string *as_string,
4447                struct in_str *input,
4448                const char *word,
4449                int heredoc_flags)
4450{
4451        o_string heredoc = NULL_O_STRING;
4452        unsigned past_EOL;
4453        int prev = 0; /* not \ */
4454        int ch;
4455
4456        /* Starting with "" is necessary for this case:
4457         * cat <<EOF
4458         *
4459         * xxx
4460         * EOF
4461         */
4462        heredoc.data = xzalloc(1); /* start as "", not as NULL */
4463
4464        goto jump_in;
4465
4466        while (1) {
4467                ch = i_getch(input);
4468                if (ch != EOF)
4469                        nommu_addchr(as_string, ch);
4470                if (ch == '\n' || ch == EOF) {
4471 check_heredoc_end:
4472                        if ((heredoc_flags & HEREDOC_QUOTED) || prev != '\\') {
4473                                /* End-of-line, and not a line continuation */
4474                                if (strcmp(heredoc.data + past_EOL, word) == 0) {
4475                                        heredoc.data[past_EOL] = '\0';
4476                                        debug_printf_heredoc("parsed '%s' heredoc '%s'\n", word, heredoc.data);
4477                                        return heredoc.data;
4478                                }
4479                                if (ch == '\n') {
4480                                        /* This is a new line.
4481                                         * Remember position and backslash-escaping status.
4482                                         */
4483                                        o_addchr(&heredoc, ch);
4484                                        prev = ch;
4485 jump_in:
4486                                        past_EOL = heredoc.length;
4487                                        /* Get 1st char of next line, possibly skipping leading tabs */
4488                                        do {
4489                                                ch = i_getch(input);
4490                                                if (ch != EOF)
4491                                                        nommu_addchr(as_string, ch);
4492                                        } while ((heredoc_flags & HEREDOC_SKIPTABS) && ch == '\t');
4493                                        /* If this immediately ended the line,
4494                                         * go back to end-of-line checks.
4495                                         */
4496                                        if (ch == '\n')
4497                                                goto check_heredoc_end;
4498                                }
4499                        } else {
4500                                /* Backslash-line continuation in an unquoted
4501                                 * heredoc. This does not need special handling
4502                                 * for heredoc body (unquoted heredocs are
4503                                 * expanded on "execution" and that would take
4504                                 * care of this case too), but not the case
4505                                 * of line continuation *in terminator*:
4506                                 *  cat <<EOF
4507                                 *  Ok1
4508                                 *  EO\
4509                                 *  F
4510                                 */
4511                                heredoc.data[--heredoc.length] = '\0';
4512                                prev = 0; /* not '\' */
4513                                continue;
4514                        }
4515                }
4516                if (ch == EOF) {
4517                        o_free(&heredoc);
4518                        return NULL; /* error */
4519                }
4520                o_addchr(&heredoc, ch);
4521                nommu_addchr(as_string, ch);
4522                if (prev == '\\' && ch == '\\')
4523                        /* Correctly handle foo\\<eol> (not a line cont.) */
4524                        prev = 0; /* not '\' */
4525                else
4526                        prev = ch;
4527        }
4528}
4529
4530/* Look at entire parse tree for not-yet-loaded REDIRECT_HEREDOCs
4531 * and load them all. There should be exactly heredoc_cnt of them.
4532 */
4533#if BB_MMU
4534#define fetch_heredocs(as_string, pi, heredoc_cnt, input) \
4535        fetch_heredocs(pi, heredoc_cnt, input)
4536#endif
4537static int fetch_heredocs(o_string *as_string, struct pipe *pi, int heredoc_cnt, struct in_str *input)
4538{
4539        while (pi && heredoc_cnt) {
4540                int i;
4541                struct command *cmd = pi->cmds;
4542
4543                debug_printf_heredoc("fetch_heredocs: num_cmds:%d cmd argv0:'%s'\n",
4544                                pi->num_cmds,
4545                                cmd->argv ? cmd->argv[0] : "NONE"
4546                );
4547                for (i = 0; i < pi->num_cmds; i++) {
4548                        struct redir_struct *redir = cmd->redirects;
4549
4550                        debug_printf_heredoc("fetch_heredocs: %d cmd argv0:'%s'\n",
4551                                        i, cmd->argv ? cmd->argv[0] : "NONE");
4552                        while (redir) {
4553                                if (redir->rd_type == REDIRECT_HEREDOC) {
4554                                        char *p;
4555
4556                                        redir->rd_type = REDIRECT_HEREDOC2;
4557                                        /* redir->rd_dup is (ab)used to indicate <<- */
4558                                        p = fetch_till_str(as_string, input,
4559                                                        redir->rd_filename, redir->rd_dup);
4560                                        if (!p) {
4561                                                syntax_error("unexpected EOF in here document");
4562                                                return -1;
4563                                        }
4564                                        free(redir->rd_filename);
4565                                        redir->rd_filename = p;
4566                                        heredoc_cnt--;
4567                                }
4568                                redir = redir->next;
4569                        }
4570                        if (cmd->group) {
4571                                //bb_error_msg("%s:%u heredoc_cnt:%d", __func__, __LINE__, heredoc_cnt);
4572                                heredoc_cnt = fetch_heredocs(as_string, cmd->group, heredoc_cnt, input);
4573                                //bb_error_msg("%s:%u heredoc_cnt:%d", __func__, __LINE__, heredoc_cnt);
4574                                if (heredoc_cnt < 0)
4575                                        return heredoc_cnt; /* error */
4576                        }
4577                        cmd++;
4578                }
4579                pi = pi->next;
4580        }
4581        return heredoc_cnt;
4582}
4583
4584
4585static int run_list(struct pipe *pi);
4586#if BB_MMU
4587#define parse_stream(pstring, heredoc_cnt_ptr, input, end_trigger) \
4588        parse_stream(heredoc_cnt_ptr, input, end_trigger)
4589#endif
4590static struct pipe *parse_stream(char **pstring,
4591                int *heredoc_cnt_ptr,
4592                struct in_str *input,
4593                int end_trigger);
4594
4595/* Returns number of heredocs not yet consumed,
4596 * or -1 on error.
4597 */
4598static int parse_group(struct parse_context *ctx,
4599                struct in_str *input, int ch)
4600{
4601        /* ctx->word contains characters seen prior to ( or {.
4602         * Typically it's empty, but for function defs,
4603         * it contains function name (without '()'). */
4604#if BB_MMU
4605# define as_string NULL
4606#else
4607        char *as_string = NULL;
4608#endif
4609        struct pipe *pipe_list;
4610        int heredoc_cnt = 0;
4611        int endch;
4612        struct command *command = ctx->command;
4613
4614        debug_printf_parse("parse_group entered\n");
4615#if ENABLE_HUSH_FUNCTIONS
4616        if (ch == '(' && !ctx->word.has_quoted_part) {
4617                if (ctx->word.length)
4618                        if (done_word(ctx))
4619                                return -1;
4620                if (!command->argv)
4621                        goto skip; /* (... */
4622                if (command->argv[1]) { /* word word ... (... */
4623                        syntax_error_unexpected_ch('(');
4624                        return -1;
4625                }
4626                /* it is "word(..." or "word (..." */
4627                do
4628                        ch = i_getch(input);
4629                while (ch == ' ' || ch == '\t');
4630                if (ch != ')') {
4631                        syntax_error_unexpected_ch(ch);
4632                        return -1;
4633                }
4634                nommu_addchr(&ctx->as_string, ch);
4635                do
4636                        ch = i_getch(input);
4637                while (ch == ' ' || ch == '\t' || ch == '\n');
4638                if (ch != '{' && ch != '(') {
4639                        syntax_error_unexpected_ch(ch);
4640                        return -1;
4641                }
4642                nommu_addchr(&ctx->as_string, ch);
4643                command->cmd_type = CMD_FUNCDEF;
4644                goto skip;
4645        }
4646#endif
4647
4648#if 0 /* Prevented by caller */
4649        if (command->argv /* word [word]{... */
4650         || ctx->word.length /* word{... */
4651         || ctx->word.has_quoted_part /* ""{... */
4652        ) {
4653                syntax_error(NULL);
4654                debug_printf_parse("parse_group return -1: "
4655                        "syntax error, groups and arglists don't mix\n");
4656                return -1;
4657        }
4658#endif
4659
4660 IF_HUSH_FUNCTIONS(skip:)
4661
4662        endch = '}';
4663        if (ch == '(') {
4664                endch = ')';
4665                IF_HUSH_FUNCTIONS(if (command->cmd_type != CMD_FUNCDEF))
4666                        command->cmd_type = CMD_SUBSHELL;
4667        } else {
4668                /* bash does not allow "{echo...", requires whitespace */
4669                ch = i_peek(input);
4670                if (ch != ' ' && ch != '\t' && ch != '\n'
4671                 && ch != '('   /* but "{(..." is allowed (without whitespace) */
4672                ) {
4673                        syntax_error_unexpected_ch(ch);
4674                        return -1;
4675                }
4676                if (ch != '(') {
4677                        ch = i_getch(input);
4678                        nommu_addchr(&ctx->as_string, ch);
4679                }
4680        }
4681
4682        debug_printf_heredoc("calling parse_stream, heredoc_cnt:%d\n", heredoc_cnt);
4683        pipe_list = parse_stream(&as_string, &heredoc_cnt, input, endch);
4684        debug_printf_heredoc("parse_stream returned: heredoc_cnt:%d\n", heredoc_cnt);
4685#if !BB_MMU
4686        if (as_string)
4687                o_addstr(&ctx->as_string, as_string);
4688#endif
4689
4690        /* empty ()/{} or parse error? */
4691        if (!pipe_list || pipe_list == ERR_PTR) {
4692                /* parse_stream already emitted error msg */
4693                if (!BB_MMU)
4694                        free(as_string);
4695                debug_printf_parse("parse_group return -1: "
4696                        "parse_stream returned %p\n", pipe_list);
4697                return -1;
4698        }
4699#if !BB_MMU
4700        as_string[strlen(as_string) - 1] = '\0'; /* plink ')' or '}' */
4701        command->group_as_string = as_string;
4702        debug_printf_parse("end of group, remembering as:'%s'\n",
4703                        command->group_as_string);
4704#endif
4705
4706#if ENABLE_HUSH_FUNCTIONS
4707        /* Convert "f() (cmds)" to "f() {(cmds)}" */
4708        if (command->cmd_type == CMD_FUNCDEF && endch == ')') {
4709                struct command *cmd2;
4710
4711                cmd2 = xzalloc(sizeof(*cmd2));
4712                cmd2->cmd_type = CMD_SUBSHELL;
4713                cmd2->group = pipe_list;
4714# if !BB_MMU
4715//UNTESTED!
4716                cmd2->group_as_string = command->group_as_string;
4717                command->group_as_string = xasprintf("(%s)", command->group_as_string);
4718# endif
4719
4720                pipe_list = new_pipe();
4721                pipe_list->cmds = cmd2;
4722                pipe_list->num_cmds = 1;
4723        }
4724#endif
4725
4726        command->group = pipe_list;
4727
4728        debug_printf_parse("parse_group return %d\n", heredoc_cnt);
4729        return heredoc_cnt;
4730        /* command remains "open", available for possible redirects */
4731#undef as_string
4732}
4733
4734#if ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS
4735/* Subroutines for copying $(...) and `...` things */
4736/* '...' */
4737static int add_till_single_quote(o_string *dest, struct in_str *input)
4738{
4739        while (1) {
4740                int ch = i_getch(input);
4741                if (ch == EOF) {
4742                        syntax_error_unterm_ch('\'');
4743                        return 0;
4744                }
4745                if (ch == '\'')
4746                        return 1;
4747                o_addchr(dest, ch);
4748        }
4749}
4750static int add_till_single_quote_dquoted(o_string *dest, struct in_str *input)
4751{
4752        while (1) {
4753                int ch = i_getch(input);
4754                if (ch == EOF) {
4755                        syntax_error_unterm_ch('\'');
4756                        return 0;
4757                }
4758                if (ch == '\'')
4759                        return 1;
4760                o_addqchr(dest, ch);
4761        }
4762}
4763/* "...\"...`..`...." - do we need to handle "...$(..)..." too? */
4764static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote);
4765static int add_till_double_quote(o_string *dest, struct in_str *input)
4766{
4767        while (1) {
4768                int ch = i_getch(input);
4769                if (ch == EOF) {
4770                        syntax_error_unterm_ch('"');
4771                        return 0;
4772                }
4773                if (ch == '"')
4774                        return 1;
4775                if (ch == '\\') {  /* \x. Copy both chars. */
4776                        o_addchr(dest, ch);
4777                        ch = i_getch(input);
4778                }
4779                o_addchr(dest, ch);
4780                if (ch == '`') {
4781                        if (!add_till_backquote(dest, input, /*in_dquote:*/ 1))
4782                                return 0;
4783                        o_addchr(dest, ch);
4784                        continue;
4785                }
4786                //if (ch == '$') ...
4787        }
4788}
4789/* Process `cmd` - copy contents until "`" is seen. Complicated by
4790 * \` quoting.
4791 * "Within the backquoted style of command substitution, backslash
4792 * shall retain its literal meaning, except when followed by: '$', '`', or '\'.
4793 * The search for the matching backquote shall be satisfied by the first
4794 * backquote found without a preceding backslash; during this search,
4795 * if a non-escaped backquote is encountered within a shell comment,
4796 * a here-document, an embedded command substitution of the $(command)
4797 * form, or a quoted string, undefined results occur. A single-quoted
4798 * or double-quoted string that begins, but does not end, within the
4799 * "`...`" sequence produces undefined results."
4800 * Example                               Output
4801 * echo `echo '\'TEST\`echo ZZ\`BEST`    \TESTZZBEST
4802 */
4803static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote)
4804{
4805        while (1) {
4806                int ch = i_getch(input);
4807                if (ch == '`')
4808                        return 1;
4809                if (ch == '\\') {
4810                        /* \x. Copy both unless it is \`, \$, \\ and maybe \" */
4811                        ch = i_getch(input);
4812                        if (ch != '`'
4813                         && ch != '$'
4814                         && ch != '\\'
4815                         && (!in_dquote || ch != '"')
4816                        ) {
4817                                o_addchr(dest, '\\');
4818                        }
4819                }
4820                if (ch == EOF) {
4821                        syntax_error_unterm_ch('`');
4822                        return 0;
4823                }
4824                o_addchr(dest, ch);
4825        }
4826}
4827/* Process $(cmd) - copy contents until ")" is seen. Complicated by
4828 * quoting and nested ()s.
4829 * "With the $(command) style of command substitution, all characters
4830 * following the open parenthesis to the matching closing parenthesis
4831 * constitute the command. Any valid shell script can be used for command,
4832 * except a script consisting solely of redirections which produces
4833 * unspecified results."
4834 * Example                              Output
4835 * echo $(echo '(TEST)' BEST)           (TEST) BEST
4836 * echo $(echo 'TEST)' BEST)            TEST) BEST
4837 * echo $(echo \(\(TEST\) BEST)         ((TEST) BEST
4838 *
4839 * Also adapted to eat ${var%...} and $((...)) constructs, since ... part
4840 * can contain arbitrary constructs, just like $(cmd).
4841 * In bash compat mode, it needs to also be able to stop on ':' or '/'
4842 * for ${var:N[:M]} and ${var/P[/R]} parsing.
4843 */
4844#define DOUBLE_CLOSE_CHAR_FLAG 0x80
4845static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsigned end_ch)
4846{
4847        int ch;
4848        char dbl = end_ch & DOUBLE_CLOSE_CHAR_FLAG;
4849# if BASH_SUBSTR || BASH_PATTERN_SUBST
4850        char end_char2 = end_ch >> 8;
4851# endif
4852        end_ch &= (DOUBLE_CLOSE_CHAR_FLAG - 1);
4853
4854# if ENABLE_HUSH_INTERACTIVE
4855        G.promptmode = 1; /* PS2 */
4856# endif
4857        debug_printf_prompt("%s promptmode=%d\n", __func__, G.promptmode);
4858
4859        while (1) {
4860                ch = i_getch(input);
4861                if (ch == EOF) {
4862                        syntax_error_unterm_ch(end_ch);
4863                        return 0;
4864                }
4865                if (ch == end_ch
4866# if BASH_SUBSTR || BASH_PATTERN_SUBST
4867                 || ch == end_char2
4868# endif
4869                ) {
4870                        if (!dbl)
4871                                break;
4872                        /* we look for closing )) of $((EXPR)) */
4873                        if (i_peek_and_eat_bkslash_nl(input) == end_ch) {
4874                                i_getch(input); /* eat second ')' */
4875                                break;
4876                        }
4877                }
4878                o_addchr(dest, ch);
4879                //bb_error_msg("%s:o_addchr('%c')", __func__, ch);
4880                if (ch == '(' || ch == '{') {
4881                        ch = (ch == '(' ? ')' : '}');
4882                        if (!add_till_closing_bracket(dest, input, ch))
4883                                return 0;
4884                        o_addchr(dest, ch);
4885                        continue;
4886                }
4887                if (ch == '\'') {
4888                        if (!add_till_single_quote(dest, input))
4889                                return 0;
4890                        o_addchr(dest, ch);
4891                        continue;
4892                }
4893                if (ch == '"') {
4894                        if (!add_till_double_quote(dest, input))
4895                                return 0;
4896                        o_addchr(dest, ch);
4897                        continue;
4898                }
4899                if (ch == '`') {
4900                        if (!add_till_backquote(dest, input, /*in_dquote:*/ 0))
4901                                return 0;
4902                        o_addchr(dest, ch);
4903                        continue;
4904                }
4905                if (ch == '\\') {
4906                        /* \x. Copy verbatim. Important for  \(, \) */
4907                        ch = i_getch(input);
4908                        if (ch == EOF) {
4909                                syntax_error_unterm_ch(end_ch);
4910                                return 0;
4911                        }
4912# if 0
4913                        if (ch == '\n') {
4914                                /* "backslash+newline", ignore both */
4915                                o_delchr(dest); /* undo insertion of '\' */
4916                                continue;
4917                        }
4918# endif
4919                        o_addchr(dest, ch);
4920                        //bb_error_msg("%s:o_addchr('%c') after '\\'", __func__, ch);
4921                        continue;
4922                }
4923        }
4924        debug_printf_parse("%s return '%s' ch:'%c'\n", __func__, dest->data, ch);
4925        return ch;
4926}
4927#endif /* ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS */
4928
4929#if BASH_DOLLAR_SQUOTE
4930/* Return code: 1 for "found and parsed", 0 for "seen something else" */
4931# if BB_MMU
4932#define parse_dollar_squote(as_string, dest, input) \
4933        parse_dollar_squote(dest, input)
4934#define as_string NULL
4935# endif
4936static int parse_dollar_squote(o_string *as_string, o_string *dest, struct in_str *input)
4937{
4938        int start;
4939        int ch = i_peek_and_eat_bkslash_nl(input);  /* first character after the $ */
4940        debug_printf_parse("parse_dollar_squote entered: ch='%c'\n", ch);
4941        if (ch != '\'')
4942                return 0;
4943
4944        dest->has_quoted_part = 1;
4945        start = dest->length;
4946
4947        ch = i_getch(input); /* eat ' */
4948        nommu_addchr(as_string, ch);
4949        while (1) {
4950                ch = i_getch(input);
4951                nommu_addchr(as_string, ch);
4952                if (ch == EOF) {
4953                        syntax_error_unterm_ch('\'');
4954                        return 0;
4955                }
4956                if (ch == '\'')
4957                        break;
4958                if (ch == SPECIAL_VAR_SYMBOL) {
4959                        /* Convert raw ^C to corresponding special variable reference */
4960                        o_addchr(dest, SPECIAL_VAR_SYMBOL);
4961                        o_addchr(dest, SPECIAL_VAR_QUOTED_SVS);
4962                        /* will addchr() another SPECIAL_VAR_SYMBOL (see after the if() block) */
4963                } else if (ch == '\\') {
4964                        static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
4965
4966                        ch = i_getch(input);
4967                        nommu_addchr(as_string, ch);
4968                        if (strchr(C_escapes, ch)) {
4969                                char buf[4];
4970                                char *p = buf;
4971                                int cnt = 2;
4972
4973                                buf[0] = ch;
4974                                if ((unsigned char)(ch - '0') <= 7) { /* \ooo */
4975                                        do {
4976                                                ch = i_peek(input);
4977                                                if ((unsigned char)(ch - '0') > 7)
4978                                                        break;
4979                                                *++p = ch = i_getch(input);
4980                                                nommu_addchr(as_string, ch);
4981                                        } while (--cnt != 0);
4982                                } else if (ch == 'x') { /* \xHH */
4983                                        do {
4984                                                ch = i_peek(input);
4985                                                if (!isxdigit(ch))
4986                                                        break;
4987                                                *++p = ch = i_getch(input);
4988                                                nommu_addchr(as_string, ch);
4989                                        } while (--cnt != 0);
4990                                        if (cnt == 2) { /* \x but next char is "bad" */
4991                                                ch = 'x';
4992                                                goto unrecognized;
4993                                        }
4994                                } /* else simple seq like \\ or \t */
4995                                *++p = '\0';
4996                                p = buf;
4997                                ch = bb_process_escape_sequence((void*)&p);
4998                                //bb_error_msg("buf:'%s' ch:%x", buf, ch);
4999                                if (ch == '\0')
5000                                        continue; /* bash compat: $'...\0...' emits nothing */
5001                        } else { /* unrecognized "\z": encode both chars unless ' or " */
5002                                if (ch != '\'' && ch != '"') {
5003 unrecognized:
5004                                        o_addqchr(dest, '\\');
5005                                }
5006                        }
5007                } /* if (\...) */
5008                o_addqchr(dest, ch);
5009        }
5010
5011        if (dest->length == start) {
5012                /* $'', $'\0', $'\000\x00' and the like */
5013                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5014                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5015        }
5016
5017        return 1;
5018# undef as_string
5019}
5020#else
5021# define parse_dollar_squote(as_string, dest, input) 0
5022#endif /* BASH_DOLLAR_SQUOTE */
5023
5024/* Return code: 0 for OK, 1 for syntax error */
5025#if BB_MMU
5026#define parse_dollar(as_string, dest, input, quote_mask) \
5027        parse_dollar(dest, input, quote_mask)
5028#define as_string NULL
5029#endif
5030static int parse_dollar(o_string *as_string,
5031                o_string *dest,
5032                struct in_str *input, unsigned char quote_mask)
5033{
5034        int ch = i_peek_and_eat_bkslash_nl(input);  /* first character after the $ */
5035
5036        debug_printf_parse("parse_dollar entered: ch='%c' quote_mask:0x%x\n", ch, quote_mask);
5037        if (isalpha(ch)) {
5038 make_var:
5039                ch = i_getch(input);
5040                nommu_addchr(as_string, ch);
5041 /*make_var1:*/
5042                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5043                while (1) {
5044                        debug_printf_parse(": '%c'\n", ch);
5045                        o_addchr(dest, ch | quote_mask);
5046                        quote_mask = 0;
5047                        ch = i_peek_and_eat_bkslash_nl(input);
5048                        if (!isalnum(ch) && ch != '_') {
5049                                /* End of variable name reached */
5050                                break;
5051                        }
5052                        ch = i_getch(input);
5053                        nommu_addchr(as_string, ch);
5054                }
5055                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5056        } else if (isdigit(ch)) {
5057 make_one_char_var:
5058                ch = i_getch(input);
5059                nommu_addchr(as_string, ch);
5060                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5061                debug_printf_parse(": '%c'\n", ch);
5062                o_addchr(dest, ch | quote_mask);
5063                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5064        } else switch (ch) {
5065        case '$': /* pid */
5066        case '!': /* last bg pid */
5067        case '?': /* last exit code */
5068        case '#': /* number of args */
5069        case '*': /* args */
5070        case '@': /* args */
5071        case '-': /* $- option flags set by set builtin or shell options (-i etc) */
5072                goto make_one_char_var;
5073        case '{': {
5074                char len_single_ch;
5075
5076                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5077
5078                ch = i_getch(input); /* eat '{' */
5079                nommu_addchr(as_string, ch);
5080
5081                ch = i_getch_and_eat_bkslash_nl(input); /* first char after '{' */
5082                /* It should be ${?}, or ${#var},
5083                 * or even ${?+subst} - operator acting on a special variable,
5084                 * or the beginning of variable name.
5085                 */
5086                if (ch == EOF
5087                 || (!strchr(_SPECIAL_VARS_STR, ch) && !isalnum(ch)) /* not one of those */
5088                ) {
5089 bad_dollar_syntax:
5090                        syntax_error_unterm_str("${name}");
5091                        debug_printf_parse("parse_dollar return 0: unterminated ${name}\n");
5092                        return 0;
5093                }
5094                nommu_addchr(as_string, ch);
5095                len_single_ch = ch;
5096                ch |= quote_mask;
5097
5098                /* It's possible to just call add_till_closing_bracket() at this point.
5099                 * However, this regresses some of our testsuite cases
5100                 * which check invalid constructs like ${%}.
5101                 * Oh well... let's check that the var name part is fine... */
5102
5103                if (isdigit(len_single_ch)
5104                 || (len_single_ch == '#' && isdigit(i_peek_and_eat_bkslash_nl(input)))
5105                ) {
5106                        /* Execution engine uses plain xatoi_positive()
5107                         * to interpret ${NNN} and {#NNN},
5108                         * check syntax here in the parser.
5109                         * (bash does not support expressions in ${#NN},
5110                         * e.g. ${#$var} and {#1:+WORD} are not supported).
5111                         */
5112                        unsigned cnt = 9; /* max 9 digits for ${NN} and 8 for {#NN} */
5113                        while (1) {
5114                                o_addchr(dest, ch);
5115                                debug_printf_parse(": '%c'\n", ch);
5116                                ch = i_getch_and_eat_bkslash_nl(input);
5117                                nommu_addchr(as_string, ch);
5118                                if (ch == '}')
5119                                        break;
5120                                if (--cnt == 0)
5121                                        goto bad_dollar_syntax;
5122                                if (len_single_ch != '#' && strchr(VAR_SUBST_OPS, ch))
5123                                        /* ${NN<op>...} is valid */
5124                                        goto eat_until_closing;
5125                                if (!isdigit(ch))
5126                                        goto bad_dollar_syntax;
5127                        }
5128                } else
5129                while (1) {
5130                        unsigned pos;
5131
5132                        o_addchr(dest, ch);
5133                        debug_printf_parse(": '%c'\n", ch);
5134
5135                        ch = i_getch(input);
5136                        nommu_addchr(as_string, ch);
5137                        if (ch == '}')
5138                                break;
5139                        if (!isalnum(ch) && ch != '_') {
5140                                unsigned end_ch;
5141                                unsigned char last_ch;
5142                                /* handle parameter expansions
5143                                 * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02
5144                                 */
5145                                if (!strchr(VAR_SUBST_OPS, ch)) { /* ${var<bad_char>... */
5146                                        if (len_single_ch != '#'
5147                                        /*|| !strchr(SPECIAL_VARS_STR, ch) - disallow errors like ${#+} ? */
5148                                         || i_peek(input) != '}'
5149                                        ) {
5150                                                goto bad_dollar_syntax;
5151                                        }
5152                                        /* else: it's "length of C" ${#C} op,
5153                                         * where C is a single char
5154                                         * special var name, e.g. ${#!}.
5155                                         */
5156                                }
5157 eat_until_closing:
5158                                /* Eat everything until closing '}' (or ':') */
5159                                end_ch = '}';
5160                                if (BASH_SUBSTR
5161                                 && ch == ':'
5162                                 && !strchr(MINUS_PLUS_EQUAL_QUESTION, i_peek(input))
5163                                ) {
5164                                        /* It's ${var:N[:M]} thing */
5165                                        end_ch = '}' * 0x100 + ':';
5166                                }
5167                                if (BASH_PATTERN_SUBST
5168                                 && ch == '/'
5169                                ) {
5170                                        /* It's ${var/[/]pattern[/repl]} thing */
5171                                        if (i_peek(input) == '/') { /* ${var//pattern[/repl]}? */
5172                                                i_getch(input);
5173                                                nommu_addchr(as_string, '/');
5174                                                ch = '\\';
5175                                        }
5176                                        end_ch = '}' * 0x100 + '/';
5177                                }
5178                                o_addchr(dest, ch);
5179                                /* The pattern can't be empty.
5180                                 * IOW: if the first char after "${v//" is a slash,
5181                                 * it does not terminate the pattern - it's the first char of the pattern:
5182                                 *  v=/dev/ram; echo ${v////-}  prints -dev-ram (pattern is "/")
5183                                 *  v=/dev/ram; echo ${v///r/-} prints /dev-am  (pattern is "/r")
5184                                 */
5185                                if (i_peek(input) == '/') {
5186                                        o_addchr(dest, i_getch(input));
5187                                }
5188 again:
5189                                if (!BB_MMU)
5190                                        pos = dest->length;
5191#if ENABLE_HUSH_DOLLAR_OPS
5192                                last_ch = add_till_closing_bracket(dest, input, end_ch);
5193                                if (last_ch == 0) /* error? */
5194                                        return 0;
5195#else
5196# error Simple code to only allow ${var} is not implemented
5197#endif
5198                                if (as_string) {
5199                                        o_addstr(as_string, dest->data + pos);
5200                                        o_addchr(as_string, last_ch);
5201                                }
5202
5203                                if ((BASH_SUBSTR || BASH_PATTERN_SUBST)
5204                                         && (end_ch & 0xff00)
5205                                ) {
5206                                        /* close the first block: */
5207                                        o_addchr(dest, SPECIAL_VAR_SYMBOL);
5208                                        /* while parsing N from ${var:N[:M]}
5209                                         * or pattern from ${var/[/]pattern[/repl]} */
5210                                        if ((end_ch & 0xff) == last_ch) {
5211                                                /* got ':' or '/'- parse the rest */
5212                                                end_ch = '}';
5213                                                goto again;
5214                                        }
5215                                        /* got '}' */
5216                                        if (BASH_SUBSTR && end_ch == '}' * 0x100 + ':') {
5217                                                /* it's ${var:N} - emulate :999999999 */
5218                                                o_addstr(dest, "999999999");
5219                                        } /* else: it's ${var/[/]pattern} */
5220                                }
5221                                break;
5222                        }
5223                        len_single_ch = 0; /* it can't be ${#C} op */
5224                }
5225                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5226                break;
5227        }
5228#if ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_TICK
5229        case '(': {
5230                unsigned pos;
5231
5232                ch = i_getch(input);
5233                nommu_addchr(as_string, ch);
5234# if ENABLE_FEATURE_SH_MATH
5235                if (i_peek_and_eat_bkslash_nl(input) == '(') {
5236                        ch = i_getch(input);
5237                        nommu_addchr(as_string, ch);
5238                        o_addchr(dest, SPECIAL_VAR_SYMBOL);
5239                        o_addchr(dest, quote_mask | '+');
5240                        if (!BB_MMU)
5241                                pos = dest->length;
5242                        if (!add_till_closing_bracket(dest, input, ')' | DOUBLE_CLOSE_CHAR_FLAG))
5243                                return 0; /* error */
5244                        if (as_string) {
5245                                o_addstr(as_string, dest->data + pos);
5246                                o_addchr(as_string, ')');
5247                                o_addchr(as_string, ')');
5248                        }
5249                        o_addchr(dest, SPECIAL_VAR_SYMBOL);
5250                        break;
5251                }
5252# endif
5253# if ENABLE_HUSH_TICK
5254                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5255                o_addchr(dest, quote_mask | '`');
5256                if (!BB_MMU)
5257                        pos = dest->length;
5258                if (!add_till_closing_bracket(dest, input, ')'))
5259                        return 0; /* error */
5260                if (as_string) {
5261                        o_addstr(as_string, dest->data + pos);
5262                        o_addchr(as_string, ')');
5263                }
5264                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5265# endif
5266                break;
5267        }
5268#endif
5269        case '_':
5270                goto make_var;
5271#if 0
5272        /* TODO: $_: */
5273        /* $_ Shell or shell script name; or last argument of last command
5274         * (if last command wasn't a pipe; if it was, bash sets $_ to "");
5275         * but in command's env, set to full pathname used to invoke it */
5276                ch = i_getch(input);
5277                nommu_addchr(as_string, ch);
5278                ch = i_peek_and_eat_bkslash_nl(input);
5279                if (isalnum(ch)) { /* it's $_name or $_123 */
5280                        ch = '_';
5281                        goto make_var1;
5282                }
5283                /* else: it's $_ */
5284#endif
5285        default:
5286                o_addQchr(dest, '$');
5287        }
5288        debug_printf_parse("parse_dollar return 1 (ok)\n");
5289        return 1;
5290#undef as_string
5291}
5292
5293#if BB_MMU
5294#define encode_string(as_string, dest, input, dquote_end) \
5295        encode_string(dest, input, dquote_end)
5296#define as_string NULL
5297#endif
5298static int encode_string(o_string *as_string,
5299                o_string *dest,
5300                struct in_str *input,
5301                int dquote_end)
5302{
5303        int ch;
5304        int next;
5305
5306 again:
5307        ch = i_getch(input);
5308        if (ch != EOF)
5309                nommu_addchr(as_string, ch);
5310        if (ch == dquote_end) { /* may be only '"' or EOF */
5311                debug_printf_parse("encode_string return 1 (ok)\n");
5312                return 1;
5313        }
5314        /* note: can't move it above ch == dquote_end check! */
5315        if (ch == EOF) {
5316                syntax_error_unterm_ch('"');
5317                return 0; /* error */
5318        }
5319        next = '\0';
5320        if (ch != '\n') {
5321                next = i_peek(input);
5322        }
5323        debug_printf_parse("\" ch=%c (%d) escape=%d\n",
5324                        ch, ch, !!(dest->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
5325        if (ch == '\\') {
5326                if (next == EOF) {
5327                        /* Testcase: in interactive shell a file with
5328                         *  echo "unterminated string\<eof>
5329                         * is sourced.
5330                         */
5331                        syntax_error_unterm_ch('"');
5332                        return 0; /* error */
5333                }
5334                /* bash:
5335                 * "The backslash retains its special meaning [in "..."]
5336                 * only when followed by one of the following characters:
5337                 * $, `, ", \, or <newline>.  A double quote may be quoted
5338                 * within double quotes by preceding it with a backslash."
5339                 * NB: in (unquoted) heredoc, above does not apply to ",
5340                 * therefore we check for it by "next == dquote_end" cond.
5341                 */
5342                if (next == dquote_end || strchr("$`\\\n", next)) {
5343                        ch = i_getch(input); /* eat next */
5344                        if (ch == '\n')
5345                                goto again; /* skip \<newline> */
5346                } /* else: ch remains == '\\', and we double it below: */
5347                o_addqchr(dest, ch); /* \c if c is a glob char, else just c */
5348                nommu_addchr(as_string, ch);
5349                goto again;
5350        }
5351        if (ch == '$') {
5352                //if (parse_dollar_squote(as_string, dest, input))
5353                //      goto again;
5354                if (!parse_dollar(as_string, dest, input, /*quote_mask:*/ 0x80)) {
5355                        debug_printf_parse("encode_string return 0: "
5356                                        "parse_dollar returned 0 (error)\n");
5357                        return 0;
5358                }
5359                goto again;
5360        }
5361#if ENABLE_HUSH_TICK
5362        if (ch == '`') {
5363                //unsigned pos = dest->length;
5364                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5365                o_addchr(dest, 0x80 | '`');
5366                if (!add_till_backquote(dest, input, /*in_dquote:*/ dquote_end == '"'))
5367                        return 0; /* error */
5368                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5369                //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos);
5370                goto again;
5371        }
5372#endif
5373        o_addQchr(dest, ch);
5374        if (ch == SPECIAL_VAR_SYMBOL) {
5375                /* Convert "^C" to corresponding special variable reference */
5376                o_addchr(dest, SPECIAL_VAR_QUOTED_SVS);
5377                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5378        }
5379        goto again;
5380#undef as_string
5381}
5382
5383/*
5384 * Scan input until EOF or end_trigger char.
5385 * Return a list of pipes to execute, or NULL on EOF
5386 * or if end_trigger character is met.
5387 * On syntax error, exit if shell is not interactive,
5388 * reset parsing machinery and start parsing anew,
5389 * or return ERR_PTR.
5390 */
5391static struct pipe *parse_stream(char **pstring,
5392                int *heredoc_cnt_ptr,
5393                struct in_str *input,
5394                int end_trigger)
5395{
5396        struct parse_context ctx;
5397        int heredoc_cnt;
5398
5399        /* Single-quote triggers a bypass of the main loop until its mate is
5400         * found.  When recursing, quote state is passed in via ctx.word.o_expflags.
5401         */
5402        debug_printf_parse("parse_stream entered, end_trigger='%c'\n",
5403                        end_trigger ? end_trigger : 'X');
5404        debug_enter();
5405
5406        initialize_context(&ctx);
5407
5408        /* If very first arg is "" or '', ctx.word.data may end up NULL.
5409         * Preventing this:
5410         */
5411        ctx.word.data = xzalloc(1); /* start as "", not as NULL */
5412
5413        /* We used to separate words on $IFS here. This was wrong.
5414         * $IFS is used only for word splitting when $var is expanded,
5415         * here we should use blank chars as separators, not $IFS
5416         */
5417
5418        heredoc_cnt = 0;
5419        while (1) {
5420                const char *is_blank;
5421                const char *is_special;
5422                int ch;
5423                int next;
5424                int redir_fd;
5425                redir_type redir_style;
5426
5427                ch = i_getch(input);
5428                debug_printf_parse(": ch=%c (%d) escape=%d\n",
5429                                ch, ch, !!(ctx.word.o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
5430                if (ch == EOF) {
5431                        struct pipe *pi;
5432
5433                        if (heredoc_cnt) {
5434                                syntax_error_unterm_str("here document");
5435                                goto parse_error_exitcode1;
5436                        }
5437                        if (end_trigger == ')') {
5438                                syntax_error_unterm_ch('(');
5439                                goto parse_error_exitcode1;
5440                        }
5441                        if (end_trigger == '}') {
5442                                syntax_error_unterm_ch('{');
5443                                goto parse_error_exitcode1;
5444                        }
5445
5446                        if (done_word(&ctx)) {
5447                                goto parse_error_exitcode1;
5448                        }
5449                        o_free_and_set_NULL(&ctx.word);
5450                        done_pipe(&ctx, PIPE_SEQ);
5451                        pi = ctx.list_head;
5452                        /* If we got nothing... */
5453                        /* (this makes bare "&" cmd a no-op.
5454                         * bash says: "syntax error near unexpected token '&'") */
5455                        if (pi->num_cmds == 0
5456                        IF_HAS_KEYWORDS(&& pi->res_word == RES_NONE)
5457                        ) {
5458                                free_pipe_list(pi);
5459                                pi = NULL;
5460                        }
5461#if !BB_MMU
5462                        debug_printf_parse("as_string1 '%s'\n", ctx.as_string.data);
5463                        if (pstring)
5464                                *pstring = ctx.as_string.data;
5465                        else
5466                                o_free(&ctx.as_string);
5467#endif
5468                        // heredoc_cnt must be 0 here anyway
5469                        //if (heredoc_cnt_ptr)
5470                        //      *heredoc_cnt_ptr = heredoc_cnt;
5471                        debug_leave();
5472                        debug_printf_heredoc("parse_stream return heredoc_cnt:%d\n", heredoc_cnt);
5473                        debug_printf_parse("parse_stream return %p\n", pi);
5474                        return pi;
5475                }
5476
5477                /* Handle "'" and "\" first, as they won't play nice with
5478                 * i_peek_and_eat_bkslash_nl() anyway:
5479                 *   echo z\\
5480                 * and
5481                 *   echo '\
5482                 *   '
5483                 * would break.
5484                 */
5485                if (ch == '\\') {
5486                        ch = i_getch(input);
5487                        if (ch == '\n')
5488                                continue; /* drop \<newline>, get next char */
5489                        nommu_addchr(&ctx.as_string, '\\');
5490                        if (ch == SPECIAL_VAR_SYMBOL) {
5491                                nommu_addchr(&ctx.as_string, ch);
5492                                /* Convert \^C to corresponding special variable reference */
5493                                goto case_SPECIAL_VAR_SYMBOL;
5494                        }
5495                        o_addchr(&ctx.word, '\\');
5496                        if (ch == EOF) {
5497                                /* Testcase: eval 'echo Ok\' */
5498                                /* bash-4.3.43 was removing backslash,
5499                                 * but 4.4.19 retains it, most other shells too
5500                                 */
5501                                continue; /* get next char */
5502                        }
5503                        /* Example: echo Hello \2>file
5504                         * we need to know that word 2 is quoted
5505                         */
5506                        ctx.word.has_quoted_part = 1;
5507                        nommu_addchr(&ctx.as_string, ch);
5508                        o_addchr(&ctx.word, ch);
5509                        continue; /* get next char */
5510                }
5511                nommu_addchr(&ctx.as_string, ch);
5512                if (ch == '\'') {
5513                        ctx.word.has_quoted_part = 1;
5514                        next = i_getch(input);
5515                        if (next == '\'' && !ctx.pending_redirect)
5516                                goto insert_empty_quoted_str_marker;
5517
5518                        ch = next;
5519                        while (1) {
5520                                if (ch == EOF) {
5521                                        syntax_error_unterm_ch('\'');
5522                                        goto parse_error_exitcode1;
5523                                }
5524                                nommu_addchr(&ctx.as_string, ch);
5525                                if (ch == '\'')
5526                                        break;
5527                                if (ch == SPECIAL_VAR_SYMBOL) {
5528                                        /* Convert raw ^C to corresponding special variable reference */
5529                                        o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5530                                        o_addchr(&ctx.word, SPECIAL_VAR_QUOTED_SVS);
5531                                }
5532                                o_addqchr(&ctx.word, ch);
5533                                ch = i_getch(input);
5534                        }
5535                        continue; /* get next char */
5536                }
5537
5538                next = '\0';
5539                if (ch != '\n')
5540                        next = i_peek_and_eat_bkslash_nl(input);
5541
5542                is_special = "{}<>&|();#" /* special outside of "str" */
5543                                "$\"" IF_HUSH_TICK("`") /* always special */
5544                                SPECIAL_VAR_SYMBOL_STR;
5545#if defined(CMD_TEST2_SINGLEWORD_NOGLOB)
5546                if (ctx.command->cmd_type == CMD_TEST2_SINGLEWORD_NOGLOB) {
5547                        /* In [[ ]], {}<>&|() are not special */
5548                        is_special += 8;
5549                } else
5550#endif
5551                /* Are { and } special here? */
5552                if (ctx.command->argv /* word [word]{... - non-special */
5553                 || ctx.word.length       /* word{... - non-special */
5554                 || ctx.word.has_quoted_part     /* ""{... - non-special */
5555                 || (next != ';'             /* }; - special */
5556                    && next != ')'           /* }) - special */
5557                    && next != '('           /* {( - special */
5558                    && next != '&'           /* }& and }&& ... - special */
5559                    && next != '|'           /* }|| ... - special */
5560                    && !strchr(defifs, next) /* {word - non-special */
5561                    )
5562                ) {
5563                        /* They are not special, skip "{}" */
5564                        is_special += 2;
5565                }
5566                is_special = strchr(is_special, ch);
5567                is_blank = strchr(defifs, ch);
5568
5569                if (!is_special && !is_blank) { /* ordinary char */
5570 ordinary_char:
5571                        o_addQchr(&ctx.word, ch);
5572                        if ((ctx.is_assignment == MAYBE_ASSIGNMENT
5573                            || ctx.is_assignment == WORD_IS_KEYWORD)
5574                         && ch == '='
5575                         && endofname(ctx.word.data)[0] == '='
5576                        ) {
5577                                ctx.is_assignment = DEFINITELY_ASSIGNMENT;
5578                                debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
5579                        }
5580                        continue;
5581                }
5582
5583                if (is_blank) {
5584#if ENABLE_HUSH_LINENO_VAR
5585/* Case:
5586 * "while ...; do<whitespace><newline>
5587 *      cmd ..."
5588 * would think that "cmd" starts in <whitespace> -
5589 * i.e., at the previous line.
5590 * We need to skip all whitespace before newlines.
5591 */
5592                        while (ch != '\n') {
5593                                next = i_peek(input);
5594                                if (next != ' ' && next != '\t' && next != '\n')
5595                                        break; /* next char is not ws */
5596                                ch = i_getch(input);
5597                        }
5598                        /* ch == last eaten whitespace char */
5599#endif
5600                        if (done_word(&ctx)) {
5601                                goto parse_error_exitcode1;
5602                        }
5603                        if (ch == '\n') {
5604                                /* Is this a case when newline is simply ignored?
5605                                 * Some examples:
5606                                 * "cmd | <newline> cmd ..."
5607                                 * "case ... in <newline> word) ..."
5608                                 */
5609                                if (IS_NULL_CMD(ctx.command)
5610                                 && ctx.word.length == 0
5611                                 && !ctx.word.has_quoted_part
5612                                 && heredoc_cnt == 0
5613                                ) {
5614                                        /* This newline can be ignored. But...
5615                                         * Without check #1, interactive shell
5616                                         * ignores even bare <newline>,
5617                                         * and shows the continuation prompt:
5618                                         * ps1_prompt$ <enter>
5619                                         * ps2> _   <=== wrong, should be ps1
5620                                         * Without check #2, "cmd & <newline>"
5621                                         * is similarly mistreated.
5622                                         * (BTW, this makes "cmd & cmd"
5623                                         * and "cmd && cmd" non-orthogonal.
5624                                         * Really, ask yourself, why
5625                                         * "cmd && <newline>" doesn't start
5626                                         * cmd but waits for more input?
5627                                         * The only reason is that it might be
5628                                         * a "cmd1 && <nl> cmd2 &" construct,
5629                                         * cmd1 may need to run in BG).
5630                                         */
5631                                        struct pipe *pi = ctx.list_head;
5632                                        if (pi->num_cmds != 0       /* check #1 */
5633                                         && pi->followup != PIPE_BG /* check #2 */
5634                                        ) {
5635                                                continue;
5636                                        }
5637                                }
5638                                /* Treat newline as a command separator. */
5639                                done_pipe(&ctx, PIPE_SEQ);
5640                                debug_printf_heredoc("heredoc_cnt:%d\n", heredoc_cnt);
5641                                if (heredoc_cnt) {
5642                                        heredoc_cnt = fetch_heredocs(&ctx.as_string, ctx.list_head, heredoc_cnt, input);
5643                                        if (heredoc_cnt != 0)
5644                                                goto parse_error_exitcode1;
5645                                }
5646                                ctx.is_assignment = MAYBE_ASSIGNMENT;
5647                                debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
5648                                ch = ';';
5649                                /* note: if (is_blank) continue;
5650                                 * will still trigger for us */
5651                        }
5652                }
5653
5654                /* "cmd}" or "cmd }..." without semicolon or &:
5655                 * } is an ordinary char in this case, even inside { cmd; }
5656                 * Pathological example: { ""}; } should exec "}" cmd
5657                 */
5658                if (ch == '}') {
5659                        if (ctx.word.length != 0 /* word} */
5660                         || ctx.word.has_quoted_part    /* ""} */
5661                        ) {
5662                                goto ordinary_char;
5663                        }
5664                        if (!IS_NULL_CMD(ctx.command)) { /* cmd } */
5665                                /* Generally, there should be semicolon: "cmd; }"
5666                                 * However, bash allows to omit it if "cmd" is
5667                                 * a group. Examples:
5668                                 * { { echo 1; } }
5669                                 * {(echo 1)}
5670                                 * { echo 0 >&2 | { echo 1; } }
5671                                 * { while false; do :; done }
5672                                 * { case a in b) ;; esac }
5673                                 */
5674                                if (ctx.command->group)
5675                                        goto term_group;
5676                                goto ordinary_char;
5677                        }
5678                        if (!IS_NULL_PIPE(ctx.pipe)) /* cmd | } */
5679                                /* Can't be an end of {cmd}, skip the check */
5680                                goto skip_end_trigger;
5681                        /* else: } does terminate a group */
5682                }
5683 term_group:
5684                if (end_trigger && end_trigger == ch
5685                 && (ch != ';' || heredoc_cnt == 0)
5686#if ENABLE_HUSH_CASE
5687                 && (ch != ')'
5688                    || ctx.ctx_res_w != RES_MATCH
5689                    || (!ctx.word.has_quoted_part && strcmp(ctx.word.data, "esac") == 0)
5690                    )
5691#endif
5692                ) {
5693                        if (done_word(&ctx)) {
5694                                goto parse_error_exitcode1;
5695                        }
5696                        done_pipe(&ctx, PIPE_SEQ);
5697                        ctx.is_assignment = MAYBE_ASSIGNMENT;
5698                        debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
5699                        /* Do we sit outside of any if's, loops or case's? */
5700                        if (!HAS_KEYWORDS
5701                        IF_HAS_KEYWORDS(|| (ctx.ctx_res_w == RES_NONE && ctx.old_flag == 0))
5702                        ) {
5703                                o_free_and_set_NULL(&ctx.word);
5704#if !BB_MMU
5705                                debug_printf_parse("as_string2 '%s'\n", ctx.as_string.data);
5706                                if (pstring)
5707                                        *pstring = ctx.as_string.data;
5708                                else
5709                                        o_free(&ctx.as_string);
5710#endif
5711                                if (ch != ';' && IS_NULL_PIPE(ctx.list_head)) {
5712                                        /* Example: bare "{ }", "()" */
5713                                        G.last_exitcode = 2; /* bash compat */
5714                                        syntax_error_unexpected_ch(ch);
5715                                        goto parse_error;
5716                                }
5717                                if (heredoc_cnt_ptr)
5718                                        *heredoc_cnt_ptr = heredoc_cnt;
5719                                debug_printf_heredoc("parse_stream return heredoc_cnt:%d\n", heredoc_cnt);
5720                                debug_printf_parse("parse_stream return %p: "
5721                                                "end_trigger char found\n",
5722                                                ctx.list_head);
5723                                debug_leave();
5724                                return ctx.list_head;
5725                        }
5726                }
5727
5728                if (is_blank)
5729                        continue;
5730
5731                /* Catch <, > before deciding whether this word is
5732                 * an assignment. a=1 2>z b=2: b=2 is still assignment */
5733                switch (ch) {
5734                case '>':
5735                        redir_fd = redirect_opt_num(&ctx.word);
5736                        if (done_word(&ctx)) {
5737                                goto parse_error_exitcode1;
5738                        }
5739                        redir_style = REDIRECT_OVERWRITE;
5740                        if (next == '>') {
5741                                redir_style = REDIRECT_APPEND;
5742                                ch = i_getch(input);
5743                                nommu_addchr(&ctx.as_string, ch);
5744                        }
5745#if 0
5746                        else if (next == '(') {
5747                                syntax_error(">(process) not supported");
5748                                goto parse_error_exitcode1;
5749                        }
5750#endif
5751                        if (parse_redirect(&ctx, redir_fd, redir_style, input))
5752                                goto parse_error_exitcode1;
5753                        continue; /* get next char */
5754                case '<':
5755                        redir_fd = redirect_opt_num(&ctx.word);
5756                        if (done_word(&ctx)) {
5757                                goto parse_error_exitcode1;
5758                        }
5759                        redir_style = REDIRECT_INPUT;
5760                        if (next == '<') {
5761                                redir_style = REDIRECT_HEREDOC;
5762                                heredoc_cnt++;
5763                                debug_printf_heredoc("++heredoc_cnt=%d\n", heredoc_cnt);
5764                                ch = i_getch(input);
5765                                nommu_addchr(&ctx.as_string, ch);
5766                        } else if (next == '>') {
5767                                redir_style = REDIRECT_IO;
5768                                ch = i_getch(input);
5769                                nommu_addchr(&ctx.as_string, ch);
5770                        }
5771#if 0
5772                        else if (next == '(') {
5773                                syntax_error("<(process) not supported");
5774                                goto parse_error_exitcode1;
5775                        }
5776#endif
5777                        if (parse_redirect(&ctx, redir_fd, redir_style, input))
5778                                goto parse_error_exitcode1;
5779                        continue; /* get next char */
5780                case '#':
5781                        if (ctx.word.length == 0 && !ctx.word.has_quoted_part) {
5782                                /* skip "#comment" */
5783                                /* note: we do not add it to &ctx.as_string */
5784/* TODO: in bash:
5785 * comment inside $() goes to the next \n, even inside quoted string (!):
5786 * cmd "$(cmd2 #comment)" - syntax error
5787 * cmd "`cmd2 #comment`" - ok
5788 * We accept both (comment ends where command subst ends, in both cases).
5789 */
5790                                while (1) {
5791                                        ch = i_peek(input);
5792                                        if (ch == '\n') {
5793                                                nommu_addchr(&ctx.as_string, '\n');
5794                                                break;
5795                                        }
5796                                        ch = i_getch(input);
5797                                        if (ch == EOF)
5798                                                break;
5799                                }
5800                                continue; /* get next char */
5801                        }
5802                        break;
5803                }
5804 skip_end_trigger:
5805
5806                if (ctx.is_assignment == MAYBE_ASSIGNMENT
5807                 /* check that we are not in word in "a=1 2>word b=1": */
5808                 && !ctx.pending_redirect
5809                ) {
5810                        /* ch is a special char and thus this word
5811                         * cannot be an assignment */
5812                        ctx.is_assignment = NOT_ASSIGNMENT;
5813                        debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
5814                }
5815
5816                /* Note: nommu_addchr(&ctx.as_string, ch) is already done */
5817
5818                switch (ch) {
5819                case_SPECIAL_VAR_SYMBOL:
5820                case SPECIAL_VAR_SYMBOL:
5821                        /* Convert raw ^C to corresponding special variable reference */
5822                        o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5823                        o_addchr(&ctx.word, SPECIAL_VAR_QUOTED_SVS);
5824                        /* fall through */
5825                case '#':
5826                        /* non-comment #: "echo a#b" etc */
5827                        o_addchr(&ctx.word, ch);
5828                        continue; /* get next char */
5829                case '$':
5830                        if (parse_dollar_squote(&ctx.as_string, &ctx.word, input))
5831                                continue; /* get next char */
5832                        if (!parse_dollar(&ctx.as_string, &ctx.word, input, /*quote_mask:*/ 0)) {
5833                                debug_printf_parse("parse_stream parse error: "
5834                                        "parse_dollar returned 0 (error)\n");
5835                                goto parse_error_exitcode1;
5836                        }
5837                        continue; /* get next char */
5838                case '"':
5839                        ctx.word.has_quoted_part = 1;
5840                        if (next == '"' && !ctx.pending_redirect) {
5841                                i_getch(input); /* eat second " */
5842 insert_empty_quoted_str_marker:
5843                                nommu_addchr(&ctx.as_string, next);
5844                                o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5845                                o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5846                                continue; /* get next char */
5847                        }
5848                        if (ctx.is_assignment == NOT_ASSIGNMENT)
5849                                ctx.word.o_expflags |= EXP_FLAG_ESC_GLOB_CHARS;
5850                        if (!encode_string(&ctx.as_string, &ctx.word, input, '"'))
5851                                goto parse_error_exitcode1;
5852                        ctx.word.o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS;
5853                        continue; /* get next char */
5854#if ENABLE_HUSH_TICK
5855                case '`': {
5856                        USE_FOR_NOMMU(unsigned pos;)
5857
5858                        o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5859                        o_addchr(&ctx.word, '`');
5860                        USE_FOR_NOMMU(pos = ctx.word.length;)
5861                        if (!add_till_backquote(&ctx.word, input, /*in_dquote:*/ 0))
5862                                goto parse_error_exitcode1;
5863# if !BB_MMU
5864                        o_addstr(&ctx.as_string, ctx.word.data + pos);
5865                        o_addchr(&ctx.as_string, '`');
5866# endif
5867                        o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5868                        //debug_printf_subst("SUBST RES3 '%s'\n", ctx.word.data + pos);
5869                        continue; /* get next char */
5870                }
5871#endif
5872                case ';':
5873#if ENABLE_HUSH_CASE
5874 case_semi:
5875#endif
5876                        if (done_word(&ctx)) {
5877                                goto parse_error_exitcode1;
5878                        }
5879                        done_pipe(&ctx, PIPE_SEQ);
5880#if ENABLE_HUSH_CASE
5881                        /* Eat multiple semicolons, detect
5882                         * whether it means something special */
5883                        while (1) {
5884                                ch = i_peek_and_eat_bkslash_nl(input);
5885                                if (ch != ';')
5886                                        break;
5887                                ch = i_getch(input);
5888                                nommu_addchr(&ctx.as_string, ch);
5889                                if (ctx.ctx_res_w == RES_CASE_BODY) {
5890                                        ctx.ctx_dsemicolon = 1;
5891                                        ctx.ctx_res_w = RES_MATCH;
5892                                        break;
5893                                }
5894                        }
5895#endif
5896 new_cmd:
5897                        /* We just finished a cmd. New one may start
5898                         * with an assignment */
5899                        ctx.is_assignment = MAYBE_ASSIGNMENT;
5900                        debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
5901                        continue; /* get next char */
5902                case '&':
5903                        if (done_word(&ctx)) {
5904                                goto parse_error_exitcode1;
5905                        }
5906                        if (next == '&') {
5907                                ch = i_getch(input);
5908                                nommu_addchr(&ctx.as_string, ch);
5909                                done_pipe(&ctx, PIPE_AND);
5910                        } else {
5911                                done_pipe(&ctx, PIPE_BG);
5912                        }
5913                        goto new_cmd;
5914                case '|':
5915                        if (done_word(&ctx)) {
5916                                goto parse_error_exitcode1;
5917                        }
5918#if ENABLE_HUSH_CASE
5919                        if (ctx.ctx_res_w == RES_MATCH)
5920                                break; /* we are in case's "word | word)" */
5921#endif
5922                        if (next == '|') { /* || */
5923                                ch = i_getch(input);
5924                                nommu_addchr(&ctx.as_string, ch);
5925                                done_pipe(&ctx, PIPE_OR);
5926                        } else {
5927                                /* we could pick up a file descriptor choice here
5928                                 * with redirect_opt_num(), but bash doesn't do it.
5929                                 * "echo foo 2| cat" yields "foo 2". */
5930                                done_command(&ctx);
5931                        }
5932                        goto new_cmd;
5933                case '(':
5934#if ENABLE_HUSH_CASE
5935                        /* "case... in [(]word)..." - skip '(' */
5936                        if (ctx.ctx_res_w == RES_MATCH
5937                         && ctx.command->argv == NULL /* not (word|(... */
5938                         && ctx.word.length == 0 /* not word(... */
5939                         && ctx.word.has_quoted_part == 0 /* not ""(... */
5940                        ) {
5941                                continue; /* get next char */
5942                        }
5943#endif
5944                        /* fall through */
5945                case '{': {
5946                        int n = parse_group(&ctx, input, ch);
5947                        if (n < 0) {
5948                                goto parse_error_exitcode1;
5949                        }
5950                        debug_printf_heredoc("parse_group done, needs heredocs:%d\n", n);
5951                        heredoc_cnt += n;
5952                        goto new_cmd;
5953                }
5954                case ')':
5955#if ENABLE_HUSH_CASE
5956                        if (ctx.ctx_res_w == RES_MATCH)
5957                                goto case_semi;
5958#endif
5959                case '}':
5960                        /* proper use of this character is caught by end_trigger:
5961                         * if we see {, we call parse_group(..., end_trigger='}')
5962                         * and it will match } earlier (not here). */
5963                        G.last_exitcode = 2;
5964                        syntax_error_unexpected_ch(ch);
5965                        goto parse_error;
5966                default:
5967                        if (HUSH_DEBUG)
5968                                bb_error_msg_and_die("BUG: unexpected %c", ch);
5969                }
5970        } /* while (1) */
5971
5972 parse_error_exitcode1:
5973        G.last_exitcode = 1;
5974 parse_error:
5975        {
5976                struct parse_context *pctx;
5977                IF_HAS_KEYWORDS(struct parse_context *p2;)
5978
5979                /* Clean up allocated tree.
5980                 * Sample for finding leaks on syntax error recovery path.
5981                 * Run it from interactive shell, watch pmap `pidof hush`.
5982                 * while if false; then false; fi; do break; fi
5983                 * Samples to catch leaks at execution:
5984                 * while if (true | { true;}); then echo ok; fi; do break; done
5985                 * while if (true | { true;}); then echo ok; fi; do (if echo ok; break; then :; fi) | cat; break; done
5986                 */
5987                pctx = &ctx;
5988                do {
5989                        /* Update pipe/command counts,
5990                         * otherwise freeing may miss some */
5991                        done_pipe(pctx, PIPE_SEQ);
5992                        debug_printf_clean("freeing list %p from ctx %p\n",
5993                                        pctx->list_head, pctx);
5994                        debug_print_tree(pctx->list_head, 0);
5995                        free_pipe_list(pctx->list_head);
5996                        debug_printf_clean("freed list %p\n", pctx->list_head);
5997#if !BB_MMU
5998                        o_free(&pctx->as_string);
5999#endif
6000                        IF_HAS_KEYWORDS(p2 = pctx->stack;)
6001                        if (pctx != &ctx) {
6002                                free(pctx);
6003                        }
6004                        IF_HAS_KEYWORDS(pctx = p2;)
6005                } while (HAS_KEYWORDS && pctx);
6006
6007                o_free(&ctx.word);
6008#if !BB_MMU
6009                if (pstring)
6010                        *pstring = NULL;
6011#endif
6012                debug_leave();
6013                return ERR_PTR;
6014        }
6015}
6016
6017
6018/*** Execution routines ***/
6019
6020/* Expansion can recurse, need forward decls: */
6021#if !BASH_PATTERN_SUBST && !ENABLE_HUSH_CASE
6022#define expand_string_to_string(str, EXP_flags, do_unbackslash) \
6023        expand_string_to_string(str)
6024#endif
6025static char *expand_string_to_string(const char *str, int EXP_flags, int do_unbackslash);
6026#if ENABLE_HUSH_TICK
6027static int process_command_subs(o_string *dest, const char *s);
6028#endif
6029static int expand_vars_to_list(o_string *output, int n, char *arg);
6030
6031/* expand_strvec_to_strvec() takes a list of strings, expands
6032 * all variable references within and returns a pointer to
6033 * a list of expanded strings, possibly with larger number
6034 * of strings. (Think VAR="a b"; echo $VAR).
6035 * This new list is allocated as a single malloc block.
6036 * NULL-terminated list of char* pointers is at the beginning of it,
6037 * followed by strings themselves.
6038 * Caller can deallocate entire list by single free(list). */
6039
6040/* A horde of its helpers come first: */
6041
6042static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len)
6043{
6044        while (--len >= 0) {
6045                char c = *str++;
6046
6047#if ENABLE_HUSH_BRACE_EXPANSION
6048                if (c == '{' || c == '}') {
6049                        /* { -> \{, } -> \} */
6050                        o_addchr(o, '\\');
6051                        /* And now we want to add { or } and continue:
6052                         *  o_addchr(o, c);
6053                         *  continue;
6054                         * luckily, just falling through achieves this.
6055                         */
6056                }
6057#endif
6058                o_addchr(o, c);
6059                if (c == '\\') {
6060                        /* \z -> \\\z; \<eol> -> \\<eol> */
6061                        o_addchr(o, '\\');
6062                        if (len) {
6063                                len--;
6064                                o_addchr(o, '\\');
6065                                o_addchr(o, *str++);
6066                        }
6067                }
6068        }
6069}
6070
6071/* Store given string, finalizing the word and starting new one whenever
6072 * we encounter IFS char(s). This is used for expanding variable values.
6073 * End-of-string does NOT finalize word: think about 'echo -$VAR-'.
6074 * Return in output->ended_in_ifs:
6075 * 1 - ended with IFS char, else 0 (this includes case of empty str).
6076 */
6077static int expand_on_ifs(o_string *output, int n, const char *str)
6078{
6079        int last_is_ifs = 0;
6080
6081        while (1) {
6082                int word_len;
6083
6084                if (!*str)  /* EOL - do not finalize word */
6085                        break;
6086                word_len = strcspn(str, G.ifs);
6087                if (word_len) {
6088                        /* We have WORD_LEN leading non-IFS chars */
6089                        if (!(output->o_expflags & EXP_FLAG_GLOB)) {
6090                                o_addblock(output, str, word_len);
6091                        } else {
6092                                /* Protect backslashes against globbing up :)
6093                                 * Example: "v='\*'; echo b$v" prints "b\*"
6094                                 * (and does not try to glob on "*")
6095                                 */
6096                                o_addblock_duplicate_backslash(output, str, word_len);
6097                                /*/ Why can't we do it easier? */
6098                                /*o_addblock(output, str, word_len); - WRONG: "v='\*'; echo Z$v" prints "Z*" instead of "Z\*" */
6099                                /*o_addqblock(output, str, word_len); - WRONG: "v='*'; echo Z$v" prints "Z*" instead of Z* files */
6100                        }
6101                        last_is_ifs = 0;
6102                        str += word_len;
6103                        if (!*str)  /* EOL - do not finalize word */
6104                                break;
6105                }
6106
6107                /* We know str here points to at least one IFS char */
6108                last_is_ifs = 1;
6109                str += strspn(str, G.ifs_whitespace); /* skip IFS whitespace chars */
6110                if (!*str)  /* EOL - do not finalize word */
6111                        break;
6112
6113                if (G.ifs_whitespace != G.ifs /* usually false ($IFS is usually all whitespace), */
6114                 && strchr(G.ifs, *str)       /* the second check would fail */
6115                ) {
6116                        /* This is a non-whitespace $IFS char */
6117                        /* Skip it and IFS whitespace chars, start new word */
6118                        str++;
6119                        str += strspn(str, G.ifs_whitespace);
6120                        goto new_word;
6121                }
6122
6123                /* Start new word... but not always! */
6124                /* Case "v=' a'; echo ''$v": we do need to finalize empty word: */
6125                if (output->has_quoted_part
6126                /*
6127                 * Case "v=' a'; echo $v":
6128                 * here nothing precedes the space in $v expansion,
6129                 * therefore we should not finish the word
6130                 * (IOW: if there *is* word to finalize, only then do it):
6131                 * It's okay if this accesses the byte before first argv[]:
6132                 * past call to o_save_ptr() cleared it to zero byte
6133                 * (grep for -prev-ifs-check-).
6134                 */
6135                 || output->data[output->length - 1]
6136                ) {
6137 new_word:
6138                        o_addchr(output, '\0');
6139                        debug_print_list("expand_on_ifs", output, n);
6140                        n = o_save_ptr(output, n);
6141                }
6142        }
6143
6144        output->ended_in_ifs = last_is_ifs;
6145        debug_print_list("expand_on_ifs[1]", output, n);
6146        return n;
6147}
6148
6149/* Helper to expand $((...)) and heredoc body. These act as if
6150 * they are in double quotes, with the exception that they are not :).
6151 * Just the rules are similar: "expand only $var and `cmd`"
6152 *
6153 * Returns malloced string.
6154 * As an optimization, we return NULL if expansion is not needed.
6155 */
6156static char *encode_then_expand_string(const char *str)
6157{
6158        char *exp_str;
6159        struct in_str input;
6160        o_string dest = NULL_O_STRING;
6161        const char *cp;
6162
6163        cp = str;
6164        for (;;) {
6165                if (!*cp) return NULL; /* string has no special chars */
6166                if (*cp == '$') break;
6167                if (*cp == '\\') break;
6168#if ENABLE_HUSH_TICK
6169                if (*cp == '`') break;
6170#endif
6171                cp++;
6172        }
6173
6174        /* We need to expand. Example:
6175         * echo $(($a + `echo 1`)) $((1 + $((2)) ))
6176         */
6177        setup_string_in_str(&input, str);
6178        encode_string(NULL, &dest, &input, EOF);
6179//TODO: error check (encode_string returns 0 on error)?
6180        //bb_error_msg("'%s' -> '%s'", str, dest.data);
6181        exp_str = expand_string_to_string(dest.data,
6182                        EXP_FLAG_ESC_GLOB_CHARS,
6183                        /*unbackslash:*/ 1
6184        );
6185        //bb_error_msg("'%s' -> '%s'", dest.data, exp_str);
6186        o_free(&dest);
6187        return exp_str;
6188}
6189
6190static const char *first_special_char_in_vararg(const char *cp)
6191{
6192        for (;;) {
6193                if (!*cp) return NULL; /* string has no special chars */
6194                if (*cp == '$') return cp;
6195                if (*cp == '\\') return cp;
6196                if (*cp == '\'') return cp;
6197                if (*cp == '"') return cp;
6198#if ENABLE_HUSH_TICK
6199                if (*cp == '`') return cp;
6200#endif
6201                /* dquoted "${x:+ARG}" should not glob, therefore
6202                 * '*' et al require some non-literal processing: */
6203                if (*cp == '*') return cp;
6204                if (*cp == '?') return cp;
6205                if (*cp == '[') return cp;
6206                cp++;
6207        }
6208}
6209
6210/* Expanding ARG in ${var#ARG}, ${var%ARG}, or ${var/ARG/ARG}.
6211 * These can contain single- and double-quoted strings,
6212 * and treated as if the ARG string is initially unquoted. IOW:
6213 * ${var#ARG} and "${var#ARG}" treat ARG the same (ARG can even be
6214 * a dquoted string: "${var#"zz"}"), the difference only comes later
6215 * (word splitting and globbing of the ${var...} result).
6216 */
6217#if !BASH_PATTERN_SUBST
6218#define encode_then_expand_vararg(str, handle_squotes, do_unbackslash) \
6219        encode_then_expand_vararg(str, handle_squotes)
6220#endif
6221static char *encode_then_expand_vararg(const char *str, int handle_squotes, int do_unbackslash)
6222{
6223#if !BASH_PATTERN_SUBST && ENABLE_HUSH_CASE
6224        const int do_unbackslash = 0;
6225#endif
6226        char *exp_str;
6227        struct in_str input;
6228        o_string dest = NULL_O_STRING;
6229
6230        if (!first_special_char_in_vararg(str)) {
6231                /* string has no special chars */
6232                return NULL;
6233        }
6234
6235        setup_string_in_str(&input, str);
6236        dest.data = xzalloc(1); /* start as "", not as NULL */
6237        exp_str = NULL;
6238
6239        for (;;) {
6240                int ch;
6241
6242                ch = i_getch(&input);
6243                debug_printf_parse("%s: ch=%c (%d) escape=%d\n",
6244                                __func__, ch, ch, !!dest.o_expflags);
6245
6246                if (!dest.o_expflags) {
6247                        if (ch == EOF)
6248                                break;
6249                        if (handle_squotes && ch == '\'') {
6250                                if (!add_till_single_quote_dquoted(&dest, &input))
6251                                        goto ret; /* error */
6252                                continue;
6253                        }
6254                }
6255                if (ch == EOF) {
6256                        syntax_error_unterm_ch('"');
6257                        goto ret; /* error */
6258                }
6259                if (ch == '"') {
6260                        dest.o_expflags ^= EXP_FLAG_ESC_GLOB_CHARS;
6261                        continue;
6262                }
6263                if (ch == '\\') {
6264                        ch = i_getch(&input);
6265                        if (ch == EOF) {
6266//example? error message?       syntax_error_unterm_ch('"');
6267                                debug_printf_parse("%s: error: \\<eof>\n", __func__);
6268                                goto ret;
6269                        }
6270                        o_addqchr(&dest, ch);
6271                        continue;
6272                }
6273                if (ch == '$') {
6274                        if (parse_dollar_squote(NULL, &dest, &input))
6275                                continue;
6276                        if (!parse_dollar(NULL, &dest, &input, /*quote_mask:*/ 0x80)) {
6277                                debug_printf_parse("%s: error: parse_dollar returned 0 (error)\n", __func__);
6278                                goto ret;
6279                        }
6280                        continue;
6281                }
6282#if ENABLE_HUSH_TICK
6283                if (ch == '`') {
6284                        //unsigned pos = dest->length;
6285                        o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6286                        o_addchr(&dest, 0x80 | '`');
6287                        if (!add_till_backquote(&dest, &input,
6288                                        /*in_dquote:*/ dest.o_expflags /* nonzero if EXP_FLAG_ESC_GLOB_CHARS set */
6289                                )
6290                        ) {
6291                                goto ret; /* error */
6292                        }
6293                        o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6294                        //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos);
6295                        continue;
6296                }
6297#endif
6298                o_addQchr(&dest, ch);
6299        } /* for (;;) */
6300
6301        debug_printf_parse("encode: '%s' -> '%s'\n", str, dest.data);
6302        exp_str = expand_string_to_string(dest.data,
6303                        do_unbackslash ? EXP_FLAG_ESC_GLOB_CHARS : 0,
6304                        do_unbackslash
6305        );
6306 ret:
6307        debug_printf_parse("expand: '%s' -> '%s'\n", dest.data, exp_str);
6308        o_free(&dest);
6309        return exp_str;
6310}
6311
6312/* Expanding ARG in ${var+ARG}, ${var-ARG}
6313 */
6314static NOINLINE int encode_then_append_var_plusminus(o_string *output, int n,
6315                char *str, int dquoted)
6316{
6317        struct in_str input;
6318        o_string dest = NULL_O_STRING;
6319
6320        if (!first_special_char_in_vararg(str)
6321         && '\0' == str[strcspn(str, G.ifs)]
6322        ) {
6323                /* string has no special chars
6324                 * && string has no $IFS chars
6325                 */
6326                if (dquoted) {
6327                        /* Prints 1 (quoted expansion is a "" word, not nothing):
6328                         * set -- "${notexist-}"; echo $#
6329                         */
6330                        output->has_quoted_part = 1;
6331                }
6332                return expand_vars_to_list(output, n, str);
6333        }
6334
6335        setup_string_in_str(&input, str);
6336
6337        for (;;) {
6338                int ch;
6339
6340                ch = i_getch(&input);
6341                debug_printf_parse("%s: ch=%c (%d) escape=%x\n",
6342                                __func__, ch, ch, dest.o_expflags);
6343
6344                if (!dest.o_expflags) {
6345                        if (ch == EOF)
6346                                break;
6347                        if (!dquoted && strchr(G.ifs, ch)) {
6348                                /* PREFIX${x:d${e}f ...} and we met space: expand "d${e}f" and start new word.
6349                                 * do not assume we are at the start of the word (PREFIX above).
6350                                 */
6351                                if (dest.data) {
6352                                        n = expand_vars_to_list(output, n, dest.data);
6353                                        o_free_and_set_NULL(&dest);
6354                                        o_addchr(output, '\0');
6355                                        n = o_save_ptr(output, n); /* create next word */
6356                                } else
6357                                if (output->length != o_get_last_ptr(output, n)
6358                                 || output->has_quoted_part
6359                                ) {
6360                                        /* For these cases:
6361                                         * f() { for i; do echo "|$i|"; done; }; x=x
6362                                         * f a${x:+ }b  # 1st condition
6363                                         * |a|
6364                                         * |b|
6365                                         * f ""${x:+ }b  # 2nd condition
6366                                         * ||
6367                                         * |b|
6368                                         */
6369                                        o_addchr(output, '\0');
6370                                        n = o_save_ptr(output, n); /* create next word */
6371                                }
6372                                continue;
6373                        }
6374                        if (!dquoted && ch == '\'') {
6375                                if (!add_till_single_quote_dquoted(&dest, &input))
6376                                        goto ret; /* error */
6377                                o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6378                                o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6379                                continue;
6380                        }
6381                }
6382                if (ch == EOF) {
6383                        syntax_error_unterm_ch('"');
6384                        goto ret; /* error */
6385                }
6386                if (ch == '"') {
6387                        dest.o_expflags ^= EXP_FLAG_ESC_GLOB_CHARS;
6388                        if (dest.o_expflags) {
6389                                o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6390                                o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6391                        }
6392                        continue;
6393                }
6394                if (ch == '\\') {
6395                        ch = i_getch(&input);
6396                        if (ch == EOF) {
6397//example? error message?       syntax_error_unterm_ch('"');
6398                                debug_printf_parse("%s: error: \\<eof>\n", __func__);
6399                                goto ret;
6400                        }
6401                        o_addqchr(&dest, ch);
6402                        continue;
6403                }
6404                if (ch == '$') {
6405                        if (!parse_dollar(NULL, &dest, &input, /*quote_mask:*/ (dest.o_expflags || dquoted) ? 0x80 : 0)) {
6406                                debug_printf_parse("%s: error: parse_dollar returned 0 (error)\n", __func__);
6407                                goto ret;
6408                        }
6409                        continue;
6410                }
6411#if ENABLE_HUSH_TICK
6412                if (ch == '`') {
6413                        //unsigned pos = dest->length;
6414                        o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6415                        o_addchr(&dest, (dest.o_expflags || dquoted) ? 0x80 | '`' : '`');
6416                        if (!add_till_backquote(&dest, &input,
6417                                        /*in_dquote:*/ dest.o_expflags /* nonzero if EXP_FLAG_ESC_GLOB_CHARS set */
6418                                )
6419                        ) {
6420                                goto ret; /* error */
6421                        }
6422                        o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6423                        //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos);
6424                        continue;
6425                }
6426#endif
6427                if (dquoted) {
6428                        /* Always glob-protect if in dquotes:
6429                         * x=x; echo "${x:+/bin/c*}" - prints: /bin/c*
6430                         * x=x; echo "${x:+"/bin/c*"}" - prints: /bin/c*
6431                         */
6432                        o_addqchr(&dest, ch);
6433                } else {
6434                        /* Glob-protect only if char is quoted:
6435                         * x=x; echo ${x:+/bin/c*} - prints many filenames
6436                         * x=x; echo ${x:+"/bin/c*"} - prints: /bin/c*
6437                         */
6438                        o_addQchr(&dest, ch);
6439                }
6440        } /* for (;;) */
6441
6442        if (dest.data) {
6443                n = expand_vars_to_list(output, n, dest.data);
6444        }
6445 ret:
6446        o_free(&dest);
6447        return n;
6448}
6449
6450#if ENABLE_FEATURE_SH_MATH
6451static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p)
6452{
6453        arith_state_t math_state;
6454        arith_t res;
6455        char *exp_str;
6456
6457        math_state.lookupvar = get_local_var_value;
6458        math_state.setvar = set_local_var_from_halves;
6459        //math_state.endofname = endofname;
6460        exp_str = encode_then_expand_string(arg);
6461        res = arith(&math_state, exp_str ? exp_str : arg);
6462        free(exp_str);
6463        if (errmsg_p)
6464                *errmsg_p = math_state.errmsg;
6465        if (math_state.errmsg)
6466                msg_and_die_if_script(math_state.errmsg);
6467        return res;
6468}
6469#endif
6470
6471#if BASH_PATTERN_SUBST
6472/* ${var/[/]pattern[/repl]} helpers */
6473static char *strstr_pattern(char *val, const char *pattern, int *size)
6474{
6475        int first_escaped = (pattern[0] == '\\' && pattern[1]);
6476        /* "first_escaped" trick allows to treat e.g. "\*no_glob_chars"
6477         * as literal too (as it is semi-common, and easy to accomodate
6478         * by just using str + 1).
6479         */
6480        int sz = strcspn(pattern + first_escaped * 2, "*?[\\");
6481        if ((pattern + first_escaped * 2)[sz] == '\0') {
6482                /* Optimization for trivial patterns.
6483                 * Testcase for very slow replace (performs about 22k replaces):
6484                 * x=::::::::::::::::::::::
6485                 * 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}
6486                 * echo "${x//:/|}"
6487                 */
6488                *size = sz + first_escaped;
6489                return strstr(val, pattern + first_escaped);
6490        }
6491
6492        while (1) {
6493                char *end = scan_and_match(val, pattern, SCAN_MOVE_FROM_RIGHT + SCAN_MATCH_LEFT_HALF);
6494                debug_printf_varexp("val:'%s' pattern:'%s' end:'%s'\n", val, pattern, end);
6495                if (end) {
6496                        *size = end - val;
6497                        return val;
6498                }
6499                if (*val == '\0')
6500                        return NULL;
6501                /* Optimization: if "*pat" did not match the start of "string",
6502                 * we know that "tring", "ring" etc will not match too:
6503                 */
6504                if (pattern[0] == '*')
6505                        return NULL;
6506                val++;
6507        }
6508}
6509static char *replace_pattern(char *val, const char *pattern, const char *repl, char exp_op)
6510{
6511        char *result = NULL;
6512        unsigned res_len = 0;
6513        unsigned repl_len = strlen(repl);
6514
6515        /* Null pattern never matches, including if "var" is empty */
6516        if (!pattern[0])
6517                return result; /* NULL, no replaces happened */
6518
6519        while (1) {
6520                int size;
6521                char *s = strstr_pattern(val, pattern, &size);
6522                if (!s)
6523                        break;
6524
6525                result = xrealloc(result, res_len + (s - val) + repl_len + 1);
6526                strcpy(mempcpy(result + res_len, val, s - val), repl);
6527                res_len += (s - val) + repl_len;
6528                debug_printf_varexp("val:'%s' s:'%s' result:'%s'\n", val, s, result);
6529
6530                val = s + size;
6531                if (exp_op == '/')
6532                        break;
6533        }
6534        if (*val && result) {
6535                result = xrealloc(result, res_len + strlen(val) + 1);
6536                strcpy(result + res_len, val);
6537                debug_printf_varexp("val:'%s' result:'%s'\n", val, result);
6538        }
6539        debug_printf_varexp("result:'%s'\n", result);
6540        return result;
6541}
6542#endif /* BASH_PATTERN_SUBST */
6543
6544static int append_str_maybe_ifs_split(o_string *output, int n,
6545                int first_ch, const char *val)
6546{
6547        if (!(first_ch & 0x80)) { /* unquoted $VAR */
6548                debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val,
6549                                !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
6550                if (val && val[0])
6551                        n = expand_on_ifs(output, n, val);
6552        } else { /* quoted "$VAR" */
6553                output->has_quoted_part = 1;
6554                debug_printf_expand("quoted '%s', output->o_escape:%d\n", val,
6555                                !!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
6556                if (val && val[0])
6557                        o_addQstr(output, val);
6558        }
6559        return n;
6560}
6561
6562/* Handle <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct.
6563 */
6564static NOINLINE int expand_one_var(o_string *output, int n,
6565                int first_ch, char *arg, char **pp)
6566{
6567        const char *val;
6568        char *to_be_freed;
6569        char *p;
6570        char *var;
6571        char exp_op;
6572        char exp_save = exp_save; /* for compiler */
6573        char *exp_saveptr; /* points to expansion operator */
6574        char *exp_word = exp_word; /* for compiler */
6575        char arg0;
6576
6577        val = NULL;
6578        to_be_freed = NULL;
6579        p = *pp;
6580        *p = '\0'; /* replace trailing SPECIAL_VAR_SYMBOL */
6581        var = arg;
6582        exp_saveptr = arg[1] ? strchr(VAR_ENCODED_SUBST_OPS, arg[1]) : NULL;
6583        arg0 = arg[0];
6584        arg[0] = (arg0 & 0x7f);
6585        exp_op = 0;
6586
6587        if (arg[0] == '#' && arg[1] /* ${#...} but not ${#} */
6588         && (!exp_saveptr               /* and ( not(${#<op_char>...}) */
6589            || (arg[2] == '\0' && strchr(SPECIAL_VARS_STR, arg[1])) /* or ${#C} "len of $C" ) */
6590            )           /* NB: skipping ^^^specvar check mishandles ${#::2} */
6591        ) {
6592                /* It must be length operator: ${#var} */
6593                var++;
6594                exp_op = 'L';
6595        } else {
6596                /* Maybe handle parameter expansion */
6597                if (exp_saveptr /* if 2nd char is one of expansion operators */
6598                 && strchr(NUMERIC_SPECVARS_STR, arg[0]) /* 1st char is special variable */
6599                ) {
6600                        /* ${?:0}, ${#[:]%0} etc */
6601                        exp_saveptr = var + 1;
6602                } else {
6603                        /* ${?}, ${var}, ${var:0}, ${var[:]%0} etc */
6604                        exp_saveptr = var+1 + strcspn(var+1, VAR_ENCODED_SUBST_OPS);
6605                }
6606                exp_op = exp_save = *exp_saveptr;
6607                if (exp_op) {
6608                        exp_word = exp_saveptr + 1;
6609                        if (exp_op == ':') {
6610                                exp_op = *exp_word++;
6611//TODO: try ${var:} and ${var:bogus} in non-bash config
6612                                if (BASH_SUBSTR
6613                                 && (!exp_op || !strchr(MINUS_PLUS_EQUAL_QUESTION, exp_op))
6614                                ) {
6615                                        /* oops... it's ${var:N[:M]}, not ${var:?xxx} or some such */
6616                                        exp_op = ':';
6617                                        exp_word--;
6618                                }
6619                        }
6620                        *exp_saveptr = '\0';
6621                } /* else: it's not an expansion op, but bare ${var} */
6622        }
6623
6624        /* Look up the variable in question */
6625        if (isdigit(var[0])) {
6626                /* parse_dollar should have vetted var for us */
6627                int nn = xatoi_positive(var);
6628                if (nn < G.global_argc)
6629                        val = G.global_argv[nn];
6630                /* else val remains NULL: $N with too big N */
6631        } else {
6632                switch (var[0]) {
6633                case '$': /* pid */
6634                        val = utoa(G.root_pid);
6635                        break;
6636                case '!': /* bg pid */
6637                        val = G.last_bg_pid ? utoa(G.last_bg_pid) : "";
6638                        break;
6639                case '?': /* exitcode */
6640                        val = utoa(G.last_exitcode);
6641                        break;
6642                case '#': /* argc */
6643                        val = utoa(G.global_argc ? G.global_argc-1 : 0);
6644                        break;
6645                case '-': { /* active options */
6646                        /* Check set_mode() to see what option chars we support */
6647                        char *cp;
6648                        val = cp = G.optstring_buf;
6649                        if (G.o_opt[OPT_O_ERREXIT])
6650                                *cp++ = 'e';
6651                        if (G_interactive_fd)
6652                                *cp++ = 'i';
6653                        if (G_x_mode)
6654                                *cp++ = 'x';
6655                        /* If G.o_opt[OPT_O_NOEXEC] is true,
6656                         * commands read but are not executed,
6657                         * so $- can not execute too, 'n' is never seen in $-.
6658                         */
6659                        if (G.opt_c)
6660                                *cp++ = 'c';
6661                        if (G.opt_s)
6662                                *cp++ = 's';
6663                        *cp = '\0';
6664                        break;
6665                }
6666                default:
6667                        val = get_local_var_value(var);
6668                }
6669        }
6670
6671        /* Handle any expansions */
6672        if (exp_op == 'L') {
6673                reinit_unicode_for_hush();
6674                debug_printf_expand("expand: length(%s)=", val);
6675                val = utoa(val ? unicode_strlen(val) : 0);
6676                debug_printf_expand("%s\n", val);
6677        } else if (exp_op) {
6678                if (exp_op == '%' || exp_op == '#') {
6679                        /* Standard-mandated substring removal ops:
6680                         * ${parameter%word} - remove smallest suffix pattern
6681                         * ${parameter%%word} - remove largest suffix pattern
6682                         * ${parameter#word} - remove smallest prefix pattern
6683                         * ${parameter##word} - remove largest prefix pattern
6684                         *
6685                         * Word is expanded to produce a glob pattern.
6686                         * Then var's value is matched to it and matching part removed.
6687                         */
6688                        /* bash compat: if x is "" and no shrinking of it is possible,
6689                         * inner ${...} is not evaluated. Example:
6690                         *  unset b; : ${a%${b=B}}; echo $b
6691                         * assignment b=B only happens if $a is not "".
6692                         */
6693                        if (val && val[0]) {
6694                                char *t;
6695                                char *exp_exp_word;
6696                                char *loc;
6697                                unsigned scan_flags = pick_scan(exp_op, *exp_word);
6698                                if (exp_op == *exp_word)  /* ## or %% */
6699                                        exp_word++;
6700                                debug_printf_expand("expand: exp_word:'%s'\n", exp_word);
6701                                exp_exp_word = encode_then_expand_vararg(exp_word, /*handle_squotes:*/ 1, /*unbackslash:*/ 0);
6702                                if (exp_exp_word)
6703                                        exp_word = exp_exp_word;
6704                                debug_printf_expand("expand: exp_word:'%s'\n", exp_word);
6705                                /*
6706                                 * HACK ALERT. We depend here on the fact that
6707                                 * G.global_argv and results of utoa and get_local_var_value
6708                                 * are actually in writable memory:
6709                                 * scan_and_match momentarily stores NULs there.
6710                                 */
6711                                t = (char*)val;
6712                                loc = scan_and_match(t, exp_word, scan_flags);
6713                                debug_printf_expand("op:%c str:'%s' pat:'%s' res:'%s'\n", exp_op, t, exp_word, loc);
6714                                free(exp_exp_word);
6715                                if (loc) { /* match was found */
6716                                        if (scan_flags & SCAN_MATCH_LEFT_HALF) /* #[#] */
6717                                                val = loc; /* take right part */
6718                                        else /* %[%] */
6719                                                val = to_be_freed = xstrndup(val, loc - val); /* left */
6720                                }
6721                        }
6722                }
6723#if BASH_PATTERN_SUBST
6724                else if (exp_op == '/' || exp_op == '\\') {
6725                        /* It's ${var/[/]pattern[/repl]} thing.
6726                         * Note that in encoded form it has TWO parts:
6727                         * var/pattern<SPECIAL_VAR_SYMBOL>repl<SPECIAL_VAR_SYMBOL>
6728                         * and if // is used, it is encoded as \:
6729                         * var\pattern<SPECIAL_VAR_SYMBOL>repl<SPECIAL_VAR_SYMBOL>
6730                         */
6731                        /* bash compat: if var is "", both pattern and repl
6732                         * are still evaluated, if it is unset, then not:
6733                         * unset b; a=; : ${a/z/${b=3}}; echo $b      # b=3
6734                         * unset b; unset a; : ${a/z/${b=3}}; echo $b # b not set
6735                         */
6736                        if (val /*&& val[0]*/) {
6737                                /* pattern uses non-standard expansion.
6738                                 * repl should be unbackslashed and globbed
6739                                 * by the usual expansion rules:
6740                                 *  >az >bz
6741                                 *  v='a bz'; echo "${v/a*z/a*z}" #prints "a*z"
6742                                 *  v='a bz'; echo "${v/a*z/\z}"  #prints "z"
6743                                 *  v='a bz'; echo ${v/a*z/a*z}   #prints "az"
6744                                 *  v='a bz'; echo ${v/a*z/\z}    #prints "z"
6745                                 * (note that a*z _pattern_ is never globbed!)
6746                                 */
6747                                char *pattern, *repl, *t;
6748                                pattern = encode_then_expand_vararg(exp_word, /*handle_squotes:*/ 1, /*unbackslash:*/ 0);
6749                                if (!pattern)
6750                                        pattern = xstrdup(exp_word);
6751                                debug_printf_varexp("pattern:'%s'->'%s'\n", exp_word, pattern);
6752                                *p++ = SPECIAL_VAR_SYMBOL;
6753                                exp_word = p;
6754                                p = strchr(p, SPECIAL_VAR_SYMBOL);
6755                                *p = '\0';
6756                                repl = encode_then_expand_vararg(exp_word, /*handle_squotes:*/ 1, /*unbackslash:*/ 1);
6757                                debug_printf_varexp("repl:'%s'->'%s'\n", exp_word, repl);
6758                                /* HACK ALERT. We depend here on the fact that
6759                                 * G.global_argv and results of utoa and get_local_var_value
6760                                 * are actually in writable memory:
6761                                 * replace_pattern momentarily stores NULs there. */
6762                                t = (char*)val;
6763                                to_be_freed = replace_pattern(t,
6764                                                pattern,
6765                                                (repl ? repl : exp_word),
6766                                                exp_op);
6767                                if (to_be_freed) /* at least one replace happened */
6768                                        val = to_be_freed;
6769                                free(pattern);
6770                                free(repl);
6771                        } else {
6772                                /* Unset variable always gives nothing */
6773                                //  a=; echo ${a/*/w}      # "w"
6774                                //  unset a; echo ${a/*/w} # ""
6775                                /* Just skip "replace" part */
6776                                *p++ = SPECIAL_VAR_SYMBOL;
6777                                p = strchr(p, SPECIAL_VAR_SYMBOL);
6778                                *p = '\0';
6779                        }
6780                }
6781#endif /* BASH_PATTERN_SUBST */
6782                else if (exp_op == ':') {
6783#if BASH_SUBSTR && ENABLE_FEATURE_SH_MATH
6784                        /* It's ${var:N[:M]} bashism.
6785                         * Note that in encoded form it has TWO parts:
6786                         * var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL>
6787                         */
6788                        arith_t beg, len;
6789                        unsigned vallen;
6790                        const char *errmsg;
6791
6792                        beg = expand_and_evaluate_arith(exp_word, &errmsg);
6793                        if (errmsg)
6794                                goto empty_result;
6795                        debug_printf_varexp("beg:'%s'=%lld\n", exp_word, (long long)beg);
6796                        *p++ = SPECIAL_VAR_SYMBOL;
6797                        exp_word = p;
6798                        p = strchr(p, SPECIAL_VAR_SYMBOL);
6799                        *p = '\0';
6800                        vallen = val ? strlen(val) : 0;
6801                        if (beg < 0) {
6802                                /* negative beg counts from the end */
6803                                beg = (arith_t)vallen + beg;
6804                        }
6805                        /* If expansion will be empty, do not even evaluate len */
6806                        if (!val || beg < 0 || beg > vallen) {
6807                                /* Why > vallen, not >=? bash:
6808                                 * unset b; a=ab; : ${a:2:${b=3}}; echo $b  # "", b=3 (!!!)
6809                                 * unset b; a=a; : ${a:2:${b=3}}; echo $b   # "", b not set
6810                                 */
6811                                goto empty_result;
6812                        }
6813                        len = expand_and_evaluate_arith(exp_word, &errmsg);
6814                        if (errmsg)
6815                                goto empty_result;
6816                        debug_printf_varexp("len:'%s'=%lld\n", exp_word, (long long)len);
6817                        debug_printf_varexp("from val:'%s'\n", val);
6818                        if (len < 0) {
6819                                /* in bash, len=-n means strlen()-n */
6820                                len = (arith_t)vallen - beg + len;
6821                                if (len < 0) /* bash compat */
6822                                        msg_and_die_if_script("%s: substring expression < 0", var);
6823                        }
6824                        if (len <= 0 || !val /*|| beg >= vallen*/) {
6825 empty_result:
6826                                val = NULL;
6827                        } else {
6828                                /* Paranoia. What if user entered 9999999999999
6829                                 * which fits in arith_t but not int? */
6830                                if (len > INT_MAX)
6831                                        len = INT_MAX;
6832                                val = to_be_freed = xstrndup(val + beg, len);
6833                        }
6834                        debug_printf_varexp("val:'%s'\n", val);
6835#else /* not (HUSH_SUBSTR_EXPANSION && FEATURE_SH_MATH) */
6836                        msg_and_die_if_script("malformed ${%s:...}", var);
6837                        val = NULL;
6838#endif
6839                } else { /* one of "-=+?" */
6840                        /* Standard-mandated substitution ops:
6841                         * ${var?word} - indicate error if unset
6842                         *      If var is unset, word (or a message indicating it is unset
6843                         *      if word is null) is written to standard error
6844                         *      and the shell exits with a non-zero exit status.
6845                         *      Otherwise, the value of var is substituted.
6846                         * ${var-word} - use default value
6847                         *      If var is unset, word is substituted.
6848                         * ${var=word} - assign and use default value
6849                         *      If var is unset, word is assigned to var.
6850                         *      In all cases, final value of var is substituted.
6851                         * ${var+word} - use alternative value
6852                         *      If var is unset, null is substituted.
6853                         *      Otherwise, word is substituted.
6854                         *
6855                         * Word is subjected to tilde expansion, parameter expansion,
6856                         * command substitution, and arithmetic expansion.
6857                         * If word is not needed, it is not expanded.
6858                         *
6859                         * Colon forms (${var:-word}, ${var:=word} etc) do the same,
6860                         * but also treat null var as if it is unset.
6861                         *
6862                         * Word-splitting and single quote behavior:
6863                         *
6864                         * $ f() { for i; do echo "|$i|"; done; }
6865                         *
6866                         * $ x=; f ${x:?'x y' z}; echo $?
6867                         * bash: x: x y z       # neither f nor "echo $?" executes
6868                         * (if interactive, bash does not exit, but merely aborts to prompt. $? is set to 1)
6869                         * $ x=; f "${x:?'x y' z}"
6870                         * bash: x: x y z       # dash prints: dash: x: 'x y' z
6871                         *
6872                         * $ x=; f ${x:='x y' z}
6873                         * |x|
6874                         * |y|
6875                         * |z|
6876                         * $ x=; f "${x:='x y' z}"
6877                         * |'x y' z|
6878                         *
6879                         * $ x=x; f ${x:+'x y' z}
6880                         * |x y|
6881                         * |z|
6882                         * $ x=x; f "${x:+'x y' z}"
6883                         * |'x y' z|
6884                         *
6885                         * $ x=; f ${x:-'x y' z}
6886                         * |x y|
6887                         * |z|
6888                         * $ x=; f "${x:-'x y' z}"
6889                         * |'x y' z|
6890                         */
6891                        int use_word = (!val || ((exp_save == ':') && !val[0]));
6892                        if (exp_op == '+')
6893                                use_word = !use_word;
6894                        debug_printf_expand("expand: op:%c (null:%s) test:%i\n", exp_op,
6895                                        (exp_save == ':') ? "true" : "false", use_word);
6896                        if (use_word) {
6897                                if (exp_op == '+' || exp_op == '-') {
6898                                        /* ${var+word} - use alternative value */
6899                                        /* ${var-word} - use default value */
6900                                        n = encode_then_append_var_plusminus(output, n, exp_word,
6901                                                        /*dquoted:*/ (arg0 & 0x80)
6902                                        );
6903                                        val = NULL;
6904                                } else {
6905                                        /* ${var?word} - indicate error if unset */
6906                                        /* ${var=word} - assign and use default value */
6907                                        to_be_freed = encode_then_expand_vararg(exp_word,
6908                                                        /*handle_squotes:*/ !(arg0 & 0x80),
6909                                                        /*unbackslash:*/ 0
6910                                        );
6911                                        if (to_be_freed)
6912                                                exp_word = to_be_freed;
6913                                        if (exp_op == '?') {
6914                                                /* mimic bash message */
6915                                                msg_and_die_if_script("%s: %s",
6916                                                        var,
6917                                                        exp_word[0]
6918                                                        ? exp_word
6919                                                        : "parameter null or not set"
6920                                                        /* ash has more specific messages, a-la: */
6921                                                        /*: (exp_save == ':' ? "parameter null or not set" : "parameter not set")*/
6922                                                );
6923//TODO: how interactive bash aborts expansion mid-command?
6924//It aborts the entire line, returns to prompt:
6925// $ f() { for i; do echo "|$i|"; done; }; x=; f "${x:?'x y' z}"; echo YO
6926// bash: x: x y z
6927// $
6928// ("echo YO" is not executed, neither the f function call)
6929                                        } else {
6930                                                val = exp_word;
6931                                        }
6932                                        if (exp_op == '=') {
6933                                                /* ${var=[word]} or ${var:=[word]} */
6934                                                if (isdigit(var[0]) || var[0] == '#') {
6935                                                        /* mimic bash message */
6936                                                        msg_and_die_if_script("$%s: cannot assign in this way", var);
6937                                                        val = NULL;
6938                                                } else {
6939                                                        char *new_var = xasprintf("%s=%s", var, val);
6940                                                        set_local_var(new_var, /*flag:*/ 0);
6941                                                }
6942                                        }
6943                                }
6944                        }
6945                } /* one of "-=+?" */
6946
6947                *exp_saveptr = exp_save;
6948        } /* if (exp_op) */
6949
6950        arg[0] = arg0;
6951        *pp = p;
6952
6953        n = append_str_maybe_ifs_split(output, n, first_ch, val);
6954
6955        free(to_be_freed);
6956        return n;
6957}
6958
6959/* Expand all variable references in given string, adding words to list[]
6960 * at n, n+1,... positions. Return updated n (so that list[n] is next one
6961 * to be filled). This routine is extremely tricky: has to deal with
6962 * variables/parameters with whitespace, $* and $@, and constructs like
6963 * 'echo -$*-'. If you play here, you must run testsuite afterwards! */
6964static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
6965{
6966        /* output->o_expflags & EXP_FLAG_SINGLEWORD (0x80) if we are in
6967         * expansion of right-hand side of assignment == 1-element expand.
6968         */
6969        char cant_be_null = 0; /* only bit 0x80 matters */
6970        char *p;
6971
6972        debug_printf_expand("expand_vars_to_list: arg:'%s' singleword:%x\n", arg,
6973                        !!(output->o_expflags & EXP_FLAG_SINGLEWORD));
6974        debug_print_list("expand_vars_to_list[0]", output, n);
6975
6976        while ((p = strchr(arg, SPECIAL_VAR_SYMBOL)) != NULL) {
6977                char first_ch;
6978#if ENABLE_FEATURE_SH_MATH
6979                char arith_buf[sizeof(arith_t)*3 + 2];
6980#endif
6981
6982                if (output->ended_in_ifs) {
6983                        o_addchr(output, '\0');
6984                        n = o_save_ptr(output, n);
6985                        output->ended_in_ifs = 0;
6986                }
6987
6988                o_addblock(output, arg, p - arg);
6989                debug_print_list("expand_vars_to_list[1]", output, n);
6990                arg = ++p;
6991                p = strchr(p, SPECIAL_VAR_SYMBOL);
6992
6993                /* Fetch special var name (if it is indeed one of them)
6994                 * and quote bit, force the bit on if singleword expansion -
6995                 * important for not getting v=$@ expand to many words. */
6996                first_ch = arg[0] | (output->o_expflags & EXP_FLAG_SINGLEWORD);
6997
6998                /* Is this variable quoted and thus expansion can't be null?
6999                 * "$@" is special. Even if quoted, it can still
7000                 * expand to nothing (not even an empty string),
7001                 * thus it is excluded. */
7002                if ((first_ch & 0x7f) != '@')
7003                        cant_be_null |= first_ch;
7004
7005                switch (first_ch & 0x7f) {
7006                /* Highest bit in first_ch indicates that var is double-quoted */
7007                case '*':
7008                case '@': {
7009                        int i;
7010                        if (!G.global_argv[1])
7011                                break;
7012                        i = 1;
7013                        cant_be_null |= first_ch; /* do it for "$@" _now_, when we know it's not empty */
7014                        if (!(first_ch & 0x80)) { /* unquoted $* or $@ */
7015                                while (G.global_argv[i]) {
7016                                        n = expand_on_ifs(output, n, G.global_argv[i]);
7017                                        debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, G.global_argc - 1);
7018                                        if (G.global_argv[i++][0] && G.global_argv[i]) {
7019                                                /* this argv[] is not empty and not last:
7020                                                 * put terminating NUL, start new word */
7021                                                o_addchr(output, '\0');
7022                                                debug_print_list("expand_vars_to_list[2]", output, n);
7023                                                n = o_save_ptr(output, n);
7024                                                debug_print_list("expand_vars_to_list[3]", output, n);
7025                                        }
7026                                }
7027                        } else
7028                        /* If EXP_FLAG_SINGLEWORD, we handle assignment 'a=....$@.....'
7029                         * and in this case should treat it like '$*' - see 'else...' below */
7030                        if (first_ch == (char)('@'|0x80)  /* quoted $@ */
7031                         && !(output->o_expflags & EXP_FLAG_SINGLEWORD) /* not v="$@" case */
7032                        ) {
7033                                while (1) {
7034                                        o_addQstr(output, G.global_argv[i]);
7035                                        if (++i >= G.global_argc)
7036                                                break;
7037                                        o_addchr(output, '\0');
7038                                        debug_print_list("expand_vars_to_list[4]", output, n);
7039                                        n = o_save_ptr(output, n);
7040                                }
7041                        } else { /* quoted $* (or v="$@" case): add as one word */
7042                                while (1) {
7043                                        o_addQstr(output, G.global_argv[i]);
7044                                        if (!G.global_argv[++i])
7045                                                break;
7046                                        if (G.ifs[0])
7047                                                o_addchr(output, G.ifs[0]);
7048                                }
7049                                output->has_quoted_part = 1;
7050                        }
7051                        break;
7052                }
7053                case SPECIAL_VAR_SYMBOL: {
7054                        /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_SYMBOL> */
7055                        /* "Empty variable", used to make "" etc to not disappear */
7056                        output->has_quoted_part = 1;
7057                        cant_be_null = 0x80;
7058                        arg++;
7059                        break;
7060                }
7061                case SPECIAL_VAR_QUOTED_SVS:
7062                        /* <SPECIAL_VAR_SYMBOL><SPECIAL_VAR_QUOTED_SVS><SPECIAL_VAR_SYMBOL> */
7063                        /* "^C variable", represents literal ^C char (possible in scripts) */
7064                        o_addchr(output, SPECIAL_VAR_SYMBOL);
7065                        arg++;
7066                        break;
7067#if ENABLE_HUSH_TICK
7068                case '`': {
7069                        /* <SPECIAL_VAR_SYMBOL>`cmd<SPECIAL_VAR_SYMBOL> */
7070                        o_string subst_result = NULL_O_STRING;
7071
7072                        *p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */
7073                        arg++;
7074                        /* Can't just stuff it into output o_string,
7075                         * expanded result may need to be globbed
7076                         * and $IFS-split */
7077                        debug_printf_subst("SUBST '%s' first_ch %x\n", arg, first_ch);
7078                        G.last_exitcode = process_command_subs(&subst_result, arg);
7079                        G.expand_exitcode = G.last_exitcode;
7080                        debug_printf_subst("SUBST RES:%d '%s'\n", G.last_exitcode, subst_result.data);
7081                        n = append_str_maybe_ifs_split(output, n, first_ch, subst_result.data);
7082                        o_free(&subst_result);
7083                        break;
7084                }
7085#endif
7086#if ENABLE_FEATURE_SH_MATH
7087                case '+': {
7088                        /* <SPECIAL_VAR_SYMBOL>+arith<SPECIAL_VAR_SYMBOL> */
7089                        arith_t res;
7090
7091                        arg++; /* skip '+' */
7092                        *p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */
7093                        debug_printf_subst("ARITH '%s' first_ch %x\n", arg, first_ch);
7094                        res = expand_and_evaluate_arith(arg, NULL);
7095                        debug_printf_subst("ARITH RES '"ARITH_FMT"'\n", res);
7096                        sprintf(arith_buf, ARITH_FMT, res);
7097                        if (res < 0
7098                         && first_ch == (char)('+'|0x80)
7099                        /* && (output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS) */
7100                        ) {
7101                                /* Quoted negative ariths, like filename[0"$((-9))"],
7102                                 * should not be interpreted as glob ranges.
7103                                 * Convert leading '-' to '\-':
7104                                 */
7105                                o_grow_by(output, 1);
7106                                output->data[output->length++] = '\\';
7107                        }
7108                        o_addstr(output, arith_buf);
7109                        break;
7110                }
7111#endif
7112                default:
7113                        /* <SPECIAL_VAR_SYMBOL>varname[ops]<SPECIAL_VAR_SYMBOL> */
7114                        n = expand_one_var(output, n, first_ch, arg, &p);
7115                        break;
7116                } /* switch (char after <SPECIAL_VAR_SYMBOL>) */
7117
7118                /* Restore NULL'ed SPECIAL_VAR_SYMBOL.
7119                 * Do the check to avoid writing to a const string. */
7120                if (*p != SPECIAL_VAR_SYMBOL)
7121                        *p = SPECIAL_VAR_SYMBOL;
7122                arg = ++p;
7123        } /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */
7124
7125        if (*arg) {
7126                /* handle trailing string */
7127                if (output->ended_in_ifs) {
7128                        o_addchr(output, '\0');
7129                        n = o_save_ptr(output, n);
7130                }
7131                debug_print_list("expand_vars_to_list[a]", output, n);
7132                /* this part is literal, and it was already pre-quoted
7133                 * if needed (much earlier), do not use o_addQstr here!
7134                 */
7135                o_addstr(output, arg);
7136                debug_print_list("expand_vars_to_list[b]", output, n);
7137        } else
7138        if (output->length == o_get_last_ptr(output, n) /* expansion is empty */
7139         && !(cant_be_null & 0x80)   /* and all vars were not quoted */
7140         && !output->has_quoted_part
7141        ) {
7142                n--;
7143                /* allow to reuse list[n] later without re-growth */
7144                output->has_empty_slot = 1;
7145        }
7146
7147        return n;
7148}
7149
7150static char **expand_variables(char **argv, unsigned expflags)
7151{
7152        int n;
7153        char **list;
7154        o_string output = NULL_O_STRING;
7155
7156        output.o_expflags = expflags;
7157
7158        n = 0;
7159        for (;;) {
7160                /* go to next list[n] */
7161                output.ended_in_ifs = 0;
7162                n = o_save_ptr(&output, n);
7163
7164                if (!*argv)
7165                        break;
7166
7167                /* expand argv[i] */
7168                n = expand_vars_to_list(&output, n, *argv++);
7169                /* if (!output->has_empty_slot) -- need this?? */
7170                        o_addchr(&output, '\0');
7171        }
7172        debug_print_list("expand_variables", &output, n);
7173
7174        /* output.data (malloced in one block) gets returned in "list" */
7175        list = o_finalize_list(&output, n);
7176        debug_print_strings("expand_variables[1]", list);
7177        return list;
7178}
7179
7180static char **expand_strvec_to_strvec(char **argv)
7181{
7182        return expand_variables(argv, EXP_FLAG_GLOB | EXP_FLAG_ESC_GLOB_CHARS);
7183}
7184
7185#if defined(CMD_SINGLEWORD_NOGLOB) || defined(CMD_TEST2_SINGLEWORD_NOGLOB)
7186static char **expand_strvec_to_strvec_singleword_noglob(char **argv)
7187{
7188        return expand_variables(argv, EXP_FLAG_SINGLEWORD);
7189}
7190#endif
7191
7192/* Used for expansion of right hand of assignments,
7193 * $((...)), heredocs, variable expansion parts.
7194 *
7195 * NB: should NOT do globbing!
7196 * "export v=/bin/c*; env | grep ^v=" outputs "v=/bin/c*"
7197 */
7198static char *expand_string_to_string(const char *str, int EXP_flags, int do_unbackslash)
7199{
7200#if !BASH_PATTERN_SUBST && !ENABLE_HUSH_CASE
7201        const int do_unbackslash = 1;
7202        const int EXP_flags = EXP_FLAG_ESC_GLOB_CHARS;
7203#endif
7204        char *argv[2], **list;
7205
7206        debug_printf_expand("string_to_string<='%s'\n", str);
7207        /* This is generally an optimization, but it also
7208         * handles "", which otherwise trips over !list[0] check below.
7209         * (is this ever happens that we actually get str="" here?)
7210         */
7211        if (!strchr(str, SPECIAL_VAR_SYMBOL) && !strchr(str, '\\')) {
7212                //TODO: Can use on strings with \ too, just unbackslash() them?
7213                debug_printf_expand("string_to_string(fast)=>'%s'\n", str);
7214                return xstrdup(str);
7215        }
7216
7217        argv[0] = (char*)str;
7218        argv[1] = NULL;
7219        list = expand_variables(argv, EXP_flags | EXP_FLAG_SINGLEWORD);
7220        if (!list[0]) {
7221                /* Example where it happens:
7222                 * x=; echo ${x:-"$@"}
7223                 */
7224                ((char*)list)[0] = '\0';
7225        } else {
7226                if (HUSH_DEBUG)
7227                        if (list[1])
7228                                bb_simple_error_msg_and_die("BUG in varexp2");
7229                /* actually, just move string 2*sizeof(char*) bytes back */
7230                overlapping_strcpy((char*)list, list[0]);
7231                if (do_unbackslash)
7232                        unbackslash((char*)list);
7233        }
7234        debug_printf_expand("string_to_string=>'%s'\n", (char*)list);
7235        return (char*)list;
7236}
7237
7238#if 0
7239static char* expand_strvec_to_string(char **argv)
7240{
7241        char **list;
7242
7243        list = expand_variables(argv, EXP_FLAG_SINGLEWORD);
7244        /* Convert all NULs to spaces */
7245        if (list[0]) {
7246                int n = 1;
7247                while (list[n]) {
7248                        if (HUSH_DEBUG)
7249                                if (list[n-1] + strlen(list[n-1]) + 1 != list[n])
7250                                        bb_error_msg_and_die("BUG in varexp3");
7251                        /* bash uses ' ' regardless of $IFS contents */
7252                        list[n][-1] = ' ';
7253                        n++;
7254                }
7255        }
7256        overlapping_strcpy((char*)list, list[0] ? list[0] : "");
7257        debug_printf_expand("strvec_to_string='%s'\n", (char*)list);
7258        return (char*)list;
7259}
7260#endif
7261
7262static char **expand_assignments(char **argv, int count)
7263{
7264        int i;
7265        char **p;
7266
7267        G.expanded_assignments = p = NULL;
7268        /* Expand assignments into one string each */
7269        for (i = 0; i < count; i++) {
7270                p = add_string_to_strings(p,
7271                        expand_string_to_string(argv[i],
7272                                EXP_FLAG_ESC_GLOB_CHARS,
7273                                /*unbackslash:*/ 1
7274                        )
7275                );
7276                G.expanded_assignments = p;
7277        }
7278        G.expanded_assignments = NULL;
7279        return p;
7280}
7281
7282
7283static void switch_off_special_sigs(unsigned mask)
7284{
7285        unsigned sig = 0;
7286        while ((mask >>= 1) != 0) {
7287                sig++;
7288                if (!(mask & 1))
7289                        continue;
7290#if ENABLE_HUSH_TRAP
7291                if (G_traps) {
7292                        if (G_traps[sig] && !G_traps[sig][0])
7293                                /* trap is '', has to remain SIG_IGN */
7294                                continue;
7295                        free(G_traps[sig]);
7296                        G_traps[sig] = NULL;
7297                }
7298#endif
7299                /* We are here only if no trap or trap was not '' */
7300                install_sighandler(sig, SIG_DFL);
7301        }
7302}
7303
7304#if BB_MMU
7305/* never called */
7306void re_execute_shell(char ***to_free, const char *s,
7307                char *g_argv0, char **g_argv,
7308                char **builtin_argv) NORETURN;
7309
7310static void reset_traps_to_defaults(void)
7311{
7312        /* This function is always called in a child shell
7313         * after fork (not vfork, NOMMU doesn't use this function).
7314         */
7315        IF_HUSH_TRAP(unsigned sig;)
7316        unsigned mask;
7317
7318        /* Child shells are not interactive.
7319         * SIGTTIN/SIGTTOU/SIGTSTP should not have special handling.
7320         * Testcase: (while :; do :; done) + ^Z should background.
7321         * Same goes for SIGTERM, SIGHUP, SIGINT.
7322         */
7323        mask = (G.special_sig_mask & SPECIAL_INTERACTIVE_SIGS) | G_fatal_sig_mask;
7324        if (!G_traps && !mask)
7325                return; /* already no traps and no special sigs */
7326
7327        /* Switch off special sigs */
7328        switch_off_special_sigs(mask);
7329# if ENABLE_HUSH_JOB
7330        G_fatal_sig_mask = 0;
7331# endif
7332        G.special_sig_mask &= ~SPECIAL_INTERACTIVE_SIGS;
7333        /* SIGQUIT,SIGCHLD and maybe SPECIAL_JOBSTOP_SIGS
7334         * remain set in G.special_sig_mask */
7335
7336# if ENABLE_HUSH_TRAP
7337        if (!G_traps)
7338                return;
7339
7340        /* Reset all sigs to default except ones with empty traps */
7341        for (sig = 0; sig < NSIG; sig++) {
7342                if (!G_traps[sig])
7343                        continue; /* no trap: nothing to do */
7344                if (!G_traps[sig][0])
7345                        continue; /* empty trap: has to remain SIG_IGN */
7346                /* sig has non-empty trap, reset it: */
7347                free(G_traps[sig]);
7348                G_traps[sig] = NULL;
7349                /* There is no signal for trap 0 (EXIT) */
7350                if (sig == 0)
7351                        continue;
7352                install_sighandler(sig, pick_sighandler(sig));
7353        }
7354# endif
7355}
7356
7357#else /* !BB_MMU */
7358
7359static void re_execute_shell(char ***to_free, const char *s,
7360                char *g_argv0, char **g_argv,
7361                char **builtin_argv) NORETURN;
7362static void re_execute_shell(char ***to_free, const char *s,
7363                char *g_argv0, char **g_argv,
7364                char **builtin_argv)
7365{
7366# define NOMMU_HACK_FMT ("-$%x:%x:%x:%x:%x:%llx" IF_HUSH_LOOPS(":%x"))
7367        /* delims + 2 * (number of bytes in printed hex numbers) */
7368        char param_buf[sizeof(NOMMU_HACK_FMT) + 2 * (sizeof(int)*6 + sizeof(long long)*1)];
7369        char *heredoc_argv[4];
7370        struct variable *cur;
7371# if ENABLE_HUSH_FUNCTIONS
7372        struct function *funcp;
7373# endif
7374        char **argv, **pp;
7375        unsigned cnt;
7376        unsigned long long empty_trap_mask;
7377
7378        if (!g_argv0) { /* heredoc */
7379                argv = heredoc_argv;
7380                argv[0] = (char *) G.argv0_for_re_execing;
7381                argv[1] = (char *) "-<";
7382                argv[2] = (char *) s;
7383                argv[3] = NULL;
7384                pp = &argv[3]; /* used as pointer to empty environment */
7385                goto do_exec;
7386        }
7387
7388        cnt = 0;
7389        pp = builtin_argv;
7390        if (pp) while (*pp++)
7391                cnt++;
7392
7393        empty_trap_mask = 0;
7394        if (G_traps) {
7395                int sig;
7396                for (sig = 1; sig < NSIG; sig++) {
7397                        if (G_traps[sig] && !G_traps[sig][0])
7398                                empty_trap_mask |= 1LL << sig;
7399                }
7400        }
7401
7402        sprintf(param_buf, NOMMU_HACK_FMT
7403                        , (unsigned) G.root_pid
7404                        , (unsigned) G.root_ppid
7405                        , (unsigned) G.last_bg_pid
7406                        , (unsigned) G.last_exitcode
7407                        , cnt
7408                        , empty_trap_mask
7409                        IF_HUSH_LOOPS(, G.depth_of_loop)
7410                        );
7411# undef NOMMU_HACK_FMT
7412        /* 1:hush 2:-$<pid>:<pid>:<exitcode>:<etc...> <vars...> <funcs...>
7413         * 3:-c 4:<cmd> 5:<arg0> <argN...> 6:NULL
7414         */
7415        cnt += 6;
7416        for (cur = G.top_var; cur; cur = cur->next) {
7417                if (!cur->flg_export || cur->flg_read_only)
7418                        cnt += 2;
7419        }
7420# if ENABLE_HUSH_FUNCTIONS
7421        for (funcp = G.top_func; funcp; funcp = funcp->next)
7422                cnt += 3;
7423# endif
7424        pp = g_argv;
7425        while (*pp++)
7426                cnt++;
7427        *to_free = argv = pp = xzalloc(sizeof(argv[0]) * cnt);
7428        *pp++ = (char *) G.argv0_for_re_execing;
7429        *pp++ = param_buf;
7430        for (cur = G.top_var; cur; cur = cur->next) {
7431                if (strcmp(cur->varstr, hush_version_str) == 0)
7432                        continue;
7433                if (cur->flg_read_only) {
7434                        *pp++ = (char *) "-R";
7435                        *pp++ = cur->varstr;
7436                } else if (!cur->flg_export) {
7437                        *pp++ = (char *) "-V";
7438                        *pp++ = cur->varstr;
7439                }
7440        }
7441# if ENABLE_HUSH_FUNCTIONS
7442        for (funcp = G.top_func; funcp; funcp = funcp->next) {
7443                *pp++ = (char *) "-F";
7444                *pp++ = funcp->name;
7445                *pp++ = funcp->body_as_string;
7446        }
7447# endif
7448        /* We can pass activated traps here. Say, -Tnn:trap_string
7449         *
7450         * However, POSIX says that subshells reset signals with traps
7451         * to SIG_DFL.
7452         * I tested bash-3.2 and it not only does that with true subshells
7453         * of the form ( list ), but with any forked children shells.
7454         * I set trap "echo W" WINCH; and then tried:
7455         *
7456         * { echo 1; sleep 20; echo 2; } &
7457         * while true; do echo 1; sleep 20; echo 2; break; done &
7458         * true | { echo 1; sleep 20; echo 2; } | cat
7459         *
7460         * In all these cases sending SIGWINCH to the child shell
7461         * did not run the trap. If I add trap "echo V" WINCH;
7462         * _inside_ group (just before echo 1), it works.
7463         *
7464         * I conclude it means we don't need to pass active traps here.
7465         */
7466        *pp++ = (char *) "-c";
7467        *pp++ = (char *) s;
7468        if (builtin_argv) {
7469                while (*++builtin_argv)
7470                        *pp++ = *builtin_argv;
7471                *pp++ = (char *) "";
7472        }
7473        *pp++ = g_argv0;
7474        while (*g_argv)
7475                *pp++ = *g_argv++;
7476        /* *pp = NULL; - is already there */
7477        pp = environ;
7478
7479 do_exec:
7480        debug_printf_exec("re_execute_shell pid:%d cmd:'%s'\n", getpid(), s);
7481        /* Don't propagate SIG_IGN to the child */
7482        if (SPECIAL_JOBSTOP_SIGS != 0)
7483                switch_off_special_sigs(G.special_sig_mask & SPECIAL_JOBSTOP_SIGS);
7484        execve(bb_busybox_exec_path, argv, pp);
7485        /* Fallback. Useful for init=/bin/hush usage etc */
7486        if (argv[0][0] == '/')
7487                execve(argv[0], argv, pp);
7488        xfunc_error_retval = 127;
7489        bb_simple_error_msg_and_die("can't re-execute the shell");
7490}
7491#endif  /* !BB_MMU */
7492
7493
7494static int run_and_free_list(struct pipe *pi);
7495
7496/* Executing from string: eval, sh -c '...'
7497 *          or from file: /etc/profile, . file, sh <script>, sh (intereactive)
7498 * end_trigger controls how often we stop parsing
7499 * NUL: parse all, execute, return
7500 * ';': parse till ';' or newline, execute, repeat till EOF
7501 */
7502static void parse_and_run_stream(struct in_str *inp, int end_trigger)
7503{
7504        /* Why we need empty flag?
7505         * An obscure corner case "false; ``; echo $?":
7506         * empty command in `` should still set $? to 0.
7507         * But we can't just set $? to 0 at the start,
7508         * this breaks "false; echo `echo $?`" case.
7509         */
7510        bool empty = 1;
7511        while (1) {
7512                struct pipe *pipe_list;
7513
7514#if ENABLE_HUSH_INTERACTIVE
7515                if (end_trigger == ';') {
7516                        G.promptmode = 0; /* PS1 */
7517                        debug_printf_prompt("%s promptmode=%d\n", __func__, G.promptmode);
7518                }
7519#endif
7520                pipe_list = parse_stream(NULL, NULL, inp, end_trigger);
7521                if (!pipe_list || pipe_list == ERR_PTR) { /* EOF/error */
7522                        /* If we are in "big" script
7523                         * (not in `cmd` or something similar)...
7524                         */
7525                        if (pipe_list == ERR_PTR && end_trigger == ';') {
7526                                /* Discard cached input (rest of line) */
7527                                int ch = inp->last_char;
7528                                while (ch != EOF && ch != '\n') {
7529                                        //bb_error_msg("Discarded:'%c'", ch);
7530                                        ch = i_getch(inp);
7531                                }
7532                                /* Force prompt */
7533                                inp->p = NULL;
7534                                /* This stream isn't empty */
7535                                empty = 0;
7536                                continue;
7537                        }
7538                        if (!pipe_list && empty)
7539                                G.last_exitcode = 0;
7540                        break;
7541                }
7542                debug_print_tree(pipe_list, 0);
7543                debug_printf_exec("parse_and_run_stream: run_and_free_list\n");
7544                run_and_free_list(pipe_list);
7545                empty = 0;
7546                if (G_flag_return_in_progress == 1)
7547                        break;
7548        }
7549}
7550
7551static void parse_and_run_string(const char *s)
7552{
7553        struct in_str input;
7554        IF_HUSH_LINENO_VAR(unsigned sv = G.parse_lineno;)
7555
7556        setup_string_in_str(&input, s);
7557        parse_and_run_stream(&input, '\0');
7558        IF_HUSH_LINENO_VAR(G.parse_lineno = sv;)
7559}
7560
7561static void parse_and_run_file(HFILE *fp)
7562{
7563        struct in_str input;
7564        IF_HUSH_LINENO_VAR(unsigned sv = G.parse_lineno;)
7565
7566        IF_HUSH_LINENO_VAR(G.parse_lineno = 1;)
7567        setup_file_in_str(&input, fp);
7568        parse_and_run_stream(&input, ';');
7569        IF_HUSH_LINENO_VAR(G.parse_lineno = sv;)
7570}
7571
7572#if ENABLE_HUSH_TICK
7573static int generate_stream_from_string(const char *s, pid_t *pid_p)
7574{
7575        pid_t pid;
7576        int channel[2];
7577# if !BB_MMU
7578        char **to_free = NULL;
7579# endif
7580
7581        xpipe(channel);
7582        pid = BB_MMU ? xfork() : xvfork();
7583        if (pid == 0) { /* child */
7584                disable_restore_tty_pgrp_on_exit();
7585                /* Process substitution is not considered to be usual
7586                 * 'command execution'.
7587                 * SUSv3 says ctrl-Z should be ignored, ctrl-C should not.
7588                 */
7589                bb_signals(0
7590                        + (1 << SIGTSTP)
7591                        + (1 << SIGTTIN)
7592                        + (1 << SIGTTOU)
7593                        , SIG_IGN);
7594                close(channel[0]); /* NB: close _first_, then move fd! */
7595                xmove_fd(channel[1], 1);
7596# if ENABLE_HUSH_TRAP
7597                /* Awful hack for `trap` or $(trap).
7598                 *
7599                 * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
7600                 * contains an example where "trap" is executed in a subshell:
7601                 *
7602                 * save_traps=$(trap)
7603                 * ...
7604                 * eval "$save_traps"
7605                 *
7606                 * Standard does not say that "trap" in subshell shall print
7607                 * parent shell's traps. It only says that its output
7608                 * must have suitable form, but then, in the above example
7609                 * (which is not supposed to be normative), it implies that.
7610                 *
7611                 * bash (and probably other shell) does implement it
7612                 * (traps are reset to defaults, but "trap" still shows them),
7613                 * but as a result, "trap" logic is hopelessly messed up:
7614                 *
7615                 * # trap
7616                 * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
7617                 * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
7618                 * # true | trap   <--- trap is in subshell - no output (ditto)
7619                 * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
7620                 * trap -- 'echo Ho' SIGWINCH
7621                 * # echo `(trap)`         <--- in subshell in subshell - output
7622                 * trap -- 'echo Ho' SIGWINCH
7623                 * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
7624                 * trap -- 'echo Ho' SIGWINCH
7625                 *
7626                 * The rules when to forget and when to not forget traps
7627                 * get really complex and nonsensical.
7628                 *
7629                 * Our solution: ONLY bare $(trap) or `trap` is special.
7630                 */
7631                s = skip_whitespace(s);
7632                if (is_prefixed_with(s, "trap")
7633                 && skip_whitespace(s + 4)[0] == '\0'
7634                ) {
7635                        static const char *const argv[] = { NULL, NULL };
7636                        builtin_trap((char**)argv);
7637                        fflush_all(); /* important */
7638                        _exit(0);
7639                }
7640# endif
7641# if BB_MMU
7642                /* Prevent it from trying to handle ctrl-z etc */
7643                IF_HUSH_JOB(G.run_list_level = 1;)
7644                CLEAR_RANDOM_T(&G.random_gen); /* or else $RANDOM repeats in child */
7645                reset_traps_to_defaults();
7646                IF_HUSH_MODE_X(G.x_mode_depth++;)
7647                //bb_error_msg("%s: ++x_mode_depth=%d", __func__, G.x_mode_depth);
7648                parse_and_run_string(s);
7649                _exit(G.last_exitcode);
7650# else
7651        /* We re-execute after vfork on NOMMU. This makes this script safe:
7652         * yes "0123456789012345678901234567890" | dd bs=32 count=64k >BIG
7653         * huge=`cat BIG` # was blocking here forever
7654         * echo OK
7655         */
7656                re_execute_shell(&to_free,
7657                                s,
7658                                G.global_argv[0],
7659                                G.global_argv + 1,
7660                                NULL);
7661# endif
7662        }
7663
7664        /* parent */
7665        *pid_p = pid;
7666# if ENABLE_HUSH_FAST
7667        G.count_SIGCHLD++;
7668//bb_error_msg("[%d] fork in generate_stream_from_string:"
7669//              " G.count_SIGCHLD:%d G.handled_SIGCHLD:%d",
7670//              getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
7671# endif
7672        enable_restore_tty_pgrp_on_exit();
7673# if !BB_MMU
7674        free(to_free);
7675# endif
7676        close(channel[1]);
7677        return channel[0];
7678}
7679
7680/* Return code is exit status of the process that is run. */
7681static int process_command_subs(o_string *dest, const char *s)
7682{
7683        FILE *fp;
7684        pid_t pid;
7685        int status, ch, eol_cnt;
7686
7687        fp = xfdopen_for_read(generate_stream_from_string(s, &pid));
7688
7689        /* Now send results of command back into original context */
7690        eol_cnt = 0;
7691        while ((ch = getc(fp)) != EOF) {
7692                if (ch == '\0')
7693                        continue;
7694                if (ch == '\n') {
7695                        eol_cnt++;
7696                        continue;
7697                }
7698                while (eol_cnt) {
7699                        o_addchr(dest, '\n');
7700                        eol_cnt--;
7701                }
7702                o_addQchr(dest, ch);
7703        }
7704
7705        debug_printf("done reading from `cmd` pipe, closing it\n");
7706        fclose(fp);
7707        /* We need to extract exitcode. Test case
7708         * "true; echo `sleep 1; false` $?"
7709         * should print 1 */
7710        safe_waitpid(pid, &status, 0);
7711        debug_printf("child exited. returning its exitcode:%d\n", WEXITSTATUS(status));
7712        return WEXITSTATUS(status);
7713}
7714#endif /* ENABLE_HUSH_TICK */
7715
7716
7717static void setup_heredoc(struct redir_struct *redir)
7718{
7719        struct fd_pair pair;
7720        pid_t pid;
7721        int len, written;
7722        /* the _body_ of heredoc (misleading field name) */
7723        const char *heredoc = redir->rd_filename;
7724        char *expanded;
7725#if !BB_MMU
7726        char **to_free;
7727#endif
7728
7729        expanded = NULL;
7730        if (!(redir->rd_dup & HEREDOC_QUOTED)) {
7731                expanded = encode_then_expand_string(heredoc);
7732                if (expanded)
7733                        heredoc = expanded;
7734        }
7735        len = strlen(heredoc);
7736
7737        close(redir->rd_fd); /* often saves dup2+close in xmove_fd */
7738        xpiped_pair(pair);
7739        xmove_fd(pair.rd, redir->rd_fd);
7740
7741        /* Try writing without forking. Newer kernels have
7742         * dynamically growing pipes. Must use non-blocking write! */
7743        ndelay_on(pair.wr);
7744        while (1) {
7745                written = write(pair.wr, heredoc, len);
7746                if (written <= 0)
7747                        break;
7748                len -= written;
7749                if (len == 0) {
7750                        close(pair.wr);
7751                        free(expanded);
7752                        return;
7753                }
7754                heredoc += written;
7755        }
7756        ndelay_off(pair.wr);
7757
7758        /* Okay, pipe buffer was not big enough */
7759        /* Note: we must not create a stray child (bastard? :)
7760         * for the unsuspecting parent process. Child creates a grandchild
7761         * and exits before parent execs the process which consumes heredoc
7762         * (that exec happens after we return from this function) */
7763#if !BB_MMU
7764        to_free = NULL;
7765#endif
7766        pid = xvfork();
7767        if (pid == 0) {
7768                /* child */
7769                disable_restore_tty_pgrp_on_exit();
7770                pid = BB_MMU ? xfork() : xvfork();
7771                if (pid != 0)
7772                        _exit(0);
7773                /* grandchild */
7774                close(redir->rd_fd); /* read side of the pipe */
7775#if BB_MMU
7776                full_write(pair.wr, heredoc, len); /* may loop or block */
7777                _exit(0);
7778#else
7779                /* Delegate blocking writes to another process */
7780                xmove_fd(pair.wr, STDOUT_FILENO);
7781                re_execute_shell(&to_free, heredoc, NULL, NULL, NULL);
7782#endif
7783        }
7784        /* parent */
7785#if ENABLE_HUSH_FAST
7786        G.count_SIGCHLD++;
7787//bb_error_msg("[%d] fork in setup_heredoc: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
7788#endif
7789        enable_restore_tty_pgrp_on_exit();
7790#if !BB_MMU
7791        free(to_free);
7792#endif
7793        close(pair.wr);
7794        free(expanded);
7795        wait(NULL); /* wait till child has died */
7796}
7797
7798struct squirrel {
7799        int orig_fd;
7800        int moved_to;
7801        /* moved_to = n: fd was moved to n; restore back to orig_fd after redir */
7802        /* moved_to = -1: fd was opened by redirect; close orig_fd after redir */
7803};
7804
7805static struct squirrel *append_squirrel(struct squirrel *sq, int i, int orig, int moved)
7806{
7807        sq = xrealloc(sq, (i + 2) * sizeof(sq[0]));
7808        sq[i].orig_fd = orig;
7809        sq[i].moved_to = moved;
7810        sq[i+1].orig_fd = -1; /* end marker */
7811        return sq;
7812}
7813
7814static struct squirrel *add_squirrel(struct squirrel *sq, int fd, int avoid_fd)
7815{
7816        int moved_to;
7817        int i;
7818
7819        i = 0;
7820        if (sq) for (; sq[i].orig_fd >= 0; i++) {
7821                /* If we collide with an already moved fd... */
7822                if (fd == sq[i].moved_to) {
7823                        sq[i].moved_to = dup_CLOEXEC(sq[i].moved_to, avoid_fd);
7824                        debug_printf_redir("redirect_fd %d: already busy, moving to %d\n", fd, sq[i].moved_to);
7825                        if (sq[i].moved_to < 0) /* what? */
7826                                xfunc_die();
7827                        return sq;
7828                }
7829                if (fd == sq[i].orig_fd) {
7830                        /* Example: echo Hello >/dev/null 1>&2 */
7831                        debug_printf_redir("redirect_fd %d: already moved\n", fd);
7832                        return sq;
7833                }
7834        }
7835
7836        /* If this fd is open, we move and remember it; if it's closed, moved_to = -1 */
7837        moved_to = dup_CLOEXEC(fd, avoid_fd);
7838        debug_printf_redir("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, moved_to);
7839        if (moved_to < 0 && errno != EBADF)
7840                xfunc_die();
7841        return append_squirrel(sq, i, fd, moved_to);
7842}
7843
7844static struct squirrel *add_squirrel_closed(struct squirrel *sq, int fd)
7845{
7846        int i;
7847
7848        i = 0;
7849        if (sq) for (; sq[i].orig_fd >= 0; i++) {
7850                /* If we collide with an already moved fd... */
7851                if (fd == sq[i].orig_fd) {
7852                        /* Examples:
7853                         * "echo 3>FILE 3>&- 3>FILE"
7854                         * "echo 3>&- 3>FILE"
7855                         * No need for last redirect to insert
7856                         * another "need to close 3" indicator.
7857                         */
7858                        debug_printf_redir("redirect_fd %d: already moved or closed\n", fd);
7859                        return sq;
7860                }
7861        }
7862
7863        debug_printf_redir("redirect_fd %d: previous fd was closed\n", fd);
7864        return append_squirrel(sq, i, fd, -1);
7865}
7866
7867/* fd: redirect wants this fd to be used (e.g. 3>file).
7868 * Move all conflicting internally used fds,
7869 * and remember them so that we can restore them later.
7870 */
7871static int save_fd_on_redirect(int fd, int avoid_fd, struct squirrel **sqp)
7872{
7873        if (avoid_fd < 9) /* the important case here is that it can be -1 */
7874                avoid_fd = 9;
7875
7876#if ENABLE_HUSH_INTERACTIVE
7877        if (fd != 0 /* don't trigger for G_interactive_fd == 0 (that's "not interactive" flag) */
7878         && fd == G_interactive_fd
7879        ) {
7880                /* Testcase: "ls -l /proc/$$/fd 255>&-" should work */
7881                G_interactive_fd = xdup_CLOEXEC_and_close(G_interactive_fd, avoid_fd);
7882                debug_printf_redir("redirect_fd %d: matches interactive_fd, moving it to %d\n", fd, G_interactive_fd);
7883                return 1; /* "we closed fd" */
7884        }
7885#endif
7886        /* Are we called from setup_redirects(squirrel==NULL)
7887         * in redirect in a [v]forked child?
7888         */
7889        if (sqp == NULL) {
7890                /* No need to move script fds.
7891                 * For NOMMU case, it's actively wrong: we'd change ->fd
7892                 * fields in memory for the parent, but parent's fds
7893                 * aren't moved, it would use wrong fd!
7894                 * Reproducer: "cmd 3>FILE" in script.
7895                 * If we would call move_HFILEs_on_redirect(), child would:
7896                 *  fcntl64(3, F_DUPFD_CLOEXEC, 10)   = 10
7897                 *  close(3)                          = 0
7898                 * and change ->fd to 10 if fd#3 is a script fd. WRONG.
7899                 */
7900                //bb_error_msg("sqp == NULL: [v]forked child");
7901                return 0;
7902        }
7903
7904        /* If this one of script's fds? */
7905        if (move_HFILEs_on_redirect(fd, avoid_fd))
7906                return 1; /* yes. "we closed fd" (actually moved it) */
7907
7908        /* Are we called for "exec 3>FILE"? Came through
7909         * redirect_and_varexp_helper(squirrel=ERR_PTR) -> setup_redirects(ERR_PTR)
7910         * This case used to fail for this script:
7911         *  exec 3>FILE
7912         *  echo Ok
7913         *  ...100000 more lines...
7914         *  echo Ok
7915         * as follows:
7916         *  read(3, "exec 3>FILE\necho Ok\necho Ok"..., 1024) = 1024
7917         *  open("FILE", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 4
7918         *  dup2(4, 3)                        = 3
7919         *  ^^^^^^^^ oops, we lost fd#3 opened to our script!
7920         *  close(4)                          = 0
7921         *  write(1, "Ok\n", 3)               = 3
7922         *  ...                               = 3
7923         *  write(1, "Ok\n", 3)               = 3
7924         *  read(3, 0x94fbc08, 1024)          = -1 EBADF (Bad file descriptor)
7925         *  ^^^^^^^^ oops, wrong fd!!!
7926         * With this case separate from sqp == NULL and *after* move_HFILEs,
7927         * it now works:
7928         */
7929        if (sqp == ERR_PTR) {
7930                /* Don't preserve redirected fds: exec is _meant_ to change these */
7931                //bb_error_msg("sqp == ERR_PTR: exec >FILE");
7932                return 0;
7933        }
7934
7935        /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
7936        *sqp = add_squirrel(*sqp, fd, avoid_fd);
7937        return 0; /* "we did not close fd" */
7938}
7939
7940static void restore_redirects(struct squirrel *sq)
7941{
7942        if (sq) {
7943                int i;
7944                for (i = 0; sq[i].orig_fd >= 0; i++) {
7945                        if (sq[i].moved_to >= 0) {
7946                                /* We simply die on error */
7947                                debug_printf_redir("restoring redirected fd from %d to %d\n", sq[i].moved_to, sq[i].orig_fd);
7948                                xmove_fd(sq[i].moved_to, sq[i].orig_fd);
7949                        } else {
7950                                /* cmd1 9>FILE; cmd2_should_see_fd9_closed */
7951                                debug_printf_redir("restoring redirected fd %d: closing it\n", sq[i].orig_fd);
7952                                close(sq[i].orig_fd);
7953                        }
7954                }
7955                free(sq);
7956        }
7957        if (G.HFILE_stdin
7958         && G.HFILE_stdin->fd > STDIN_FILENO
7959        /* we compare > STDIN, not == STDIN, since hfgetc()
7960         * closes fd and sets ->fd to -1 if EOF is reached.
7961         * Testcase: echo 'pwd' | hush
7962         */
7963        ) {
7964                /* Testcase: interactive "read r <FILE; echo $r; read r; echo $r".
7965                 * Redirect moves ->fd to e.g. 10,
7966                 * and it is not restored above (we do not restore script fds
7967                 * after redirects, we just use new, "moved" fds).
7968                 * However for stdin, get_user_input() -> read_line_input(),
7969                 * and read builtin, depend on fd == STDIN_FILENO.
7970                 */
7971                debug_printf_redir("restoring %d to stdin\n", G.HFILE_stdin->fd);
7972                xmove_fd(G.HFILE_stdin->fd, STDIN_FILENO);
7973                G.HFILE_stdin->fd = STDIN_FILENO;
7974        }
7975
7976        /* If moved, G_interactive_fd stays on new fd, not restoring it */
7977}
7978
7979#if ENABLE_FEATURE_SH_STANDALONE && BB_MMU
7980static void close_saved_fds_and_FILE_fds(void)
7981{
7982        if (G_interactive_fd)
7983                close(G_interactive_fd);
7984        close_all_HFILE_list();
7985}
7986#endif
7987
7988static int internally_opened_fd(int fd, struct squirrel *sq)
7989{
7990        int i;
7991
7992#if ENABLE_HUSH_INTERACTIVE
7993        if (fd == G_interactive_fd)
7994                return 1;
7995#endif
7996        /* If this one of script's fds? */
7997        if (fd_in_HFILEs(fd))
7998                return 1;
7999
8000        if (sq) for (i = 0; sq[i].orig_fd >= 0; i++) {
8001                if (fd == sq[i].moved_to)
8002                        return 1;
8003        }
8004        return 0;
8005}
8006
8007/* squirrel != NULL means we squirrel away copies of stdin, stdout,
8008 * and stderr if they are redirected. */
8009static int setup_redirects(struct command *prog, struct squirrel **sqp)
8010{
8011        struct redir_struct *redir;
8012
8013        for (redir = prog->redirects; redir; redir = redir->next) {
8014                int newfd;
8015                int closed;
8016
8017                if (redir->rd_type == REDIRECT_HEREDOC2) {
8018                        /* "rd_fd<<HERE" case */
8019                        save_fd_on_redirect(redir->rd_fd, /*avoid:*/ 0, sqp);
8020                        /* for REDIRECT_HEREDOC2, rd_filename holds _contents_
8021                         * of the heredoc */
8022                        debug_printf_redir("set heredoc '%s'\n",
8023                                        redir->rd_filename);
8024                        setup_heredoc(redir);
8025                        continue;
8026                }
8027
8028                if (redir->rd_dup == REDIRFD_TO_FILE) {
8029                        /* "rd_fd<*>file" case (<*> is <,>,>>,<>) */
8030                        char *p;
8031                        int mode;
8032
8033                        if (redir->rd_filename == NULL) {
8034                                /* Examples:
8035                                 * "cmd >" (no filename)
8036                                 * "cmd > <file" (2nd redirect starts too early)
8037                                 */
8038                                syntax_error("invalid redirect");
8039                                continue;
8040                        }
8041                        mode = redir_table[redir->rd_type].mode;
8042                        p = expand_string_to_string(redir->rd_filename,
8043                                EXP_FLAG_ESC_GLOB_CHARS, /*unbackslash:*/ 1);
8044                        newfd = open_or_warn(p, mode);
8045                        free(p);
8046                        if (newfd < 0) {
8047                                /* Error message from open_or_warn can be lost
8048                                 * if stderr has been redirected, but bash
8049                                 * and ash both lose it as well
8050                                 * (though zsh doesn't!)
8051                                 */
8052                                return 1;
8053                        }
8054                        if (newfd == redir->rd_fd && sqp) {
8055                                /* open() gave us precisely the fd we wanted.
8056                                 * This means that this fd was not busy
8057                                 * (not opened to anywhere).
8058                                 * Remember to close it on restore:
8059                                 */
8060                                *sqp = add_squirrel_closed(*sqp, newfd);
8061                                debug_printf_redir("redir to previously closed fd %d\n", newfd);
8062                        }
8063                } else {
8064                        /* "rd_fd>&rd_dup" or "rd_fd>&-" case */
8065                        newfd = redir->rd_dup;
8066                }
8067
8068                if (newfd == redir->rd_fd)
8069                        continue;
8070
8071                /* if "N>FILE": move newfd to redir->rd_fd */
8072                /* if "N>&M": dup newfd to redir->rd_fd */
8073                /* if "N>&-": close redir->rd_fd (newfd is REDIRFD_CLOSE) */
8074
8075                closed = save_fd_on_redirect(redir->rd_fd, /*avoid:*/ newfd, sqp);
8076                if (newfd == REDIRFD_CLOSE) {
8077                        /* "N>&-" means "close me" */
8078                        if (!closed) {
8079                                /* ^^^ optimization: saving may already
8080                                 * have closed it. If not... */
8081                                close(redir->rd_fd);
8082                        }
8083                        /* Sometimes we do another close on restore, getting EBADF.
8084                         * Consider "echo 3>FILE 3>&-"
8085                         * first redirect remembers "need to close 3",
8086                         * and second redirect closes 3! Restore code then closes 3 again.
8087                         */
8088                } else {
8089                        /* if newfd is a script fd or saved fd, simulate EBADF */
8090                        if (internally_opened_fd(newfd, sqp && sqp != ERR_PTR ? *sqp : NULL)) {
8091                                //errno = EBADF;
8092                                //bb_perror_msg_and_die("can't duplicate file descriptor");
8093                                newfd = -1; /* same effect as code above */
8094                        }
8095                        xdup2(newfd, redir->rd_fd);
8096                        if (redir->rd_dup == REDIRFD_TO_FILE)
8097                                /* "rd_fd > FILE" */
8098                                close(newfd);
8099                        /* else: "rd_fd > rd_dup" */
8100                }
8101        }
8102        return 0;
8103}
8104
8105static char *find_in_path(const char *arg)
8106{
8107        char *ret = NULL;
8108        const char *PATH = get_local_var_value("PATH");
8109
8110        if (!PATH)
8111                return NULL;
8112
8113        while (1) {
8114                const char *end = strchrnul(PATH, ':');
8115                int sz = end - PATH; /* must be int! */
8116
8117                free(ret);
8118                if (sz != 0) {
8119                        ret = xasprintf("%.*s/%s", sz, PATH, arg);
8120                } else {
8121                        /* We have xxx::yyyy in $PATH,
8122                         * it means "use current dir" */
8123                        ret = xstrdup(arg);
8124                }
8125                if (access(ret, F_OK) == 0)
8126                        break;
8127
8128                if (*end == '\0') {
8129                        free(ret);
8130                        return NULL;
8131                }
8132                PATH = end + 1;
8133        }
8134
8135        return ret;
8136}
8137
8138static const struct built_in_command *find_builtin_helper(const char *name,
8139                const struct built_in_command *x,
8140                const struct built_in_command *end)
8141{
8142        while (x != end) {
8143                if (strcmp(name, x->b_cmd) != 0) {
8144                        x++;
8145                        continue;
8146                }
8147                debug_printf_exec("found builtin '%s'\n", name);
8148                return x;
8149        }
8150        return NULL;
8151}
8152static const struct built_in_command *find_builtin1(const char *name)
8153{
8154        return find_builtin_helper(name, bltins1, &bltins1[ARRAY_SIZE(bltins1)]);
8155}
8156static const struct built_in_command *find_builtin(const char *name)
8157{
8158        const struct built_in_command *x = find_builtin1(name);
8159        if (x)
8160                return x;
8161        return find_builtin_helper(name, bltins2, &bltins2[ARRAY_SIZE(bltins2)]);
8162}
8163
8164#if ENABLE_HUSH_JOB && EDITING_HAS_get_exe_name
8165static const char * FAST_FUNC get_builtin_name(int i)
8166{
8167        if (/*i >= 0 && */ i < ARRAY_SIZE(bltins1)) {
8168                return bltins1[i].b_cmd;
8169        }
8170        i -= ARRAY_SIZE(bltins1);
8171        if (i < ARRAY_SIZE(bltins2)) {
8172                return bltins2[i].b_cmd;
8173        }
8174        return NULL;
8175}
8176#endif
8177
8178static void remove_nested_vars(void)
8179{
8180        struct variable *cur;
8181        struct variable **cur_pp;
8182
8183        cur_pp = &G.top_var;
8184        while ((cur = *cur_pp) != NULL) {
8185                if (cur->var_nest_level <= G.var_nest_level) {
8186                        cur_pp = &cur->next;
8187                        continue;
8188                }
8189                /* Unexport */
8190                if (cur->flg_export) {
8191                        debug_printf_env("unexporting nested '%s'/%u\n", cur->varstr, cur->var_nest_level);
8192                        bb_unsetenv(cur->varstr);
8193                }
8194                /* Remove from global list */
8195                *cur_pp = cur->next;
8196                /* Free */
8197                if (!cur->max_len) {
8198                        debug_printf_env("freeing nested '%s'/%u\n", cur->varstr, cur->var_nest_level);
8199                        free(cur->varstr);
8200                }
8201                free(cur);
8202        }
8203}
8204
8205static void enter_var_nest_level(void)
8206{
8207        G.var_nest_level++;
8208        debug_printf_env("var_nest_level++ %u\n", G.var_nest_level);
8209
8210        /* Try: f() { echo -n .; f; }; f
8211         * struct variable::var_nest_level is uint16_t,
8212         * thus limiting recursion to < 2^16.
8213         * In any case, with 8 Mbyte stack SEGV happens
8214         * not too long after 2^16 recursions anyway.
8215         */
8216        if (G.var_nest_level > 0xff00)
8217                bb_error_msg_and_die("fatal recursion (depth %u)", G.var_nest_level);
8218}
8219
8220static void leave_var_nest_level(void)
8221{
8222        G.var_nest_level--;
8223        debug_printf_env("var_nest_level-- %u\n", G.var_nest_level);
8224        if (HUSH_DEBUG && (int)G.var_nest_level < 0)
8225                bb_simple_error_msg_and_die("BUG: nesting underflow");
8226
8227        remove_nested_vars();
8228}
8229
8230#if ENABLE_HUSH_FUNCTIONS
8231static struct function **find_function_slot(const char *name)
8232{
8233        struct function *funcp;
8234        struct function **funcpp = &G.top_func;
8235
8236        while ((funcp = *funcpp) != NULL) {
8237                if (strcmp(name, funcp->name) == 0) {
8238                        debug_printf_exec("found function '%s'\n", name);
8239                        break;
8240                }
8241                funcpp = &funcp->next;
8242        }
8243        return funcpp;
8244}
8245
8246static ALWAYS_INLINE const struct function *find_function(const char *name)
8247{
8248        const struct function *funcp = *find_function_slot(name);
8249        return funcp;
8250}
8251
8252/* Note: takes ownership on name ptr */
8253static struct function *new_function(char *name)
8254{
8255        struct function **funcpp = find_function_slot(name);
8256        struct function *funcp = *funcpp;
8257
8258        if (funcp != NULL) {
8259                struct command *cmd = funcp->parent_cmd;
8260                debug_printf_exec("func %p parent_cmd %p\n", funcp, cmd);
8261                if (!cmd) {
8262                        debug_printf_exec("freeing & replacing function '%s'\n", funcp->name);
8263                        free(funcp->name);
8264                        /* Note: if !funcp->body, do not free body_as_string!
8265                         * This is a special case of "-F name body" function:
8266                         * body_as_string was not malloced! */
8267                        if (funcp->body) {
8268                                free_pipe_list(funcp->body);
8269# if !BB_MMU
8270                                free(funcp->body_as_string);
8271# endif
8272                        }
8273                } else {
8274                        debug_printf_exec("reinserting in tree & replacing function '%s'\n", funcp->name);
8275                        cmd->argv[0] = funcp->name;
8276                        cmd->group = funcp->body;
8277# if !BB_MMU
8278                        cmd->group_as_string = funcp->body_as_string;
8279# endif
8280                }
8281        } else {
8282                debug_printf_exec("remembering new function '%s'\n", name);
8283                funcp = *funcpp = xzalloc(sizeof(*funcp));
8284                /*funcp->next = NULL;*/
8285        }
8286
8287        funcp->name = name;
8288        return funcp;
8289}
8290
8291# if ENABLE_HUSH_UNSET
8292static void unset_func(const char *name)
8293{
8294        struct function **funcpp = find_function_slot(name);
8295        struct function *funcp = *funcpp;
8296
8297        if (funcp != NULL) {
8298                debug_printf_exec("freeing function '%s'\n", funcp->name);
8299                *funcpp = funcp->next;
8300                /* funcp is unlinked now, deleting it.
8301                 * Note: if !funcp->body, the function was created by
8302                 * "-F name body", do not free ->body_as_string
8303                 * and ->name as they were not malloced. */
8304                if (funcp->body) {
8305                        free_pipe_list(funcp->body);
8306                        free(funcp->name);
8307#  if !BB_MMU
8308                        free(funcp->body_as_string);
8309#  endif
8310                }
8311                free(funcp);
8312        }
8313}
8314# endif
8315
8316# if BB_MMU
8317#define exec_function(to_free, funcp, argv) \
8318        exec_function(funcp, argv)
8319# endif
8320static void exec_function(char ***to_free,
8321                const struct function *funcp,
8322                char **argv) NORETURN;
8323static void exec_function(char ***to_free,
8324                const struct function *funcp,
8325                char **argv)
8326{
8327# if BB_MMU
8328        int n;
8329
8330        argv[0] = G.global_argv[0];
8331        G.global_argv = argv;
8332        G.global_argc = n = 1 + string_array_len(argv + 1);
8333
8334// Example when we are here: "cmd | func"
8335// func will run with saved-redirect fds open.
8336// $ f() { echo /proc/self/fd/*; }
8337// $ true | f
8338// /proc/self/fd/0 /proc/self/fd/1 /proc/self/fd/2 /proc/self/fd/255 /proc/self/fd/3
8339// stdio^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ G_interactive_fd^ DIR fd for glob
8340// Same in script:
8341// $ . ./SCRIPT
8342// /proc/self/fd/0 /proc/self/fd/1 /proc/self/fd/2 /proc/self/fd/255 /proc/self/fd/3 /proc/self/fd/4
8343// stdio^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ G_interactive_fd^ opened ./SCRIPT DIR fd for glob
8344// They are CLOEXEC so external programs won't see them, but
8345// for "more correctness" we might want to close those extra fds here:
8346//?     close_saved_fds_and_FILE_fds();
8347
8348        /* "we are in a function, ok to use return" */
8349        G_flag_return_in_progress = -1;
8350        enter_var_nest_level();
8351        IF_HUSH_LOCAL(G.func_nest_level++;)
8352
8353        /* On MMU, funcp->body is always non-NULL */
8354        n = run_list(funcp->body);
8355        _exit(n);
8356# else
8357//?     close_saved_fds_and_FILE_fds();
8358
8359//TODO: check whether "true | func_with_return" works
8360
8361        re_execute_shell(to_free,
8362                        funcp->body_as_string,
8363                        G.global_argv[0],
8364                        argv + 1,
8365                        NULL);
8366# endif
8367}
8368
8369static int run_function(const struct function *funcp, char **argv)
8370{
8371        int rc;
8372        save_arg_t sv;
8373        smallint sv_flg;
8374
8375        save_and_replace_G_args(&sv, argv);
8376
8377        /* "We are in function, ok to use return" */
8378        sv_flg = G_flag_return_in_progress;
8379        G_flag_return_in_progress = -1;
8380
8381        /* Make "local" variables properly shadow previous ones */
8382        IF_HUSH_LOCAL(enter_var_nest_level();)
8383        IF_HUSH_LOCAL(G.func_nest_level++;)
8384
8385        /* On MMU, funcp->body is always non-NULL */
8386# if !BB_MMU
8387        if (!funcp->body) {
8388                /* Function defined by -F */
8389                parse_and_run_string(funcp->body_as_string);
8390                rc = G.last_exitcode;
8391        } else
8392# endif
8393        {
8394                rc = run_list(funcp->body);
8395        }
8396
8397        IF_HUSH_LOCAL(G.func_nest_level--;)
8398        IF_HUSH_LOCAL(leave_var_nest_level();)
8399
8400        G_flag_return_in_progress = sv_flg;
8401# if ENABLE_HUSH_TRAP
8402        debug_printf_exec("G.return_exitcode=-1\n");
8403        G.return_exitcode = -1; /* invalidate stashed return value */
8404# endif
8405
8406        restore_G_args(&sv, argv);
8407
8408        return rc;
8409}
8410#endif /* ENABLE_HUSH_FUNCTIONS */
8411
8412
8413#if BB_MMU
8414#define exec_builtin(to_free, x, argv) \
8415        exec_builtin(x, argv)
8416#else
8417#define exec_builtin(to_free, x, argv) \
8418        exec_builtin(to_free, argv)
8419#endif
8420static void exec_builtin(char ***to_free,
8421                const struct built_in_command *x,
8422                char **argv) NORETURN;
8423static void exec_builtin(char ***to_free,
8424                const struct built_in_command *x,
8425                char **argv)
8426{
8427#if BB_MMU
8428        int rcode;
8429//?     close_saved_fds_and_FILE_fds();
8430        rcode = x->b_function(argv);
8431        fflush_all();
8432        _exit(rcode);
8433#else
8434        fflush_all();
8435        /* On NOMMU, we must never block!
8436         * Example: { sleep 99 | read line; } & echo Ok
8437         */
8438        re_execute_shell(to_free,
8439                        argv[0],
8440                        G.global_argv[0],
8441                        G.global_argv + 1,
8442                        argv);
8443#endif
8444}
8445
8446
8447static void execvp_or_die(char **argv) NORETURN;
8448static void execvp_or_die(char **argv)
8449{
8450        int e;
8451        debug_printf_exec("execing '%s'\n", argv[0]);
8452        /* Don't propagate SIG_IGN to the child */
8453        if (SPECIAL_JOBSTOP_SIGS != 0)
8454                switch_off_special_sigs(G.special_sig_mask & SPECIAL_JOBSTOP_SIGS);
8455        execvp(argv[0], argv);
8456        e = 2;
8457        if (errno == EACCES) e = 126;
8458        if (errno == ENOENT) e = 127;
8459        bb_perror_msg("can't execute '%s'", argv[0]);
8460        _exit(e);
8461}
8462
8463#if ENABLE_HUSH_MODE_X
8464static void x_mode_print_optionally_squoted(const char *str)
8465{
8466        unsigned len;
8467        const char *cp;
8468
8469        cp = str;
8470
8471        /* the set of chars which-cause-string-to-be-squoted mimics bash */
8472        /* test a char with: bash -c 'set -x; echo "CH"' */
8473        if (str[strcspn(str, "\\\"'`$(){}[]<>;#&|~*?!^"
8474                        " " "\001\002\003\004\005\006\007"
8475                        "\010\011\012\013\014\015\016\017"
8476                        "\020\021\022\023\024\025\026\027"
8477                        "\030\031\032\033\034\035\036\037"
8478                        )
8479                ] == '\0'
8480        ) {
8481                /* string has no special chars */
8482                x_mode_addstr(str);
8483                return;
8484        }
8485
8486        cp = str;
8487        for (;;) {
8488                /* print '....' up to EOL or first squote */
8489                len = (int)(strchrnul(cp, '\'') - cp);
8490                if (len != 0) {
8491                        x_mode_addchr('\'');
8492                        x_mode_addblock(cp, len);
8493                        x_mode_addchr('\'');
8494                        cp += len;
8495                }
8496                if (*cp == '\0')
8497                        break;
8498                /* string contains squote(s), print them as \' */
8499                x_mode_addchr('\\');
8500                x_mode_addchr('\'');
8501                cp++;
8502        }
8503}
8504static void dump_cmd_in_x_mode(char **argv)
8505{
8506        if (G_x_mode && argv) {
8507                unsigned n;
8508
8509                /* "+[+++...][ cmd...]\n\0" */
8510                x_mode_prefix();
8511                n = 0;
8512                while (argv[n]) {
8513                        x_mode_addchr(' ');
8514                        if (argv[n][0] == '\0') {
8515                                x_mode_addchr('\'');
8516                                x_mode_addchr('\'');
8517                        } else {
8518                                x_mode_print_optionally_squoted(argv[n]);
8519                        }
8520                        n++;
8521                }
8522                x_mode_flush();
8523        }
8524}
8525#else
8526# define dump_cmd_in_x_mode(argv) ((void)0)
8527#endif
8528
8529#if ENABLE_HUSH_COMMAND
8530static void if_command_vV_print_and_exit(char opt_vV, char *cmd, const char *explanation)
8531{
8532        char *to_free;
8533
8534        if (!opt_vV)
8535                return;
8536
8537        to_free = NULL;
8538        if (!explanation) {
8539                char *path = getenv("PATH");
8540                explanation = to_free = find_executable(cmd, &path); /* path == NULL is ok */
8541                if (!explanation)
8542                        _exit(1); /* PROG was not found */
8543                if (opt_vV != 'V')
8544                        cmd = to_free; /* -v PROG prints "/path/to/PROG" */
8545        }
8546        printf((opt_vV == 'V') ? "%s is %s\n" : "%s\n", cmd, explanation);
8547        free(to_free);
8548        fflush_all();
8549        _exit(0);
8550}
8551#else
8552# define if_command_vV_print_and_exit(a,b,c) ((void)0)
8553#endif
8554
8555#if BB_MMU
8556#define pseudo_exec_argv(nommu_save, argv, assignment_cnt, argv_expanded) \
8557        pseudo_exec_argv(argv, assignment_cnt, argv_expanded)
8558#define pseudo_exec(nommu_save, command, argv_expanded) \
8559        pseudo_exec(command, argv_expanded)
8560#endif
8561
8562/* Called after [v]fork() in run_pipe, or from builtin_exec.
8563 * Never returns.
8564 * Don't exit() here.  If you don't exec, use _exit instead.
8565 * The at_exit handlers apparently confuse the calling process,
8566 * in particular stdin handling. Not sure why? -- because of vfork! (vda)
8567 */
8568static void pseudo_exec_argv(nommu_save_t *nommu_save,
8569                char **argv, int assignment_cnt,
8570                char **argv_expanded) NORETURN;
8571static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save,
8572                char **argv, int assignment_cnt,
8573                char **argv_expanded)
8574{
8575        const struct built_in_command *x;
8576        struct variable **sv_shadowed;
8577        char **new_env;
8578        IF_HUSH_COMMAND(char opt_vV = 0;)
8579        IF_HUSH_FUNCTIONS(const struct function *funcp;)
8580
8581        new_env = expand_assignments(argv, assignment_cnt);
8582        dump_cmd_in_x_mode(new_env);
8583
8584        if (!argv[assignment_cnt]) {
8585                /* Case when we are here: ... | var=val | ...
8586                 * (note that we do not exit early, i.e., do not optimize out
8587                 * expand_assignments(): think about ... | var=`sleep 1` | ...
8588                 */
8589                free_strings(new_env);
8590                _exit(EXIT_SUCCESS);
8591        }
8592
8593        sv_shadowed = G.shadowed_vars_pp;
8594#if BB_MMU
8595        G.shadowed_vars_pp = NULL; /* "don't save, free them instead" */
8596#else
8597        G.shadowed_vars_pp = &nommu_save->old_vars;
8598        G.var_nest_level++;
8599#endif
8600        set_vars_and_save_old(new_env);
8601        G.shadowed_vars_pp = sv_shadowed;
8602
8603        if (argv_expanded) {
8604                argv = argv_expanded;
8605        } else {
8606                argv = expand_strvec_to_strvec(argv + assignment_cnt);
8607#if !BB_MMU
8608                nommu_save->argv = argv;
8609#endif
8610        }
8611        dump_cmd_in_x_mode(argv);
8612
8613#if ENABLE_FEATURE_SH_STANDALONE || BB_MMU
8614        if (strchr(argv[0], '/') != NULL)
8615                goto skip;
8616#endif
8617
8618#if ENABLE_HUSH_FUNCTIONS
8619        /* Check if the command matches any functions (this goes before bltins) */
8620        funcp = find_function(argv[0]);
8621        if (funcp)
8622                exec_function(&nommu_save->argv_from_re_execing, funcp, argv);
8623#endif
8624
8625#if ENABLE_HUSH_COMMAND
8626        /* "command BAR": run BAR without looking it up among functions
8627         * "command -v BAR": print "BAR" or "/path/to/BAR"; or exit 1
8628         * "command -V BAR": print "BAR is {a function,a shell builtin,/path/to/BAR}"
8629         */
8630        while (strcmp(argv[0], "command") == 0 && argv[1]) {
8631                char *p;
8632
8633                argv++;
8634                p = *argv;
8635                if (p[0] != '-' || !p[1])
8636                        continue; /* bash allows "command command command [-OPT] BAR" */
8637
8638                for (;;) {
8639                        p++;
8640                        switch (*p) {
8641                        case '\0':
8642                                argv++;
8643                                p = *argv;
8644                                if (p[0] != '-' || !p[1])
8645                                        goto after_opts;
8646                                continue; /* next arg is also -opts, process it too */
8647                        case 'v':
8648                        case 'V':
8649                                opt_vV = *p;
8650                                continue;
8651                        default:
8652                                bb_error_msg_and_die("%s: %s: invalid option", "command", argv[0]);
8653                        }
8654                }
8655        }
8656 after_opts:
8657# if ENABLE_HUSH_FUNCTIONS
8658        if (opt_vV && find_function(argv[0]))
8659                if_command_vV_print_and_exit(opt_vV, argv[0], "a function");
8660# endif
8661#endif
8662
8663        /* Check if the command matches any of the builtins.
8664         * Depending on context, this might be redundant.  But it's
8665         * easier to waste a few CPU cycles than it is to figure out
8666         * if this is one of those cases.
8667         */
8668        /* Why "BB_MMU ? :" difference in logic? -
8669         * On NOMMU, it is more expensive to re-execute shell
8670         * just in order to run echo or test builtin.
8671         * It's better to skip it here and run corresponding
8672         * non-builtin later. */
8673        x = BB_MMU ? find_builtin(argv[0]) : find_builtin1(argv[0]);
8674        if (x) {
8675                if_command_vV_print_and_exit(opt_vV, argv[0], "a shell builtin");
8676                exec_builtin(&nommu_save->argv_from_re_execing, x, argv);
8677        }
8678
8679#if ENABLE_FEATURE_SH_STANDALONE
8680        /* Check if the command matches any busybox applets */
8681        {
8682                int a = find_applet_by_name(argv[0]);
8683                if (a >= 0) {
8684                        if_command_vV_print_and_exit(opt_vV, argv[0], "an applet");
8685# if BB_MMU /* see above why on NOMMU it is not allowed */
8686                        if (APPLET_IS_NOEXEC(a)) {
8687                                /* Do not leak open fds from opened script files etc.
8688                                 * Testcase: interactive "ls -l /proc/self/fd"
8689                                 * should not show tty fd open.
8690                                 */
8691                                close_saved_fds_and_FILE_fds();
8692//FIXME: should also close saved redir fds
8693//This casuses test failures in
8694//redir_children_should_not_see_saved_fd_2.tests
8695//redir_children_should_not_see_saved_fd_3.tests
8696//if you replace "busybox find" with just "find" in them
8697                                /* Without this, "rm -i FILE" can't be ^C'ed: */
8698                                switch_off_special_sigs(G.special_sig_mask);
8699                                debug_printf_exec("running applet '%s'\n", argv[0]);
8700                                run_noexec_applet_and_exit(a, argv[0], argv);
8701                        }
8702# endif
8703                        /* Re-exec ourselves */
8704                        debug_printf_exec("re-execing applet '%s'\n", argv[0]);
8705                        /* Don't propagate SIG_IGN to the child */
8706                        if (SPECIAL_JOBSTOP_SIGS != 0)
8707                                switch_off_special_sigs(G.special_sig_mask & SPECIAL_JOBSTOP_SIGS);
8708                        execv(bb_busybox_exec_path, argv);
8709                        /* If they called chroot or otherwise made the binary no longer
8710                         * executable, fall through */
8711                }
8712        }
8713#endif
8714
8715#if ENABLE_FEATURE_SH_STANDALONE || BB_MMU
8716 skip:
8717#endif
8718        if_command_vV_print_and_exit(opt_vV, argv[0], NULL);
8719        execvp_or_die(argv);
8720}
8721
8722/* Called after [v]fork() in run_pipe
8723 */
8724static void pseudo_exec(nommu_save_t *nommu_save,
8725                struct command *command,
8726                char **argv_expanded) NORETURN;
8727static void pseudo_exec(nommu_save_t *nommu_save,
8728                struct command *command,
8729                char **argv_expanded)
8730{
8731#if ENABLE_HUSH_FUNCTIONS
8732        if (command->cmd_type == CMD_FUNCDEF) {
8733                /* Ignore funcdefs in pipes:
8734                 * true | f() { cmd }
8735                 */
8736                _exit(0);
8737        }
8738#endif
8739
8740        if (command->argv) {
8741                pseudo_exec_argv(nommu_save, command->argv,
8742                                command->assignment_cnt, argv_expanded);
8743        }
8744
8745        if (command->group) {
8746                /* Cases when we are here:
8747                 * ( list )
8748                 * { list } &
8749                 * ... | ( list ) | ...
8750                 * ... | { list } | ...
8751                 */
8752#if BB_MMU
8753                int rcode;
8754                debug_printf_exec("pseudo_exec: run_list\n");
8755                reset_traps_to_defaults();
8756                rcode = run_list(command->group);
8757                /* OK to leak memory by not calling free_pipe_list,
8758                 * since this process is about to exit */
8759                _exit(rcode);
8760#else
8761                re_execute_shell(&nommu_save->argv_from_re_execing,
8762                                command->group_as_string,
8763                                G.global_argv[0],
8764                                G.global_argv + 1,
8765                                NULL);
8766#endif
8767        }
8768
8769        /* Case when we are here: ... | >file */
8770        debug_printf_exec("pseudo_exec'ed null command\n");
8771        _exit(EXIT_SUCCESS);
8772}
8773
8774#if ENABLE_HUSH_JOB
8775static const char *get_cmdtext(struct pipe *pi)
8776{
8777        char **argv;
8778        char *p;
8779        int len;
8780
8781        /* This is subtle. ->cmdtext is created only on first backgrounding.
8782         * (Think "cat, <ctrl-z>, fg, <ctrl-z>, fg, <ctrl-z>...." here...)
8783         * On subsequent bg argv is trashed, but we won't use it */
8784        if (pi->cmdtext)
8785                return pi->cmdtext;
8786
8787        argv = pi->cmds[0].argv;
8788        if (!argv) {
8789                pi->cmdtext = xzalloc(1);
8790                return pi->cmdtext;
8791        }
8792        len = 0;
8793        do {
8794                len += strlen(*argv) + 1;
8795        } while (*++argv);
8796        p = xmalloc(len);
8797        pi->cmdtext = p;
8798        argv = pi->cmds[0].argv;
8799        do {
8800                p = stpcpy(p, *argv);
8801                *p++ = ' ';
8802        } while (*++argv);
8803        p[-1] = '\0';
8804        return pi->cmdtext;
8805}
8806
8807static void remove_job_from_table(struct pipe *pi)
8808{
8809        struct pipe *prev_pipe;
8810
8811        if (pi == G.job_list) {
8812                G.job_list = pi->next;
8813        } else {
8814                prev_pipe = G.job_list;
8815                while (prev_pipe->next != pi)
8816                        prev_pipe = prev_pipe->next;
8817                prev_pipe->next = pi->next;
8818        }
8819        G.last_jobid = 0;
8820        if (G.job_list)
8821                G.last_jobid = G.job_list->jobid;
8822}
8823
8824static void delete_finished_job(struct pipe *pi)
8825{
8826        remove_job_from_table(pi);
8827        free_pipe(pi);
8828}
8829
8830static void clean_up_last_dead_job(void)
8831{
8832        if (G.job_list && !G.job_list->alive_cmds)
8833                delete_finished_job(G.job_list);
8834}
8835
8836static void insert_job_into_table(struct pipe *pi)
8837{
8838        struct pipe *job, **jobp;
8839        int i;
8840
8841        clean_up_last_dead_job();
8842
8843        /* Find the end of the list, and find next job ID to use */
8844        i = 0;
8845        jobp = &G.job_list;
8846        while ((job = *jobp) != NULL) {
8847                if (job->jobid > i)
8848                        i = job->jobid;
8849                jobp = &job->next;
8850        }
8851        pi->jobid = i + 1;
8852
8853        /* Create a new job struct at the end */
8854        job = *jobp = xmemdup(pi, sizeof(*pi));
8855        job->next = NULL;
8856        job->cmds = xzalloc(sizeof(pi->cmds[0]) * pi->num_cmds);
8857        /* Cannot copy entire pi->cmds[] vector! This causes double frees */
8858        for (i = 0; i < pi->num_cmds; i++) {
8859                job->cmds[i].pid = pi->cmds[i].pid;
8860                /* all other fields are not used and stay zero */
8861        }
8862        job->cmdtext = xstrdup(get_cmdtext(pi));
8863
8864        if (G_interactive_fd)
8865                printf("[%u] %u %s\n", job->jobid, (unsigned)job->cmds[0].pid, job->cmdtext);
8866        G.last_jobid = job->jobid;
8867}
8868#endif /* JOB */
8869
8870static int job_exited_or_stopped(struct pipe *pi)
8871{
8872        int rcode, i;
8873
8874        if (pi->alive_cmds != pi->stopped_cmds)
8875                return -1;
8876
8877        /* All processes in fg pipe have exited or stopped */
8878        rcode = 0;
8879        i = pi->num_cmds;
8880        while (--i >= 0) {
8881                rcode = pi->cmds[i].cmd_exitcode;
8882                /* usually last process gives overall exitstatus,
8883                 * but with "set -o pipefail", last *failed* process does */
8884                if (G.o_opt[OPT_O_PIPEFAIL] == 0 || rcode != 0)
8885                        break;
8886        }
8887        IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
8888        return rcode;
8889}
8890
8891static int process_wait_result(struct pipe *fg_pipe, pid_t childpid, int status)
8892{
8893#if ENABLE_HUSH_JOB
8894        struct pipe *pi;
8895#endif
8896        int i, dead;
8897
8898        dead = WIFEXITED(status) || WIFSIGNALED(status);
8899
8900#if DEBUG_JOBS
8901        if (WIFSTOPPED(status))
8902                debug_printf_jobs("pid %d stopped by sig %d (exitcode %d)\n",
8903                                childpid, WSTOPSIG(status), WEXITSTATUS(status));
8904        if (WIFSIGNALED(status))
8905                debug_printf_jobs("pid %d killed by sig %d (exitcode %d)\n",
8906                                childpid, WTERMSIG(status), WEXITSTATUS(status));
8907        if (WIFEXITED(status))
8908                debug_printf_jobs("pid %d exited, exitcode %d\n",
8909                                childpid, WEXITSTATUS(status));
8910#endif
8911        /* Were we asked to wait for a fg pipe? */
8912        if (fg_pipe) {
8913                i = fg_pipe->num_cmds;
8914
8915                while (--i >= 0) {
8916                        int rcode;
8917
8918                        debug_printf_jobs("check pid %d\n", fg_pipe->cmds[i].pid);
8919                        if (fg_pipe->cmds[i].pid != childpid)
8920                                continue;
8921                        if (dead) {
8922                                int ex;
8923                                fg_pipe->cmds[i].pid = 0;
8924                                fg_pipe->alive_cmds--;
8925                                ex = WEXITSTATUS(status);
8926                                /* bash prints killer signal's name for *last*
8927                                 * process in pipe (prints just newline for SIGINT/SIGPIPE).
8928                                 * Mimic this. Example: "sleep 5" + (^\ or kill -QUIT)
8929                                 */
8930                                if (WIFSIGNALED(status)) {
8931                                        int sig = WTERMSIG(status);
8932#if ENABLE_HUSH_JOB
8933                                        if (G.run_list_level == 1
8934                                        /* ^^^^^ Do not print in nested contexts, example:
8935                                         * echo `sleep 1; sh -c 'kill -9 $$'` - prints "137", NOT "Killed 137"
8936                                         */
8937                                         && i == fg_pipe->num_cmds-1
8938                                        ) {
8939                                                /* strsignal() is for bash compat. ~600 bloat versus bbox's get_signame() */
8940                                                puts(sig == SIGINT || sig == SIGPIPE ? "" : strsignal(sig));
8941                                        }
8942#endif
8943                                        /* TODO: if (WCOREDUMP(status)) + " (core dumped)"; */
8944                                        /* MIPS has 128 sigs (1..128), if sig==128,
8945                                         * 128 + sig would result in exitcode 256 -> 0!
8946                                         */
8947                                        ex = 128 | sig;
8948                                }
8949                                fg_pipe->cmds[i].cmd_exitcode = ex;
8950                        } else {
8951                                fg_pipe->stopped_cmds++;
8952                        }
8953                        debug_printf_jobs("fg_pipe: alive_cmds %d stopped_cmds %d\n",
8954                                        fg_pipe->alive_cmds, fg_pipe->stopped_cmds);
8955                        rcode = job_exited_or_stopped(fg_pipe);
8956                        if (rcode >= 0) {
8957/* Note: *non-interactive* bash does not continue if all processes in fg pipe
8958 * are stopped. Testcase: "cat | cat" in a script (not on command line!)
8959 * and "killall -STOP cat" */
8960                                if (G_interactive_fd) {
8961#if ENABLE_HUSH_JOB
8962                                        if (fg_pipe->alive_cmds != 0)
8963                                                insert_job_into_table(fg_pipe);
8964#endif
8965                                        return rcode;
8966                                }
8967                                if (fg_pipe->alive_cmds == 0)
8968                                        return rcode;
8969                        }
8970                        /* There are still running processes in the fg_pipe */
8971                        return -1;
8972                }
8973                /* It wasn't in fg_pipe, look for process in bg pipes */
8974        }
8975
8976#if ENABLE_HUSH_JOB
8977        /* We were asked to wait for bg or orphaned children */
8978        /* No need to remember exitcode in this case */
8979        for (pi = G.job_list; pi; pi = pi->next) {
8980                for (i = 0; i < pi->num_cmds; i++) {
8981                        if (pi->cmds[i].pid == childpid)
8982                                goto found_pi_and_prognum;
8983                }
8984        }
8985        /* Happens when shell is used as init process (init=/bin/sh) */
8986        debug_printf("checkjobs: pid %d was not in our list!\n", childpid);
8987        return -1; /* this wasn't a process from fg_pipe */
8988
8989 found_pi_and_prognum:
8990        if (dead) {
8991                /* child exited */
8992                int rcode = WEXITSTATUS(status);
8993                if (WIFSIGNALED(status))
8994                        /* NB: not 128 + sig, MIPS has sig 128 */
8995                        rcode = 128 | WTERMSIG(status);
8996                pi->cmds[i].cmd_exitcode = rcode;
8997                if (G.last_bg_pid == pi->cmds[i].pid)
8998                        G.last_bg_pid_exitcode = rcode;
8999                pi->cmds[i].pid = 0;
9000                pi->alive_cmds--;
9001                if (!pi->alive_cmds) {
9002# if ENABLE_HUSH_BASH_COMPAT
9003                        G.dead_job_exitcode = job_exited_or_stopped(pi);
9004# endif
9005                        if (G_interactive_fd) {
9006                                printf(JOB_STATUS_FORMAT, pi->jobid,
9007                                                "Done", pi->cmdtext);
9008                                delete_finished_job(pi);
9009                        } else {
9010/*
9011 * bash deletes finished jobs from job table only in interactive mode,
9012 * after "jobs" cmd, or if pid of a new process matches one of the old ones
9013 * (see cleanup_dead_jobs(), delete_old_job(), J_NOTIFIED in bash source).
9014 * Testcase script: "(exit 3) & sleep 1; wait %1; echo $?" prints 3 in bash.
9015 * We only retain one "dead" job, if it's the single job on the list.
9016 * This covers most of real-world scenarios where this is useful.
9017 */
9018                                if (pi != G.job_list)
9019                                        delete_finished_job(pi);
9020                        }
9021                }
9022        } else {
9023                /* child stopped */
9024                pi->stopped_cmds++;
9025        }
9026#endif
9027        return -1; /* this wasn't a process from fg_pipe */
9028}
9029
9030/* Check to see if any processes have exited -- if they have,
9031 * figure out why and see if a job has completed.
9032 *
9033 * If non-NULL fg_pipe: wait for its completion or stop.
9034 * Return its exitcode or zero if stopped.
9035 *
9036 * Alternatively (fg_pipe == NULL, waitfor_pid != 0):
9037 * waitpid(WNOHANG), if waitfor_pid exits or stops, return exitcode+1,
9038 * else return <0 if waitpid errors out (e.g. ECHILD: nothing to wait for)
9039 * or 0 if no children changed status.
9040 *
9041 * Alternatively (fg_pipe == NULL, waitfor_pid == 0),
9042 * return <0 if waitpid errors out (e.g. ECHILD: nothing to wait for)
9043 * or 0 if no children changed status.
9044 */
9045static int checkjobs(struct pipe *fg_pipe, pid_t waitfor_pid)
9046{
9047        int attributes;
9048        int status;
9049        int rcode = 0;
9050
9051        debug_printf_jobs("checkjobs %p\n", fg_pipe);
9052
9053        attributes = WUNTRACED;
9054        if (fg_pipe == NULL)
9055                attributes |= WNOHANG;
9056
9057        errno = 0;
9058#if ENABLE_HUSH_FAST
9059        if (G.handled_SIGCHLD == G.count_SIGCHLD) {
9060//bb_error_msg("[%d] checkjobs: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d children?:%d fg_pipe:%p",
9061//getpid(), G.count_SIGCHLD, G.handled_SIGCHLD, G.we_have_children, fg_pipe);
9062                /* There was neither fork nor SIGCHLD since last waitpid */
9063                /* Avoid doing waitpid syscall if possible */
9064                if (!G.we_have_children) {
9065                        errno = ECHILD;
9066                        return -1;
9067                }
9068                if (fg_pipe == NULL) { /* is WNOHANG set? */
9069                        /* We have children, but they did not exit
9070                         * or stop yet (we saw no SIGCHLD) */
9071                        return 0;
9072                }
9073                /* else: !WNOHANG, waitpid will block, can't short-circuit */
9074        }
9075#endif
9076
9077/* Do we do this right?
9078 * bash-3.00# sleep 20 | false
9079 * <ctrl-Z pressed>
9080 * [3]+  Stopped          sleep 20 | false
9081 * bash-3.00# echo $?
9082 * 1   <========== bg pipe is not fully done, but exitcode is already known!
9083 * [hush 1.14.0: yes we do it right]
9084 */
9085        while (1) {
9086                pid_t childpid;
9087#if ENABLE_HUSH_FAST
9088                int i;
9089                i = G.count_SIGCHLD;
9090#endif
9091                childpid = waitpid(-1, &status, attributes);
9092                if (childpid <= 0) {
9093                        if (childpid && errno != ECHILD)
9094                                bb_simple_perror_msg("waitpid");
9095#if ENABLE_HUSH_FAST
9096                        else { /* Until next SIGCHLD, waitpid's are useless */
9097                                G.we_have_children = (childpid == 0);
9098                                G.handled_SIGCHLD = i;
9099//bb_error_msg("[%d] checkjobs: waitpid returned <= 0, G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
9100                        }
9101#endif
9102                        /* ECHILD (no children), or 0 (no change in children status) */
9103                        rcode = childpid;
9104                        break;
9105                }
9106                rcode = process_wait_result(fg_pipe, childpid, status);
9107                if (rcode >= 0) {
9108                        /* fg_pipe exited or stopped */
9109                        break;
9110                }
9111                if (childpid == waitfor_pid) { /* "wait PID" */
9112                        debug_printf_exec("childpid==waitfor_pid:%d status:0x%08x\n", childpid, status);
9113                        rcode = WEXITSTATUS(status);
9114                        if (WIFSIGNALED(status))
9115                                rcode = 128 | WTERMSIG(status);
9116                        if (WIFSTOPPED(status))
9117                                /* bash: "cmd & wait $!" and cmd stops: $? = 128 | stopsig */
9118                                rcode = 128 | WSTOPSIG(status);
9119                        rcode++;
9120                        break; /* "wait PID" called us, give it exitcode+1 */
9121                }
9122#if ENABLE_HUSH_BASH_COMPAT
9123                if (-1 == waitfor_pid /* "wait -n" (wait for any one job) */
9124                 && G.dead_job_exitcode >= 0 /* some job did finish */
9125                ) {
9126                        debug_printf_exec("waitfor_pid:-1\n");
9127                        rcode = G.dead_job_exitcode + 1;
9128                        break;
9129                }
9130#endif
9131                /* This wasn't one of our processes, or */
9132                /* fg_pipe still has running processes, do waitpid again */
9133        } /* while (waitpid succeeds)... */
9134
9135        return rcode;
9136}
9137
9138#if ENABLE_HUSH_JOB
9139static int checkjobs_and_fg_shell(struct pipe *fg_pipe)
9140{
9141        pid_t p;
9142        int rcode = checkjobs(fg_pipe, 0 /*(no pid to wait for)*/);
9143        if (G_saved_tty_pgrp) {
9144                /* Job finished, move the shell to the foreground */
9145                p = getpgrp(); /* our process group id */
9146                debug_printf_jobs("fg'ing ourself: getpgrp()=%d\n", (int)p);
9147                tcsetpgrp(G_interactive_fd, p);
9148        }
9149        return rcode;
9150}
9151#endif
9152
9153/* Start all the jobs, but don't wait for anything to finish.
9154 * See checkjobs().
9155 *
9156 * Return code is normally -1, when the caller has to wait for children
9157 * to finish to determine the exit status of the pipe.  If the pipe
9158 * is a simple builtin command, however, the action is done by the
9159 * time run_pipe returns, and the exit code is provided as the
9160 * return value.
9161 *
9162 * Returns -1 only if started some children. IOW: we have to
9163 * mask out retvals of builtins etc with 0xff!
9164 *
9165 * The only case when we do not need to [v]fork is when the pipe
9166 * is single, non-backgrounded, non-subshell command. Examples:
9167 * cmd ; ...   { list } ; ...
9168 * cmd && ...  { list } && ...
9169 * cmd || ...  { list } || ...
9170 * If it is, then we can run cmd as a builtin, NOFORK,
9171 * or (if SH_STANDALONE) an applet, and we can run the { list }
9172 * with run_list. If it isn't one of these, we fork and exec cmd.
9173 *
9174 * Cases when we must fork:
9175 * non-single:   cmd | cmd
9176 * backgrounded: cmd &     { list } &
9177 * subshell:     ( list ) [&]
9178 */
9179#if !ENABLE_HUSH_MODE_X
9180#define redirect_and_varexp_helper(command, sqp, argv_expanded) \
9181        redirect_and_varexp_helper(command, sqp)
9182#endif
9183static int redirect_and_varexp_helper(
9184                struct command *command,
9185                struct squirrel **sqp,
9186                char **argv_expanded)
9187{
9188        /* Assignments occur before redirects. Try:
9189         * a=`sleep 1` sleep 2 3>/qwe/rty
9190         */
9191
9192        char **new_env = expand_assignments(command->argv, command->assignment_cnt);
9193        dump_cmd_in_x_mode(new_env);
9194        dump_cmd_in_x_mode(argv_expanded);
9195        /* this takes ownership of new_env[i] elements, and frees new_env: */
9196        set_vars_and_save_old(new_env);
9197
9198        return setup_redirects(command, sqp);
9199}
9200static NOINLINE int run_pipe(struct pipe *pi)
9201{
9202        static const char *const null_ptr = NULL;
9203
9204        int cmd_no;
9205        int next_infd;
9206        struct command *command;
9207        char **argv_expanded;
9208        char **argv;
9209        struct squirrel *squirrel = NULL;
9210        int rcode;
9211
9212        debug_printf_exec("run_pipe start: members:%d\n", pi->num_cmds);
9213        debug_enter();
9214
9215        /* Testcase: set -- q w e; (IFS='' echo "$*"; IFS=''; echo "$*"); echo "$*"
9216         * Result should be 3 lines: q w e, qwe, q w e
9217         */
9218        if (G.ifs_whitespace != G.ifs)
9219                free(G.ifs_whitespace);
9220        G.ifs = get_local_var_value("IFS");
9221        if (G.ifs) {
9222                char *p;
9223                G.ifs_whitespace = (char*)G.ifs;
9224                p = skip_whitespace(G.ifs);
9225                if (*p) {
9226                        /* Not all $IFS is whitespace */
9227                        char *d;
9228                        int len = p - G.ifs;
9229                        p = skip_non_whitespace(p);
9230                        G.ifs_whitespace = xmalloc(len + strlen(p) + 1); /* can overestimate */
9231                        d = mempcpy(G.ifs_whitespace, G.ifs, len);
9232                        while (*p) {
9233                                if (isspace(*p))
9234                                        *d++ = *p;
9235                                p++;
9236                        }
9237                        *d = '\0';
9238                }
9239        } else {
9240                G.ifs = defifs;
9241                G.ifs_whitespace = (char*)G.ifs;
9242        }
9243
9244        IF_HUSH_JOB(pi->pgrp = -1;)
9245        pi->stopped_cmds = 0;
9246        command = &pi->cmds[0];
9247        argv_expanded = NULL;
9248
9249        if (pi->num_cmds != 1
9250         || pi->followup == PIPE_BG
9251         || command->cmd_type == CMD_SUBSHELL
9252        ) {
9253                goto must_fork;
9254        }
9255
9256        pi->alive_cmds = 1;
9257
9258        debug_printf_exec(": group:%p argv:'%s'\n",
9259                command->group, command->argv ? command->argv[0] : "NONE");
9260
9261        if (command->group) {
9262#if ENABLE_HUSH_FUNCTIONS
9263                if (command->cmd_type == CMD_FUNCDEF) {
9264                        /* "executing" func () { list } */
9265                        struct function *funcp;
9266
9267                        funcp = new_function(command->argv[0]);
9268                        /* funcp->name is already set to argv[0] */
9269                        funcp->body = command->group;
9270# if !BB_MMU
9271                        funcp->body_as_string = command->group_as_string;
9272                        command->group_as_string = NULL;
9273# endif
9274                        command->group = NULL;
9275                        command->argv[0] = NULL;
9276                        debug_printf_exec("cmd %p has child func at %p\n", command, funcp);
9277                        funcp->parent_cmd = command;
9278                        command->child_func = funcp;
9279
9280                        debug_printf_exec("run_pipe: return EXIT_SUCCESS\n");
9281                        debug_leave();
9282                        return EXIT_SUCCESS;
9283                }
9284#endif
9285                /* { list } */
9286                debug_printf_exec("non-subshell group\n");
9287                rcode = 1; /* exitcode if redir failed */
9288                if (setup_redirects(command, &squirrel) == 0) {
9289                        debug_printf_exec(": run_list\n");
9290//FIXME: we need to pass squirrel down into run_list()
9291//for SH_STANDALONE case, or else this construct:
9292// { find /proc/self/fd; true; } >FILE; cmd2
9293//has no way of closing saved fd#1 for "find",
9294//and in SH_STANDALONE mode, "find" is not execed,
9295//therefore CLOEXEC on saved fd does not help.
9296                        rcode = run_list(command->group) & 0xff;
9297                }
9298                restore_redirects(squirrel);
9299                IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
9300                debug_leave();
9301                debug_printf_exec("run_pipe: return %d\n", rcode);
9302                return rcode;
9303        }
9304
9305        argv = command->argv ? command->argv : (char **) &null_ptr;
9306        {
9307                const struct built_in_command *x;
9308                IF_HUSH_FUNCTIONS(const struct function *funcp;)
9309                IF_NOT_HUSH_FUNCTIONS(enum { funcp = 0 };)
9310                struct variable **sv_shadowed;
9311                struct variable *old_vars;
9312
9313#if ENABLE_HUSH_LINENO_VAR
9314                G.execute_lineno = command->lineno;
9315#endif
9316
9317                if (argv[command->assignment_cnt] == NULL) {
9318                        /* Assignments, but no command.
9319                         * Ensure redirects take effect (that is, create files).
9320                         * Try "a=t >file"
9321                         */
9322                        unsigned i;
9323                        G.expand_exitcode = 0;
9324 only_assignments:
9325                        rcode = setup_redirects(command, &squirrel);
9326                        restore_redirects(squirrel);
9327
9328                        /* Set shell variables */
9329                        i = 0;
9330                        while (i < command->assignment_cnt) {
9331                                char *p = expand_string_to_string(argv[i],
9332                                                EXP_FLAG_ESC_GLOB_CHARS,
9333                                                /*unbackslash:*/ 1
9334                                );
9335#if ENABLE_HUSH_MODE_X
9336                                if (G_x_mode) {
9337                                        char *eq;
9338                                        if (i == 0)
9339                                                x_mode_prefix();
9340                                        x_mode_addchr(' ');
9341                                        eq = strchrnul(p, '=');
9342                                        if (*eq) eq++;
9343                                        x_mode_addblock(p, (eq - p));
9344                                        x_mode_print_optionally_squoted(eq);
9345                                        x_mode_flush();
9346                                }
9347#endif
9348                                debug_printf_env("set shell var:'%s'->'%s'\n", *argv, p);
9349                                if (set_local_var(p, /*flag:*/ 0)) {
9350                                        /* assignment to readonly var / putenv error? */
9351                                        rcode = 1;
9352                                }
9353                                i++;
9354                        }
9355                        /* Redirect error sets $? to 1. Otherwise,
9356                         * if evaluating assignment value set $?, retain it.
9357                         * Else, clear $?:
9358                         *  false; q=`exit 2`; echo $? - should print 2
9359                         *  false; x=1; echo $? - should print 0
9360                         * Because of the 2nd case, we can't just use G.last_exitcode.
9361                         */
9362                        if (rcode == 0)
9363                                rcode = G.expand_exitcode;
9364                        IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
9365                        debug_leave();
9366                        debug_printf_exec("run_pipe: return %d\n", rcode);
9367                        return rcode;
9368                }
9369
9370                /* Expand the rest into (possibly) many strings each */
9371#if defined(CMD_TEST2_SINGLEWORD_NOGLOB)
9372                if (command->cmd_type == CMD_TEST2_SINGLEWORD_NOGLOB)
9373                        argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt);
9374                else
9375#endif
9376#if defined(CMD_SINGLEWORD_NOGLOB)
9377                if (command->cmd_type == CMD_SINGLEWORD_NOGLOB)
9378                        argv_expanded = expand_strvec_to_strvec_singleword_noglob(argv + command->assignment_cnt);
9379                else
9380#endif
9381                        argv_expanded = expand_strvec_to_strvec(argv + command->assignment_cnt);
9382
9383                /* If someone gives us an empty string: `cmd with empty output` */
9384                if (!argv_expanded[0]) {
9385                        free(argv_expanded);
9386                        /* `false` still has to set exitcode 1 */
9387                        G.expand_exitcode = G.last_exitcode;
9388                        goto only_assignments;
9389                }
9390
9391                old_vars = NULL;
9392                sv_shadowed = G.shadowed_vars_pp;
9393
9394                /* Check if argv[0] matches any functions (this goes before bltins) */
9395                IF_HUSH_FUNCTIONS(funcp = find_function(argv_expanded[0]);)
9396                IF_HUSH_FUNCTIONS(x = NULL;)
9397                IF_HUSH_FUNCTIONS(if (!funcp))
9398                        x = find_builtin(argv_expanded[0]);
9399                if (x || funcp) {
9400                        if (x && x->b_function == builtin_exec && argv_expanded[1] == NULL) {
9401                                debug_printf("exec with redirects only\n");
9402                                /*
9403                                 * Variable assignments are executed, but then "forgotten":
9404                                 *  a=`sleep 1;echo A` exec 3>&-; echo $a
9405                                 * sleeps, but prints nothing.
9406                                 */
9407                                enter_var_nest_level();
9408                                G.shadowed_vars_pp = &old_vars;
9409                                rcode = redirect_and_varexp_helper(command,
9410                                        /*squirrel:*/ ERR_PTR,
9411                                        argv_expanded
9412                                );
9413                                G.shadowed_vars_pp = sv_shadowed;
9414                                /* rcode=1 can be if redir file can't be opened */
9415
9416                                goto clean_up_and_ret1;
9417                        }
9418
9419                        /* Bump var nesting, or this will leak exported $a:
9420                         * a=b true; env | grep ^a=
9421                         */
9422                        enter_var_nest_level();
9423                        /* Collect all variables "shadowed" by helper
9424                         * (IOW: old vars overridden by "var1=val1 var2=val2 cmd..." syntax)
9425                         * into old_vars list:
9426                         */
9427                        G.shadowed_vars_pp = &old_vars;
9428                        rcode = redirect_and_varexp_helper(command, &squirrel, argv_expanded);
9429                        if (rcode == 0) {
9430                                if (!funcp) {
9431                                        /* Do not collect *to old_vars list* vars shadowed
9432                                         * by e.g. "local VAR" builtin (collect them
9433                                         * in the previously nested list instead):
9434                                         * don't want them to be restored immediately
9435                                         * after "local" completes.
9436                                         */
9437                                        G.shadowed_vars_pp = sv_shadowed;
9438
9439                                        debug_printf_exec(": builtin '%s' '%s'...\n",
9440                                                x->b_cmd, argv_expanded[1]);
9441                                        fflush_all();
9442                                        rcode = x->b_function(argv_expanded) & 0xff;
9443                                        fflush_all();
9444                                }
9445#if ENABLE_HUSH_FUNCTIONS
9446                                else {
9447                                        debug_printf_exec(": function '%s' '%s'...\n",
9448                                                funcp->name, argv_expanded[1]);
9449                                        rcode = run_function(funcp, argv_expanded) & 0xff;
9450                                        /*
9451                                         * But do collect *to old_vars list* vars shadowed
9452                                         * within function execution. To that end, restore
9453                                         * this pointer _after_ function run:
9454                                         */
9455                                        G.shadowed_vars_pp = sv_shadowed;
9456                                }
9457#endif
9458                        }
9459                } else
9460                if (ENABLE_FEATURE_SH_NOFORK && NUM_APPLETS > 1) {
9461                        int n = find_applet_by_name(argv_expanded[0]);
9462                        if (n < 0 || !APPLET_IS_NOFORK(n))
9463                                goto must_fork;
9464
9465                        enter_var_nest_level();
9466                        /* Collect all variables "shadowed" by helper into old_vars list */
9467                        G.shadowed_vars_pp = &old_vars;
9468                        rcode = redirect_and_varexp_helper(command, &squirrel, argv_expanded);
9469                        G.shadowed_vars_pp = sv_shadowed;
9470
9471                        if (rcode == 0) {
9472                                debug_printf_exec(": run_nofork_applet '%s' '%s'...\n",
9473                                        argv_expanded[0], argv_expanded[1]);
9474                                /*
9475                                 * Note: signals (^C) can't interrupt here.
9476                                 * We remember them and they will be acted upon
9477                                 * after applet returns.
9478                                 * This makes applets which can run for a long time
9479                                 * and/or wait for user input ineligible for NOFORK:
9480                                 * for example, "yes" or "rm" (rm -i waits for input).
9481                                 */
9482                                rcode = run_nofork_applet(n, argv_expanded);
9483                        }
9484                } else
9485                        goto must_fork;
9486
9487                restore_redirects(squirrel);
9488 clean_up_and_ret1:
9489                leave_var_nest_level();
9490                add_vars(old_vars);
9491
9492                /*
9493                 * Try "usleep 99999999" + ^C + "echo $?"
9494                 * with FEATURE_SH_NOFORK=y.
9495                 */
9496                if (!funcp) {
9497                        /* It was builtin or nofork.
9498                         * if this would be a real fork/execed program,
9499                         * it should have died if a fatal sig was received.
9500                         * But OTOH, there was no separate process,
9501                         * the sig was sent to _shell_, not to non-existing
9502                         * child.
9503                         * Let's just handle ^C only, this one is obvious:
9504                         * we aren't ok with exitcode 0 when ^C was pressed
9505                         * during builtin/nofork.
9506                         */
9507                        if (sigismember(&G.pending_set, SIGINT))
9508                                rcode = 128 | SIGINT;
9509                }
9510                free(argv_expanded);
9511                IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
9512                debug_leave();
9513                debug_printf_exec("run_pipe return %d\n", rcode);
9514                return rcode;
9515        }
9516
9517 must_fork:
9518        /* NB: argv_expanded may already be created, and that
9519         * might include `cmd` runs! Do not rerun it! We *must*
9520         * use argv_expanded if it's non-NULL */
9521
9522        /* Going to fork a child per each pipe member */
9523        pi->alive_cmds = 0;
9524        next_infd = 0;
9525
9526        cmd_no = 0;
9527        while (cmd_no < pi->num_cmds) {
9528                struct fd_pair pipefds;
9529#if !BB_MMU
9530                int sv_var_nest_level = G.var_nest_level;
9531                volatile nommu_save_t nommu_save;
9532                nommu_save.old_vars = NULL;
9533                nommu_save.argv = NULL;
9534                nommu_save.argv_from_re_execing = NULL;
9535#endif
9536                command = &pi->cmds[cmd_no];
9537                cmd_no++;
9538                if (command->argv) {
9539                        debug_printf_exec(": pipe member '%s' '%s'...\n",
9540                                        command->argv[0], command->argv[1]);
9541                } else {
9542                        debug_printf_exec(": pipe member with no argv\n");
9543                }
9544
9545                /* pipes are inserted between pairs of commands */
9546                pipefds.rd = 0;
9547                pipefds.wr = 1;
9548                if (cmd_no < pi->num_cmds)
9549                        xpiped_pair(pipefds);
9550
9551#if ENABLE_HUSH_LINENO_VAR
9552                G.execute_lineno = command->lineno;
9553#endif
9554
9555                command->pid = BB_MMU ? fork() : vfork();
9556                if (!command->pid) { /* child */
9557#if ENABLE_HUSH_JOB
9558                        disable_restore_tty_pgrp_on_exit();
9559                        CLEAR_RANDOM_T(&G.random_gen); /* or else $RANDOM repeats in child */
9560
9561                        /* Every child adds itself to new process group
9562                         * with pgid == pid_of_first_child_in_pipe */
9563                        if (G.run_list_level == 1 && G_interactive_fd) {
9564                                pid_t pgrp;
9565                                pgrp = pi->pgrp;
9566                                if (pgrp < 0) /* true for 1st process only */
9567                                        pgrp = getpid();
9568                                if (setpgid(0, pgrp) == 0
9569                                 && pi->followup != PIPE_BG
9570                                 && G_saved_tty_pgrp /* we have ctty */
9571                                ) {
9572                                        /* We do it in *every* child, not just first,
9573                                         * to avoid races */
9574                                        tcsetpgrp(G_interactive_fd, pgrp);
9575                                }
9576                        }
9577#endif
9578                        if (pi->alive_cmds == 0 && pi->followup == PIPE_BG) {
9579                                /* 1st cmd in backgrounded pipe
9580                                 * should have its stdin /dev/null'ed */
9581                                close(0);
9582                                if (open(bb_dev_null, O_RDONLY))
9583                                        xopen("/", O_RDONLY);
9584                        } else {
9585                                xmove_fd(next_infd, 0);
9586                        }
9587                        xmove_fd(pipefds.wr, 1);
9588                        if (pipefds.rd > 1)
9589                                close(pipefds.rd);
9590                        /* Like bash, explicit redirects override pipes,
9591                         * and the pipe fd (fd#1) is available for dup'ing:
9592                         * "cmd1 2>&1 | cmd2": fd#1 is duped to fd#2, thus stderr
9593                         * of cmd1 goes into pipe.
9594                         */
9595                        if (setup_redirects(command, NULL)) {
9596                                /* Happens when redir file can't be opened:
9597                                 * $ hush -c 'echo FOO >&2 | echo BAR 3>/qwe/rty; echo BAZ'
9598                                 * FOO
9599                                 * hush: can't open '/qwe/rty': No such file or directory
9600                                 * BAZ
9601                                 * (echo BAR is not executed, it hits _exit(1) below)
9602                                 */
9603                                _exit(1);
9604                        }
9605
9606                        /* Stores to nommu_save list of env vars putenv'ed
9607                         * (NOMMU, on MMU we don't need that) */
9608                        /* cast away volatility... */
9609                        pseudo_exec((nommu_save_t*) &nommu_save, command, argv_expanded);
9610                        /* pseudo_exec() does not return */
9611                }
9612
9613                /* parent or error */
9614#if ENABLE_HUSH_FAST
9615                G.count_SIGCHLD++;
9616//bb_error_msg("[%d] fork in run_pipe: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
9617#endif
9618                enable_restore_tty_pgrp_on_exit();
9619#if !BB_MMU
9620                /* Clean up after vforked child */
9621                free(nommu_save.argv);
9622                free(nommu_save.argv_from_re_execing);
9623                G.var_nest_level = sv_var_nest_level;
9624                remove_nested_vars();
9625                add_vars(nommu_save.old_vars);
9626#endif
9627                free(argv_expanded);
9628                argv_expanded = NULL;
9629                if (command->pid < 0) { /* [v]fork failed */
9630                        /* Clearly indicate, was it fork or vfork */
9631                        bb_simple_perror_msg(BB_MMU ? "vfork"+1 : "vfork");
9632                } else {
9633                        pi->alive_cmds++;
9634#if ENABLE_HUSH_JOB
9635                        /* Second and next children need to know pid of first one */
9636                        if (pi->pgrp < 0)
9637                                pi->pgrp = command->pid;
9638#endif
9639                }
9640
9641                if (cmd_no > 1)
9642                        close(next_infd);
9643                if (cmd_no < pi->num_cmds)
9644                        close(pipefds.wr);
9645                /* Pass read (output) pipe end to next iteration */
9646                next_infd = pipefds.rd;
9647        }
9648
9649        if (!pi->alive_cmds) {
9650                debug_leave();
9651                debug_printf_exec("run_pipe return 1 (all forks failed, no children)\n");
9652                return 1;
9653        }
9654
9655        debug_leave();
9656        debug_printf_exec("run_pipe return -1 (%u children started)\n", pi->alive_cmds);
9657        return -1;
9658}
9659
9660/* NB: called by pseudo_exec, and therefore must not modify any
9661 * global data until exec/_exit (we can be a child after vfork!) */
9662static int run_list(struct pipe *pi)
9663{
9664#if ENABLE_HUSH_CASE
9665        char *case_word = NULL;
9666#endif
9667#if ENABLE_HUSH_LOOPS
9668        struct pipe *loop_top = NULL;
9669        char **for_lcur = NULL;
9670        char **for_list = NULL;
9671#endif
9672        smallint last_followup;
9673        smalluint rcode;
9674#if ENABLE_HUSH_IF || ENABLE_HUSH_CASE
9675        smalluint cond_code = 0;
9676#else
9677        enum { cond_code = 0 };
9678#endif
9679#if HAS_KEYWORDS
9680        smallint rword;      /* RES_foo */
9681        smallint last_rword; /* ditto */
9682#endif
9683
9684        debug_printf_exec("run_list start lvl %d\n", G.run_list_level);
9685        debug_enter();
9686
9687#if ENABLE_HUSH_LOOPS
9688        /* Check syntax for "for" */
9689        {
9690                struct pipe *cpipe;
9691                for (cpipe = pi; cpipe; cpipe = cpipe->next) {
9692                        if (cpipe->res_word != RES_FOR && cpipe->res_word != RES_IN)
9693                                continue;
9694                        /* current word is FOR or IN (BOLD in comments below) */
9695                        if (cpipe->next == NULL) {
9696                                syntax_error("malformed for");
9697                                debug_leave();
9698                                debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level);
9699                                return 1;
9700                        }
9701                        /* "FOR v; do ..." and "for v IN a b; do..." are ok */
9702                        if (cpipe->next->res_word == RES_DO)
9703                                continue;
9704                        /* next word is not "do". It must be "in" then ("FOR v in ...") */
9705                        if (cpipe->res_word == RES_IN /* "for v IN a b; not_do..."? */
9706                         || cpipe->next->res_word != RES_IN /* FOR v not_do_and_not_in..."? */
9707                        ) {
9708                                syntax_error("malformed for");
9709                                debug_leave();
9710                                debug_printf_exec("run_list lvl %d return 1\n", G.run_list_level);
9711                                return 1;
9712                        }
9713                }
9714        }
9715#endif
9716
9717        /* Past this point, all code paths should jump to ret: label
9718         * in order to return, no direct "return" statements please.
9719         * This helps to ensure that no memory is leaked. */
9720
9721#if ENABLE_HUSH_JOB
9722        G.run_list_level++;
9723#endif
9724
9725#if HAS_KEYWORDS
9726        rword = RES_NONE;
9727        last_rword = RES_XXXX;
9728#endif
9729        last_followup = PIPE_SEQ;
9730        rcode = G.last_exitcode;
9731
9732        /* Go through list of pipes, (maybe) executing them. */
9733        for (; pi; pi = IF_HUSH_LOOPS(rword == RES_DONE ? loop_top : ) pi->next) {
9734                int r;
9735                int sv_errexit_depth;
9736
9737                if (G.flag_SIGINT)
9738                        break;
9739                if (G_flag_return_in_progress == 1)
9740                        break;
9741
9742                IF_HAS_KEYWORDS(rword = pi->res_word;)
9743                debug_printf_exec(": rword=%d cond_code=%d last_rword=%d\n",
9744                                rword, cond_code, last_rword);
9745
9746                sv_errexit_depth = G.errexit_depth;
9747                if (
9748#if ENABLE_HUSH_IF
9749                    rword == RES_IF || rword == RES_ELIF ||
9750#endif
9751                    pi->followup != PIPE_SEQ
9752                ) {
9753                        G.errexit_depth++;
9754                }
9755#if ENABLE_HUSH_LOOPS
9756                if ((rword == RES_WHILE || rword == RES_UNTIL || rword == RES_FOR)
9757                 && loop_top == NULL /* avoid bumping G.depth_of_loop twice */
9758                ) {
9759                        /* start of a loop: remember where loop starts */
9760                        loop_top = pi;
9761                        G.depth_of_loop++;
9762                }
9763#endif
9764                /* Still in the same "if...", "then..." or "do..." branch? */
9765                if (IF_HAS_KEYWORDS(rword == last_rword &&) 1) {
9766                        if ((rcode == 0 && last_followup == PIPE_OR)
9767                         || (rcode != 0 && last_followup == PIPE_AND)
9768                        ) {
9769                                /* It is "<true> || CMD" or "<false> && CMD"
9770                                 * and we should not execute CMD */
9771                                debug_printf_exec("skipped cmd because of || or &&\n");
9772                                last_followup = pi->followup;
9773                                goto dont_check_jobs_but_continue;
9774                        }
9775                }
9776                last_followup = pi->followup;
9777                IF_HAS_KEYWORDS(last_rword = rword;)
9778#if ENABLE_HUSH_IF
9779                if (cond_code) {
9780                        if (rword == RES_THEN) {
9781                                /* if false; then ... fi has exitcode 0! */
9782                                G.last_exitcode = rcode = EXIT_SUCCESS;
9783                                /* "if <false> THEN cmd": skip cmd */
9784                                continue;
9785                        }
9786                } else {
9787                        if (rword == RES_ELSE || rword == RES_ELIF) {
9788                                /* "if <true> then ... ELSE/ELIF cmd":
9789                                 * skip cmd and all following ones */
9790                                break;
9791                        }
9792                }
9793#endif
9794#if ENABLE_HUSH_LOOPS
9795                if (rword == RES_FOR) { /* && pi->num_cmds - always == 1 */
9796                        if (!for_lcur) {
9797                                /* first loop through for */
9798
9799                                static const char encoded_dollar_at[] ALIGN1 = {
9800                                        SPECIAL_VAR_SYMBOL, '@' | 0x80, SPECIAL_VAR_SYMBOL, '\0'
9801                                }; /* encoded representation of "$@" */
9802                                static const char *const encoded_dollar_at_argv[] = {
9803                                        encoded_dollar_at, NULL
9804                                }; /* argv list with one element: "$@" */
9805                                char **vals;
9806
9807                                G.last_exitcode = rcode = EXIT_SUCCESS;
9808                                vals = (char**)encoded_dollar_at_argv;
9809                                if (pi->next->res_word == RES_IN) {
9810                                        /* if no variable values after "in" we skip "for" */
9811                                        if (!pi->next->cmds[0].argv) {
9812                                                debug_printf_exec(": null FOR: exitcode EXIT_SUCCESS\n");
9813                                                break;
9814                                        }
9815                                        vals = pi->next->cmds[0].argv;
9816                                } /* else: "for var; do..." -> assume "$@" list */
9817                                /* create list of variable values */
9818                                debug_print_strings("for_list made from", vals);
9819                                for_list = expand_strvec_to_strvec(vals);
9820                                for_lcur = for_list;
9821                                debug_print_strings("for_list", for_list);
9822                        }
9823                        if (!*for_lcur) {
9824                                /* "for" loop is over, clean up */
9825                                free(for_list);
9826                                for_list = NULL;
9827                                for_lcur = NULL;
9828                                break;
9829                        }
9830                        /* Insert next value from for_lcur */
9831                        /* note: *for_lcur already has quotes removed, $var expanded, etc */
9832                        set_local_var(xasprintf("%s=%s", pi->cmds[0].argv[0], *for_lcur++), /*flag:*/ 0);
9833                        continue;
9834                }
9835                if (rword == RES_IN) {
9836                        continue; /* "for v IN list;..." - "in" has no cmds anyway */
9837                }
9838                if (rword == RES_DONE) {
9839                        continue; /* "done" has no cmds too */
9840                }
9841#endif
9842#if ENABLE_HUSH_CASE
9843                if (rword == RES_CASE) {
9844                        debug_printf_exec("CASE cond_code:%d\n", cond_code);
9845                        case_word = expand_string_to_string(pi->cmds->argv[0],
9846                                EXP_FLAG_ESC_GLOB_CHARS, /*unbackslash:*/ 1);
9847                        debug_printf_exec("CASE word1:'%s'\n", case_word);
9848                        //unbackslash(case_word);
9849                        //debug_printf_exec("CASE word2:'%s'\n", case_word);
9850                        continue;
9851                }
9852                if (rword == RES_MATCH) {
9853                        char **argv;
9854
9855                        debug_printf_exec("MATCH cond_code:%d\n", cond_code);
9856                        if (!case_word) /* "case ... matched_word) ... WORD)": we executed selected branch, stop */
9857                                break;
9858                        /* all prev words didn't match, does this one match? */
9859                        argv = pi->cmds->argv;
9860                        while (*argv) {
9861                                char *pattern;
9862                                debug_printf_exec("expand_string_to_string('%s')\n", *argv);
9863                                pattern = expand_string_to_string(*argv,
9864                                                EXP_FLAG_ESC_GLOB_CHARS,
9865                                                /*unbackslash:*/ 0
9866                                );
9867                                /* TODO: which FNM_xxx flags to use? */
9868                                cond_code = (fnmatch(pattern, case_word, /*flags:*/ 0) != 0);
9869                                debug_printf_exec("fnmatch(pattern:'%s',str:'%s'):%d\n",
9870                                                pattern, case_word, cond_code);
9871                                free(pattern);
9872                                if (cond_code == 0) {
9873                                        /* match! we will execute this branch */
9874                                        free(case_word);
9875                                        case_word = NULL; /* make future "word)" stop */
9876                                        break;
9877                                }
9878                                argv++;
9879                        }
9880                        continue;
9881                }
9882                if (rword == RES_CASE_BODY) { /* inside of a case branch */
9883                        debug_printf_exec("CASE_BODY cond_code:%d\n", cond_code);
9884                        if (cond_code != 0)
9885                                continue; /* not matched yet, skip this pipe */
9886                }
9887                if (rword == RES_ESAC) {
9888                        debug_printf_exec("ESAC cond_code:%d\n", cond_code);
9889                        if (case_word) {
9890                                /* "case" did not match anything: still set $? (to 0) */
9891                                G.last_exitcode = rcode = EXIT_SUCCESS;
9892                        }
9893                }
9894#endif
9895                /* Just pressing <enter> in shell should check for jobs.
9896                 * OTOH, in non-interactive shell this is useless
9897                 * and only leads to extra job checks */
9898                if (pi->num_cmds == 0) {
9899                        if (G_interactive_fd)
9900                                goto check_jobs_and_continue;
9901                        continue;
9902                }
9903
9904                /* After analyzing all keywords and conditions, we decided
9905                 * to execute this pipe. NB: have to do checkjobs(NULL)
9906                 * after run_pipe to collect any background children,
9907                 * even if list execution is to be stopped. */
9908                debug_printf_exec(": run_pipe with %d members\n", pi->num_cmds);
9909#if ENABLE_HUSH_LOOPS
9910                G.flag_break_continue = 0;
9911#endif
9912                rcode = r = G.o_opt[OPT_O_NOEXEC] ? 0 : run_pipe(pi);
9913                /* NB: rcode is a smalluint, r is int */
9914                if (r != -1) {
9915                        /* We ran a builtin, function, or group.
9916                         * rcode is already known
9917                         * and we don't need to wait for anything. */
9918                        debug_printf_exec(": builtin/func exitcode %d\n", rcode);
9919                        G.last_exitcode = rcode;
9920                        check_and_run_traps();
9921#if ENABLE_HUSH_TRAP && ENABLE_HUSH_FUNCTIONS
9922                        rcode = G.last_exitcode; /* "return" in trap can change it, read back */
9923#endif
9924#if ENABLE_HUSH_LOOPS
9925                        /* Was it "break" or "continue"? */
9926                        if (G.flag_break_continue) {
9927                                smallint fbc = G.flag_break_continue;
9928                                /* We might fall into outer *loop*,
9929                                 * don't want to break it too */
9930                                if (loop_top) {
9931                                        G.depth_break_continue--;
9932                                        if (G.depth_break_continue == 0)
9933                                                G.flag_break_continue = 0;
9934                                        /* else: e.g. "continue 2" should *break* once, *then* continue */
9935                                } /* else: "while... do... { we are here (innermost list is not a loop!) };...done" */
9936                                if (G.depth_break_continue != 0 || fbc == BC_BREAK) {
9937                                        checkjobs(NULL, 0 /*(no pid to wait for)*/);
9938                                        break;
9939                                }
9940                                /* "continue": simulate end of loop */
9941                                rword = RES_DONE;
9942                                continue;
9943                        }
9944#endif
9945                        if (G_flag_return_in_progress == 1) {
9946                                checkjobs(NULL, 0 /*(no pid to wait for)*/);
9947                                break;
9948                        }
9949                } else if (pi->followup == PIPE_BG) {
9950                        /* What does bash do with attempts to background builtins? */
9951                        /* even bash 3.2 doesn't do that well with nested bg:
9952                         * try "{ { sleep 10; echo DEEP; } & echo HERE; } &".
9953                         * I'm NOT treating inner &'s as jobs */
9954#if ENABLE_HUSH_JOB
9955                        if (G.run_list_level == 1)
9956                                insert_job_into_table(pi);
9957#endif
9958                        /* Last command's pid goes to $! */
9959                        G.last_bg_pid = pi->cmds[pi->num_cmds - 1].pid;
9960                        G.last_bg_pid_exitcode = 0;
9961                        debug_printf_exec(": cmd&: exitcode EXIT_SUCCESS\n");
9962/* Check pi->pi_inverted? "! sleep 1 & echo $?": bash says 1. dash and ash say 0 */
9963                        rcode = EXIT_SUCCESS;
9964                        goto check_traps;
9965                } else {
9966#if ENABLE_HUSH_JOB
9967                        if (G.run_list_level == 1 && G_interactive_fd) {
9968                                /* Waits for completion, then fg's main shell */
9969                                rcode = checkjobs_and_fg_shell(pi);
9970                                debug_printf_exec(": checkjobs_and_fg_shell exitcode %d\n", rcode);
9971                                goto check_traps;
9972                        }
9973#endif
9974                        /* This one just waits for completion */
9975                        rcode = checkjobs(pi, 0 /*(no pid to wait for)*/);
9976                        debug_printf_exec(": checkjobs exitcode %d\n", rcode);
9977 check_traps:
9978                        G.last_exitcode = rcode;
9979                        check_and_run_traps();
9980#if ENABLE_HUSH_TRAP && ENABLE_HUSH_FUNCTIONS
9981                        rcode = G.last_exitcode; /* "return" in trap can change it, read back */
9982#endif
9983                }
9984
9985                /* Handle "set -e" */
9986                if (rcode != 0 && G.o_opt[OPT_O_ERREXIT]) {
9987                        debug_printf_exec("ERREXIT:1 errexit_depth:%d\n", G.errexit_depth);
9988                        if (G.errexit_depth == 0)
9989                                hush_exit(rcode);
9990                }
9991                G.errexit_depth = sv_errexit_depth;
9992
9993                /* Analyze how result affects subsequent commands */
9994#if ENABLE_HUSH_IF
9995                if (rword == RES_IF || rword == RES_ELIF)
9996                        cond_code = rcode;
9997#endif
9998 check_jobs_and_continue:
9999                checkjobs(NULL, 0 /*(no pid to wait for)*/);
10000 dont_check_jobs_but_continue: ;
10001#if ENABLE_HUSH_LOOPS
10002                /* Beware of "while false; true; do ..."! */
10003                if (pi->next
10004                 && (pi->next->res_word == RES_DO || pi->next->res_word == RES_DONE)
10005                 /* check for RES_DONE is needed for "while ...; do \n done" case */
10006                ) {
10007                        if (rword == RES_WHILE) {
10008                                if (rcode) {
10009                                        /* "while false; do...done" - exitcode 0 */
10010                                        G.last_exitcode = rcode = EXIT_SUCCESS;
10011                                        debug_printf_exec(": while expr is false: breaking (exitcode:EXIT_SUCCESS)\n");
10012                                        break;
10013                                }
10014                        }
10015                        if (rword == RES_UNTIL) {
10016                                if (!rcode) {
10017                                        debug_printf_exec(": until expr is true: breaking\n");
10018                                        break;
10019                                }
10020                        }
10021                }
10022#endif
10023        } /* for (pi) */
10024
10025#if ENABLE_HUSH_JOB
10026        G.run_list_level--;
10027#endif
10028#if ENABLE_HUSH_LOOPS
10029        if (loop_top)
10030                G.depth_of_loop--;
10031        free(for_list);
10032#endif
10033#if ENABLE_HUSH_CASE
10034        free(case_word);
10035#endif
10036        debug_leave();
10037        debug_printf_exec("run_list lvl %d return %d\n", G.run_list_level + 1, rcode);
10038        return rcode;
10039}
10040
10041/* Select which version we will use */
10042static int run_and_free_list(struct pipe *pi)
10043{
10044        int rcode = 0;
10045        debug_printf_exec("run_and_free_list entered\n");
10046        if (!G.o_opt[OPT_O_NOEXEC]) {
10047                debug_printf_exec(": run_list: 1st pipe with %d cmds\n", pi->num_cmds);
10048                rcode = run_list(pi);
10049        }
10050        /* free_pipe_list has the side effect of clearing memory.
10051         * In the long run that function can be merged with run_list,
10052         * but doing that now would hobble the debugging effort. */
10053        free_pipe_list(pi);
10054        debug_printf_exec("run_and_free_list return %d\n", rcode);
10055        return rcode;
10056}
10057
10058
10059static void install_sighandlers(unsigned mask)
10060{
10061        sighandler_t old_handler;
10062        unsigned sig = 0;
10063        while ((mask >>= 1) != 0) {
10064                sig++;
10065                if (!(mask & 1))
10066                        continue;
10067                old_handler = install_sighandler(sig, pick_sighandler(sig));
10068                /* POSIX allows shell to re-enable SIGCHLD
10069                 * even if it was SIG_IGN on entry.
10070                 * Therefore we skip IGN check for it:
10071                 */
10072                if (sig == SIGCHLD)
10073                        continue;
10074                /* Interactive bash re-enables SIGHUP which is SIG_IGNed on entry.
10075                 * Try:
10076                 * trap '' hup; bash; echo RET  # type "kill -hup $$", see SIGHUP having effect
10077                 * trap '' hup; bash -c 'kill -hup $$; echo ALIVE'  # here SIGHUP is SIG_IGNed
10078                 */
10079                if (sig == SIGHUP && G_interactive_fd)
10080                        continue;
10081                /* Unless one of the above signals, is it SIG_IGN? */
10082                if (old_handler == SIG_IGN) {
10083                        /* oops... restore back to IGN, and record this fact */
10084                        install_sighandler(sig, old_handler);
10085#if ENABLE_HUSH_TRAP
10086                        if (!G_traps)
10087                                G_traps = xzalloc(sizeof(G_traps[0]) * NSIG);
10088                        free(G_traps[sig]);
10089                        G_traps[sig] = xzalloc(1); /* == xstrdup(""); */
10090#endif
10091                }
10092        }
10093}
10094
10095/* Called a few times only (or even once if "sh -c") */
10096static void install_special_sighandlers(void)
10097{
10098        unsigned mask;
10099
10100        /* Which signals are shell-special? */
10101        mask = (1 << SIGQUIT) | (1 << SIGCHLD);
10102        if (G_interactive_fd) {
10103                mask |= SPECIAL_INTERACTIVE_SIGS;
10104                if (G_saved_tty_pgrp) /* we have ctty, job control sigs work */
10105                        mask |= SPECIAL_JOBSTOP_SIGS;
10106        }
10107        /* Careful, do not re-install handlers we already installed */
10108        if (G.special_sig_mask != mask) {
10109                unsigned diff = mask & ~G.special_sig_mask;
10110                G.special_sig_mask = mask;
10111                install_sighandlers(diff);
10112        }
10113}
10114
10115#if ENABLE_HUSH_JOB
10116/* helper */
10117/* Set handlers to restore tty pgrp and exit */
10118static void install_fatal_sighandlers(void)
10119{
10120        unsigned mask;
10121
10122        /* We will restore tty pgrp on these signals */
10123        mask = 0
10124                /*+ (1 << SIGILL ) * HUSH_DEBUG*/
10125                /*+ (1 << SIGFPE ) * HUSH_DEBUG*/
10126                + (1 << SIGBUS ) * HUSH_DEBUG
10127                + (1 << SIGSEGV) * HUSH_DEBUG
10128                /*+ (1 << SIGTRAP) * HUSH_DEBUG*/
10129                + (1 << SIGABRT)
10130        /* bash 3.2 seems to handle these just like 'fatal' ones */
10131                + (1 << SIGPIPE)
10132                + (1 << SIGALRM)
10133        /* if we are interactive, SIGHUP, SIGTERM and SIGINT are special sigs.
10134         * if we aren't interactive... but in this case
10135         * we never want to restore pgrp on exit, and this fn is not called
10136         */
10137                /*+ (1 << SIGHUP )*/
10138                /*+ (1 << SIGTERM)*/
10139                /*+ (1 << SIGINT )*/
10140        ;
10141        G_fatal_sig_mask = mask;
10142
10143        install_sighandlers(mask);
10144}
10145#endif
10146
10147static int set_mode(int state, char mode, const char *o_opt)
10148{
10149        int idx;
10150        switch (mode) {
10151        case 'n':
10152                /* set -n has no effect in interactive shell */
10153                /* Try: while set -n; do echo $-; done */
10154                if (!G_interactive_fd)
10155                        G.o_opt[OPT_O_NOEXEC] = state;
10156                break;
10157        case 'x':
10158                IF_HUSH_MODE_X(G_x_mode = state;)
10159                IF_HUSH_MODE_X(if (G.x_mode_fd <= 0) G.x_mode_fd = dup_CLOEXEC(2, 10);)
10160                break;
10161        case 'e':
10162                G.o_opt[OPT_O_ERREXIT] = state;
10163                break;
10164        case 'o':
10165                if (!o_opt) {
10166                        /* "set -o" or "set +o" without parameter.
10167                         * in bash, set -o produces this output:
10168                         *  pipefail        off
10169                         * and set +o:
10170                         *  set +o pipefail
10171                         * We always use the second form.
10172                         */
10173                        const char *p = o_opt_strings;
10174                        idx = 0;
10175                        while (*p) {
10176                                printf("set %co %s\n", (G.o_opt[idx] ? '-' : '+'), p);
10177                                idx++;
10178                                p += strlen(p) + 1;
10179                        }
10180                        break;
10181                }
10182                idx = index_in_strings(o_opt_strings, o_opt);
10183                if (idx >= 0) {
10184                        G.o_opt[idx] = state;
10185                        break;
10186                }
10187                /* fall through to error */
10188        default:
10189                return EXIT_FAILURE;
10190        }
10191        return EXIT_SUCCESS;
10192}
10193
10194int hush_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
10195int hush_main(int argc, char **argv)
10196{
10197        pid_t cached_getpid;
10198        enum {
10199                OPT_login = (1 << 0),
10200        };
10201        unsigned flags;
10202#if !BB_MMU
10203        unsigned builtin_argc = 0;
10204#endif
10205        char **e;
10206        struct variable *cur_var;
10207        struct variable *shell_ver;
10208
10209        INIT_G();
10210        if (EXIT_SUCCESS != 0) /* if EXIT_SUCCESS == 0, it is already done */
10211                G.last_exitcode = EXIT_SUCCESS;
10212#if ENABLE_HUSH_TRAP
10213# if ENABLE_HUSH_FUNCTIONS
10214        G.return_exitcode = -1;
10215# endif
10216        G.pre_trap_exitcode = -1;
10217#endif
10218
10219#if ENABLE_HUSH_FAST
10220        G.count_SIGCHLD++; /* ensure it is != G.handled_SIGCHLD */
10221#endif
10222#if !BB_MMU
10223        G.argv0_for_re_execing = argv[0];
10224#endif
10225
10226        cached_getpid = getpid();   /* for tcsetpgrp() during init */
10227        G.root_pid = cached_getpid; /* for $PID  (NOMMU can override via -$HEXPID:HEXPPID:...) */
10228        G.root_ppid = getppid();    /* for $PPID (NOMMU can override) */
10229
10230        /* Deal with HUSH_VERSION */
10231        debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION");
10232        unsetenv("HUSH_VERSION"); /* in case it exists in initial env */
10233        shell_ver = xzalloc(sizeof(*shell_ver));
10234        shell_ver->flg_export = 1;
10235        shell_ver->flg_read_only = 1;
10236        /* Code which handles ${var<op>...} needs writable values for all variables,
10237         * therefore we xstrdup: */
10238        shell_ver->varstr = xstrdup(hush_version_str);
10239
10240        /* Create shell local variables from the values
10241         * currently living in the environment */
10242        G.top_var = shell_ver;
10243        cur_var = G.top_var;
10244        e = environ;
10245        if (e) while (*e) {
10246                char *value = strchr(*e, '=');
10247                if (value) { /* paranoia */
10248                        cur_var->next = xzalloc(sizeof(*cur_var));
10249                        cur_var = cur_var->next;
10250                        cur_var->varstr = *e;
10251                        cur_var->max_len = strlen(*e);
10252                        cur_var->flg_export = 1;
10253                }
10254                e++;
10255        }
10256        /* (Re)insert HUSH_VERSION into env (AFTER we scanned the env!) */
10257        debug_printf_env("putenv '%s'\n", shell_ver->varstr);
10258        putenv(shell_ver->varstr);
10259
10260        /* Export PWD */
10261        set_pwd_var(SETFLAG_EXPORT);
10262
10263#if BASH_HOSTNAME_VAR
10264        /* Set (but not export) HOSTNAME unless already set */
10265        if (!get_local_var_value("HOSTNAME")) {
10266                struct utsname uts;
10267                uname(&uts);
10268                set_local_var_from_halves("HOSTNAME", uts.nodename);
10269        }
10270#endif
10271        /* IFS is not inherited from the parent environment */
10272        set_local_var_from_halves("IFS", defifs);
10273
10274        if (!get_local_var_value("PATH"))
10275                set_local_var_from_halves("PATH", bb_default_root_path);
10276
10277        /* PS1/PS2 are set later, if we determine that we are interactive */
10278
10279        /* bash also exports SHLVL and _,
10280         * and sets (but doesn't export) the following variables:
10281         * BASH=/bin/bash
10282         * BASH_VERSINFO=([0]="3" [1]="2" [2]="0" [3]="1" [4]="release" [5]="i386-pc-linux-gnu")
10283         * BASH_VERSION='3.2.0(1)-release'
10284         * HOSTTYPE=i386
10285         * MACHTYPE=i386-pc-linux-gnu
10286         * OSTYPE=linux-gnu
10287         * PPID=<NNNNN> - we also do it elsewhere
10288         * EUID=<NNNNN>
10289         * UID=<NNNNN>
10290         * GROUPS=()
10291         * LINES=<NNN>
10292         * COLUMNS=<NNN>
10293         * BASH_ARGC=()
10294         * BASH_ARGV=()
10295         * BASH_LINENO=()
10296         * BASH_SOURCE=()
10297         * DIRSTACK=()
10298         * PIPESTATUS=([0]="0")
10299         * HISTFILE=/<xxx>/.bash_history
10300         * HISTFILESIZE=500
10301         * HISTSIZE=500
10302         * MAILCHECK=60
10303         * PATH=/usr/gnu/bin:/usr/local/bin:/bin:/usr/bin:.
10304         * SHELL=/bin/bash
10305         * SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
10306         * TERM=dumb
10307         * OPTERR=1
10308         * OPTIND=1
10309         * PS4='+ '
10310         */
10311
10312#if NUM_SCRIPTS > 0
10313        if (argc < 0) {
10314                char *script = get_script_content(-argc - 1);
10315                G.global_argv = argv;
10316                G.global_argc = string_array_len(argv);
10317                //install_special_sighandlers(); - needed?
10318                parse_and_run_string(script);
10319                goto final_return;
10320        }
10321#endif
10322
10323        /* Initialize some more globals to non-zero values */
10324        die_func = restore_ttypgrp_and__exit;
10325
10326        /* Shell is non-interactive at first. We need to call
10327         * install_special_sighandlers() if we are going to execute "sh <script>",
10328         * "sh -c <cmds>" or login shell's /etc/profile and friends.
10329         * If we later decide that we are interactive, we run install_special_sighandlers()
10330         * in order to intercept (more) signals.
10331         */
10332
10333        /* Parse options */
10334        /* http://www.opengroup.org/onlinepubs/9699919799/utilities/sh.html */
10335        flags = (argv[0] && argv[0][0] == '-') ? OPT_login : 0;
10336        while (1) {
10337                int opt = getopt(argc, argv, "+" /* stop at 1st non-option */
10338                                "cexinsl"
10339#if !BB_MMU
10340                                "<:$:R:V:"
10341# if ENABLE_HUSH_FUNCTIONS
10342                                "F:"
10343# endif
10344#endif
10345                );
10346                if (opt <= 0)
10347                        break;
10348                switch (opt) {
10349                case 'c':
10350                        /* Note: -c is not an option with param!
10351                         * "hush -c -l SCRIPT" is valid. "hush -cSCRIPT" is not.
10352                         */
10353                        G.opt_c = 1;
10354                        break;
10355                case 'i':
10356                        /* Well, we cannot just declare interactiveness,
10357                         * we have to have some stuff (ctty, etc) */
10358                        /* G_interactive_fd++; */
10359//There are a few cases where bash -i -c 'SCRIPT'
10360//has visible effect (differs from bash -c 'SCRIPT'):
10361//it ignores TERM:
10362//      bash -i -c 'kill $$; echo ALIVE'
10363//      ALIVE
10364//it resets SIG_INGed HUP to SIG_DFL:
10365//      trap '' hup; bash -i -c 'kill -hup $$; echo ALIVE'
10366//      Hangup   [the message is not printed by bash, it's the shell which started it]
10367//is talkative about jobs and exiting:
10368//      bash -i -c 'sleep 1 & exit'
10369//      [1] 16170
10370//      exit
10371//includes $ENV file (only if run as "sh"):
10372//      echo last >/tmp/ENV; ENV=/tmp/ENV sh -i -c 'echo HERE'
10373//      last: cannot open /var/log/wtmp: No such file or directory
10374//      HERE
10375//(under "bash", it's the opposite: it runs $BASH_ENV file only *without* -i).
10376//
10377//ash -i -c 'sleep 3; sleep 3', on ^C, drops into a prompt instead of exiting
10378//(this may be a bug, bash does not do this).
10379//(ash -i -c 'sleep 3' won't show this, the last command gets auto-"exec"ed)
10380//
10381//None of the above feel like useful features people would rely on.
10382                        break;
10383                case 's':
10384                        G.opt_s = 1;
10385                        break;
10386                case 'l':
10387                        flags |= OPT_login;
10388                        break;
10389#if !BB_MMU
10390                case '<': /* "big heredoc" support */
10391                        full_write1_str(optarg);
10392                        _exit(0);
10393                case '$': {
10394                        unsigned long long empty_trap_mask;
10395
10396                        G.root_pid = bb_strtou(optarg, &optarg, 16);
10397                        optarg++;
10398                        G.root_ppid = bb_strtou(optarg, &optarg, 16);
10399                        optarg++;
10400                        G.last_bg_pid = bb_strtou(optarg, &optarg, 16);
10401                        optarg++;
10402                        G.last_exitcode = bb_strtou(optarg, &optarg, 16);
10403                        optarg++;
10404                        builtin_argc = bb_strtou(optarg, &optarg, 16);
10405                        optarg++;
10406                        empty_trap_mask = bb_strtoull(optarg, &optarg, 16);
10407                        if (empty_trap_mask != 0) {
10408                                IF_HUSH_TRAP(int sig;)
10409                                install_special_sighandlers();
10410# if ENABLE_HUSH_TRAP
10411                                G_traps = xzalloc(sizeof(G_traps[0]) * NSIG);
10412                                for (sig = 1; sig < NSIG; sig++) {
10413                                        if (empty_trap_mask & (1LL << sig)) {
10414                                                G_traps[sig] = xzalloc(1); /* == xstrdup(""); */
10415                                                install_sighandler(sig, SIG_IGN);
10416                                        }
10417                                }
10418# endif
10419                        }
10420# if ENABLE_HUSH_LOOPS
10421                        optarg++;
10422                        G.depth_of_loop = bb_strtou(optarg, &optarg, 16);
10423# endif
10424                        /* Suppress "killed by signal" message, -$ hack is used
10425                         * for subshells: echo `sh -c 'kill -9 $$'`
10426                         * should be silent.
10427                         */
10428                        IF_HUSH_JOB(G.run_list_level = 1;)
10429# if ENABLE_HUSH_FUNCTIONS
10430                        /* nommu uses re-exec trick for "... | func | ...",
10431                         * should allow "return".
10432                         * This accidentally allows returns in subshells.
10433                         */
10434                        G_flag_return_in_progress = -1;
10435# endif
10436                        break;
10437                }
10438                case 'R':
10439                case 'V':
10440                        set_local_var(xstrdup(optarg), opt == 'R' ? SETFLAG_MAKE_RO : 0);
10441                        break;
10442# if ENABLE_HUSH_FUNCTIONS
10443                case 'F': {
10444                        struct function *funcp = new_function(optarg);
10445                        /* funcp->name is already set to optarg */
10446                        /* funcp->body is set to NULL. It's a special case. */
10447                        funcp->body_as_string = argv[optind];
10448                        optind++;
10449                        break;
10450                }
10451# endif
10452#endif
10453                /*case '?': invalid option encountered (set_mode('?') will fail) */
10454                /*case 'n':*/
10455                /*case 'x':*/
10456                /*case 'e':*/
10457                default:
10458                        if (set_mode(1, opt, NULL) == 0) /* no error */
10459                                break;
10460                        bb_show_usage();
10461                }
10462        } /* option parsing loop */
10463
10464        /* Skip options. Try "hush -l": $1 should not be "-l"! */
10465        G.global_argc = argc - (optind - 1);
10466        G.global_argv = argv + (optind - 1);
10467        G.global_argv[0] = argv[0];
10468
10469        /* If we are login shell... */
10470        if (flags & OPT_login) {
10471                const char *hp = NULL;
10472                HFILE *input;
10473
10474                debug_printf("sourcing /etc/profile\n");
10475                input = hfopen("/etc/profile");
10476 run_profile:
10477                if (input != NULL) {
10478                        install_special_sighandlers();
10479                        parse_and_run_file(input);
10480                        hfclose(input);
10481                }
10482                /* bash: after sourcing /etc/profile,
10483                 * tries to source (in the given order):
10484                 * ~/.bash_profile, ~/.bash_login, ~/.profile,
10485                 * stopping on first found. --noprofile turns this off.
10486                 * bash also sources ~/.bash_logout on exit.
10487                 * If called as sh, skips .bash_XXX files.
10488                 */
10489                if (!hp) { /* unless we looped on the "goto" already */
10490                        hp = get_local_var_value("HOME");
10491                        if (hp && hp[0]) {
10492                                debug_printf("sourcing ~/.profile\n");
10493                                hp = concat_path_file(hp, ".profile");
10494                                input = hfopen(hp);
10495                                free((char*)hp);
10496                                goto run_profile;
10497                        }
10498                }
10499        }
10500
10501        /* -c takes effect *after* -l */
10502        if (G.opt_c) {
10503                /* Possibilities:
10504                 * sh ... -c 'script'
10505                 * sh ... -c 'script' ARG0 [ARG1...]
10506                 * On NOMMU, if builtin_argc != 0,
10507                 * sh ... -c 'builtin' BARGV... "" ARG0 [ARG1...]
10508                 * "" needs to be replaced with NULL
10509                 * and BARGV vector fed to builtin function.
10510                 * Note: the form without ARG0 never happens:
10511                 * sh ... -c 'builtin' BARGV... ""
10512                 */
10513                char *script;
10514
10515                install_special_sighandlers();
10516
10517                G.global_argc--;
10518                G.global_argv++;
10519#if !BB_MMU
10520                if (builtin_argc) {
10521                        /* -c 'builtin' [BARGV...] "" ARG0 [ARG1...] */
10522                        const struct built_in_command *x;
10523                        x = find_builtin(G.global_argv[0]);
10524                        if (x) { /* paranoia */
10525                                argv = G.global_argv;
10526                                G.global_argc -= builtin_argc + 1; /* skip [BARGV...] "" */
10527                                G.global_argv += builtin_argc + 1;
10528                                G.global_argv[-1] = NULL; /* replace "" */
10529                                G.last_exitcode = x->b_function(argv);
10530                        }
10531                        goto final_return;
10532                }
10533#endif
10534
10535                script = G.global_argv[0];
10536                if (!script)
10537                        bb_error_msg_and_die(bb_msg_requires_arg, "-c");
10538                if (!G.global_argv[1]) {
10539                        /* -c 'script' (no params): prevent empty $0 */
10540                        G.global_argv[0] = argv[0];
10541                } else { /* else -c 'script' ARG0 [ARG1...]: $0 is ARG0 */
10542                        G.global_argc--;
10543                        G.global_argv++;
10544                }
10545                parse_and_run_string(script);
10546                goto final_return;
10547        }
10548
10549        /* -s is: hush -s ARGV1 ARGV2 (no SCRIPT) */
10550        if (!G.opt_s && G.global_argv[1]) {
10551                HFILE *input;
10552                /*
10553                 * "bash <script>" (which is never interactive (unless -i?))
10554                 * sources $BASH_ENV here (without scanning $PATH).
10555                 * If called as sh, does the same but with $ENV.
10556                 * Also NB, per POSIX, $ENV should undergo parameter expansion.
10557                 */
10558                G.global_argc--;
10559                G.global_argv++;
10560                debug_printf("running script '%s'\n", G.global_argv[0]);
10561                xfunc_error_retval = 127; /* for "hush /does/not/exist" case */
10562                input = hfopen(G.global_argv[0]);
10563                if (!input) {
10564                        bb_simple_perror_msg_and_die(G.global_argv[0]);
10565                }
10566                xfunc_error_retval = 1;
10567                install_special_sighandlers();
10568                parse_and_run_file(input);
10569#if ENABLE_FEATURE_CLEAN_UP
10570                hfclose(input);
10571#endif
10572                goto final_return;
10573        }
10574        /* "implicit" -s: bare interactive hush shows 's' in $- */
10575        G.opt_s = 1;
10576
10577        /* Up to here, shell was non-interactive. Now it may become one.
10578         * NB: don't forget to (re)run install_special_sighandlers() as needed.
10579         */
10580
10581        /* A shell is interactive if the '-i' flag was given,
10582         * or if all of the following conditions are met:
10583         *    no -c command
10584         *    no arguments remaining or the -s flag given
10585         *    standard input is a terminal
10586         *    standard output is a terminal
10587         * Refer to Posix.2, the description of the 'sh' utility.
10588         */
10589#if ENABLE_HUSH_JOB
10590        if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
10591                G_saved_tty_pgrp = tcgetpgrp(STDIN_FILENO);
10592                debug_printf("saved_tty_pgrp:%d\n", G_saved_tty_pgrp);
10593                if (G_saved_tty_pgrp < 0)
10594                        G_saved_tty_pgrp = 0;
10595
10596                /* try to dup stdin to high fd#, >= 255 */
10597                G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, 254);
10598                if (G_interactive_fd < 0) {
10599                        /* try to dup to any fd */
10600                        G_interactive_fd = dup(STDIN_FILENO);
10601                        if (G_interactive_fd < 0) {
10602                                /* give up */
10603                                G_interactive_fd = 0;
10604                                G_saved_tty_pgrp = 0;
10605                        }
10606                }
10607        }
10608        debug_printf("interactive_fd:%d\n", G_interactive_fd);
10609        if (G_interactive_fd) {
10610                close_on_exec_on(G_interactive_fd);
10611
10612                if (G_saved_tty_pgrp) {
10613                        /* If we were run as 'hush &', sleep until we are
10614                         * in the foreground (tty pgrp == our pgrp).
10615                         * If we get started under a job aware app (like bash),
10616                         * make sure we are now in charge so we don't fight over
10617                         * who gets the foreground */
10618                        while (1) {
10619                                pid_t shell_pgrp = getpgrp();
10620                                G_saved_tty_pgrp = tcgetpgrp(G_interactive_fd);
10621                                if (G_saved_tty_pgrp == shell_pgrp)
10622                                        break;
10623                                /* send TTIN to ourself (should stop us) */
10624                                kill(- shell_pgrp, SIGTTIN);
10625                        }
10626                }
10627
10628                /* Install more signal handlers */
10629                install_special_sighandlers();
10630
10631                if (G_saved_tty_pgrp) {
10632                        /* Set other signals to restore saved_tty_pgrp */
10633                        install_fatal_sighandlers();
10634                        /* Put ourselves in our own process group
10635                         * (bash, too, does this only if ctty is available) */
10636                        bb_setpgrp(); /* is the same as setpgid(our_pid, our_pid); */
10637                        /* Grab control of the terminal */
10638                        tcsetpgrp(G_interactive_fd, cached_getpid);
10639                }
10640                enable_restore_tty_pgrp_on_exit();
10641
10642# if ENABLE_FEATURE_EDITING
10643                G.line_input_state = new_line_input_t(FOR_SHELL);
10644#  if EDITING_HAS_get_exe_name
10645                G.line_input_state->get_exe_name = get_builtin_name;
10646#  endif
10647# endif
10648# if ENABLE_HUSH_SAVEHISTORY && MAX_HISTORY > 0
10649                {
10650                        const char *hp = get_local_var_value("HISTFILE");
10651                        if (!hp) {
10652                                hp = get_local_var_value("HOME");
10653                                if (hp)
10654                                        hp = concat_path_file(hp, ".hush_history");
10655                        } else {
10656                                hp = xstrdup(hp);
10657                        }
10658                        if (hp) {
10659                                G.line_input_state->hist_file = hp;
10660                                //set_local_var(xasprintf("HISTFILE=%s", ...));
10661                        }
10662#  if ENABLE_FEATURE_SH_HISTFILESIZE
10663                        hp = get_local_var_value("HISTFILESIZE");
10664                        G.line_input_state->max_history = size_from_HISTFILESIZE(hp);
10665#  endif
10666                }
10667# endif
10668        } else {
10669                install_special_sighandlers();
10670        }
10671#elif ENABLE_HUSH_INTERACTIVE
10672        /* No job control compiled in, only prompt/line editing */
10673        if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
10674                G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, 254);
10675                if (G_interactive_fd < 0) {
10676                        /* try to dup to any fd */
10677                        G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, -1);
10678                        if (G_interactive_fd < 0)
10679                                /* give up */
10680                                G_interactive_fd = 0;
10681                }
10682        }
10683        if (G_interactive_fd) {
10684                close_on_exec_on(G_interactive_fd);
10685        }
10686        install_special_sighandlers();
10687#else
10688        /* We have interactiveness code disabled */
10689        install_special_sighandlers();
10690#endif
10691        /* bash:
10692         * if interactive but not a login shell, sources ~/.bashrc
10693         * (--norc turns this off, --rcfile <file> overrides)
10694         */
10695
10696        if (G_interactive_fd) {
10697#if ENABLE_HUSH_INTERACTIVE && ENABLE_FEATURE_EDITING_FANCY_PROMPT
10698                /* Set (but not export) PS1/2 unless already set */
10699                if (!get_local_var_value("PS1"))
10700                        set_local_var_from_halves("PS1", "\\w \\$ ");
10701                if (!get_local_var_value("PS2"))
10702                        set_local_var_from_halves("PS2", "> ");
10703#endif
10704                if (!ENABLE_FEATURE_SH_EXTRA_QUIET) {
10705                        /* note: ash and hush share this string */
10706                        printf("\n\n%s %s\n"
10707                                IF_HUSH_HELP("Enter 'help' for a list of built-in commands.\n")
10708                                "\n",
10709                                bb_banner,
10710                                "hush - the humble shell"
10711                        );
10712                }
10713        }
10714
10715        parse_and_run_file(hfopen(NULL)); /* stdin */
10716
10717 final_return:
10718        hush_exit(G.last_exitcode);
10719}
10720
10721
10722/*
10723 * Built-ins
10724 */
10725static int FAST_FUNC builtin_true(char **argv UNUSED_PARAM)
10726{
10727        return 0;
10728}
10729
10730#if ENABLE_HUSH_TEST || ENABLE_HUSH_ECHO || ENABLE_HUSH_PRINTF || ENABLE_HUSH_KILL
10731static NOINLINE int run_applet_main(char **argv, int (*applet_main_func)(int argc, char **argv))
10732{
10733        int argc = string_array_len(argv);
10734        return applet_main_func(argc, argv);
10735}
10736#endif
10737#if ENABLE_HUSH_TEST || BASH_TEST2
10738static int FAST_FUNC builtin_test(char **argv)
10739{
10740        return run_applet_main(argv, test_main);
10741}
10742#endif
10743#if ENABLE_HUSH_ECHO
10744static int FAST_FUNC builtin_echo(char **argv)
10745{
10746        return run_applet_main(argv, echo_main);
10747}
10748#endif
10749#if ENABLE_HUSH_PRINTF
10750static int FAST_FUNC builtin_printf(char **argv)
10751{
10752        return run_applet_main(argv, printf_main);
10753}
10754#endif
10755
10756#if ENABLE_HUSH_HELP
10757static int FAST_FUNC builtin_help(char **argv UNUSED_PARAM)
10758{
10759        const struct built_in_command *x;
10760
10761        printf(
10762                "Built-in commands:\n"
10763                "------------------\n");
10764        for (x = bltins1; x != &bltins1[ARRAY_SIZE(bltins1)]; x++) {
10765                if (x->b_descr)
10766                        printf("%-10s%s\n", x->b_cmd, x->b_descr);
10767        }
10768        return EXIT_SUCCESS;
10769}
10770#endif
10771
10772#if MAX_HISTORY && ENABLE_FEATURE_EDITING
10773static int FAST_FUNC builtin_history(char **argv UNUSED_PARAM)
10774{
10775        show_history(G.line_input_state);
10776        return EXIT_SUCCESS;
10777}
10778#endif
10779
10780static char **skip_dash_dash(char **argv)
10781{
10782        argv++;
10783        if (argv[0] && argv[0][0] == '-' && argv[0][1] == '-' && argv[0][2] == '\0')
10784                argv++;
10785        return argv;
10786}
10787
10788static int FAST_FUNC builtin_cd(char **argv)
10789{
10790        const char *newdir;
10791
10792        argv = skip_dash_dash(argv);
10793        newdir = argv[0];
10794        if (newdir == NULL) {
10795                /* bash does nothing (exitcode 0) if HOME is ""; if it's unset,
10796                 * bash says "bash: cd: HOME not set" and does nothing
10797                 * (exitcode 1)
10798                 */
10799                const char *home = get_local_var_value("HOME");
10800                newdir = home ? home : "/";
10801        }
10802        if (chdir(newdir)) {
10803                /* Mimic bash message exactly */
10804                bb_perror_msg("cd: %s", newdir);
10805                return EXIT_FAILURE;
10806        }
10807        /* Read current dir (get_cwd(1) is inside) and set PWD.
10808         * Note: do not enforce exporting. If PWD was unset or unexported,
10809         * set it again, but do not export. bash does the same.
10810         */
10811        set_pwd_var(/*flag:*/ 0);
10812        return EXIT_SUCCESS;
10813}
10814
10815static int FAST_FUNC builtin_pwd(char **argv UNUSED_PARAM)
10816{
10817        puts(get_cwd(0));
10818        return EXIT_SUCCESS;
10819}
10820
10821static int FAST_FUNC builtin_eval(char **argv)
10822{
10823        argv = skip_dash_dash(argv);
10824
10825        if (!argv[0])
10826                return EXIT_SUCCESS;
10827
10828        IF_HUSH_MODE_X(G.x_mode_depth++;)
10829        //bb_error_msg("%s: ++x_mode_depth=%d", __func__, G.x_mode_depth);
10830        if (!argv[1]) {
10831                /* bash:
10832                 * eval "echo Hi; done" ("done" is syntax error):
10833                 * "echo Hi" will not execute too.
10834                 */
10835                parse_and_run_string(argv[0]);
10836        } else {
10837                /* "The eval utility shall construct a command by
10838                 * concatenating arguments together, separating
10839                 * each with a <space> character."
10840                 */
10841                char *str, *p;
10842                unsigned len = 0;
10843                char **pp = argv;
10844                do
10845                        len += strlen(*pp) + 1;
10846                while (*++pp);
10847                str = p = xmalloc(len);
10848                pp = argv;
10849                for (;;) {
10850                        p = stpcpy(p, *pp);
10851                        pp++;
10852                        if (!*pp)
10853                                break;
10854                        *p++ = ' ';
10855                }
10856                parse_and_run_string(str);
10857                free(str);
10858        }
10859        IF_HUSH_MODE_X(G.x_mode_depth--;)
10860        //bb_error_msg("%s: --x_mode_depth=%d", __func__, G.x_mode_depth);
10861        return G.last_exitcode;
10862}
10863
10864static int FAST_FUNC builtin_exec(char **argv)
10865{
10866        argv = skip_dash_dash(argv);
10867        if (argv[0] == NULL)
10868                return EXIT_SUCCESS; /* bash does this */
10869
10870        /* Careful: we can end up here after [v]fork. Do not restore
10871         * tty pgrp then, only top-level shell process does that */
10872        if (G_saved_tty_pgrp && getpid() == G.root_pid)
10873                tcsetpgrp(G_interactive_fd, G_saved_tty_pgrp);
10874
10875        /* Saved-redirect fds, script fds and G_interactive_fd are still
10876         * open here. However, they are all CLOEXEC, and execv below
10877         * closes them. Try interactive "exec ls -l /proc/self/fd",
10878         * it should show no extra open fds in the "ls" process.
10879         * If we'd try to run builtins/NOEXECs, this would need improving.
10880         */
10881        //close_saved_fds_and_FILE_fds();
10882
10883        /* TODO: if exec fails, bash does NOT exit! We do.
10884         * We'll need to undo trap cleanup (it's inside execvp_or_die)
10885         * and tcsetpgrp, and this is inherently racy.
10886         */
10887        execvp_or_die(argv);
10888}
10889
10890static int FAST_FUNC builtin_exit(char **argv)
10891{
10892        debug_printf_exec("%s()\n", __func__);
10893
10894        /* interactive bash:
10895         * # trap "echo EEE" EXIT
10896         * # exit
10897         * exit
10898         * There are stopped jobs.
10899         * (if there are _stopped_ jobs, running ones don't count)
10900         * # exit
10901         * exit
10902         * EEE (then bash exits)
10903         *
10904         * TODO: we can use G.exiting = -1 as indicator "last cmd was exit"
10905         */
10906
10907        /* note: EXIT trap is run by hush_exit */
10908        argv = skip_dash_dash(argv);
10909        if (argv[0] == NULL) {
10910#if ENABLE_HUSH_TRAP
10911                if (G.pre_trap_exitcode >= 0) /* "exit" in trap uses $? from before the trap */
10912                        hush_exit(G.pre_trap_exitcode);
10913#endif
10914                hush_exit(G.last_exitcode);
10915        }
10916        /* mimic bash: exit 123abc == exit 255 + error msg */
10917        xfunc_error_retval = 255;
10918        /* bash: exit -2 == exit 254, no error msg */
10919        hush_exit(xatoi(argv[0]) & 0xff);
10920}
10921
10922#if ENABLE_HUSH_TYPE
10923/* http://www.opengroup.org/onlinepubs/9699919799/utilities/type.html */
10924static int FAST_FUNC builtin_type(char **argv)
10925{
10926        int ret = EXIT_SUCCESS;
10927
10928        while (*++argv) {
10929                const char *type;
10930                char *path = NULL;
10931
10932                if (0) {} /* make conditional compile easier below */
10933                /*else if (find_alias(*argv))
10934                        type = "an alias";*/
10935# if ENABLE_HUSH_FUNCTIONS
10936                else if (find_function(*argv))
10937                        type = "a function";
10938# endif
10939                else if (find_builtin(*argv))
10940                        type = "a shell builtin";
10941                else if ((path = find_in_path(*argv)) != NULL)
10942                        type = path;
10943                else {
10944                        bb_error_msg("type: %s: not found", *argv);
10945                        ret = EXIT_FAILURE;
10946                        continue;
10947                }
10948
10949                printf("%s is %s\n", *argv, type);
10950                free(path);
10951        }
10952
10953        return ret;
10954}
10955#endif
10956
10957#if ENABLE_HUSH_READ
10958/* Interruptibility of read builtin in bash
10959 * (tested on bash-4.2.8 by sending signals (not by ^C)):
10960 *
10961 * Empty trap makes read ignore corresponding signal, for any signal.
10962 *
10963 * SIGINT:
10964 * - terminates non-interactive shell;
10965 * - interrupts read in interactive shell;
10966 * if it has non-empty trap:
10967 * - executes trap and returns to command prompt in interactive shell;
10968 * - executes trap and returns to read in non-interactive shell;
10969 * SIGTERM:
10970 * - is ignored (does not interrupt) read in interactive shell;
10971 * - terminates non-interactive shell;
10972 * if it has non-empty trap:
10973 * - executes trap and returns to read;
10974 * SIGHUP:
10975 * - terminates shell (regardless of interactivity);
10976 * if it has non-empty trap:
10977 * - executes trap and returns to read;
10978 * SIGCHLD from children:
10979 * - does not interrupt read regardless of interactivity:
10980 *   try: sleep 1 & read x; echo $x
10981 */
10982static int FAST_FUNC builtin_read(char **argv)
10983{
10984        const char *r;
10985        struct builtin_read_params params;
10986
10987        memset(&params, 0, sizeof(params));
10988
10989        /* "!": do not abort on errors.
10990         * Option string must start with "sr" to match BUILTIN_READ_xxx
10991         */
10992        params.read_flags = getopt32(argv,
10993# if BASH_READ_D
10994                IF_NOT_HUSH_BASH_COMPAT("^")
10995                "!srn:p:t:u:d:" IF_NOT_HUSH_BASH_COMPAT("\0" "-1"/*min 1 arg*/),
10996                &params.opt_n, &params.opt_p, &params.opt_t, &params.opt_u, &params.opt_d
10997# else
10998                IF_NOT_HUSH_BASH_COMPAT("^")
10999                "!srn:p:t:u:" IF_NOT_HUSH_BASH_COMPAT("\0" "-1"/*min 1 arg*/),
11000                &params.opt_n, &params.opt_p, &params.opt_t, &params.opt_u
11001# endif
11002//TODO: print "read: need variable name"
11003//for the case of !BASH "read" with no args (now it fails silently)
11004//(or maybe extend getopt32() to emit a message if "-1" fails)
11005        );
11006        if ((uint32_t)params.read_flags == (uint32_t)-1)
11007                return EXIT_FAILURE;
11008        argv += optind;
11009        params.argv = argv;
11010        params.setvar = set_local_var_from_halves;
11011        params.ifs = get_local_var_value("IFS"); /* can be NULL */
11012
11013 again:
11014        r = shell_builtin_read(&params);
11015
11016        if ((uintptr_t)r == 1 && errno == EINTR) {
11017                unsigned sig = check_and_run_traps();
11018                if (sig != SIGINT)
11019                        goto again;
11020        }
11021
11022        if ((uintptr_t)r > 1) {
11023                bb_simple_error_msg(r);
11024                r = (char*)(uintptr_t)1;
11025        }
11026
11027        return (uintptr_t)r;
11028}
11029#endif
11030
11031#if ENABLE_HUSH_UMASK
11032static int FAST_FUNC builtin_umask(char **argv)
11033{
11034        int rc;
11035        mode_t mask;
11036
11037        rc = 1;
11038        mask = umask(0);
11039        argv = skip_dash_dash(argv);
11040        if (argv[0]) {
11041                mode_t old_mask = mask;
11042
11043                /* numeric umasks are taken as-is */
11044                /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
11045                if (!isdigit(argv[0][0]))
11046                        mask ^= 0777;
11047                mask = bb_parse_mode(argv[0], mask);
11048                if (!isdigit(argv[0][0]))
11049                        mask ^= 0777;
11050                if ((unsigned)mask > 0777) {
11051                        mask = old_mask;
11052                        /* bash messages:
11053                         * bash: umask: 'q': invalid symbolic mode operator
11054                         * bash: umask: 999: octal number out of range
11055                         */
11056                        bb_error_msg("%s: invalid mode '%s'", "umask", argv[0]);
11057                        rc = 0;
11058                }
11059        } else {
11060                /* Mimic bash */
11061                printf("%04o\n", (unsigned) mask);
11062                /* fall through and restore mask which we set to 0 */
11063        }
11064        umask(mask);
11065
11066        return !rc; /* rc != 0 - success */
11067}
11068#endif
11069
11070#if ENABLE_HUSH_EXPORT || ENABLE_HUSH_TRAP
11071static void print_escaped(const char *s)
11072{
11073        if (*s == '\'')
11074                goto squote;
11075        do {
11076                const char *p = strchrnul(s, '\'');
11077                /* print 'xxxx', possibly just '' */
11078                printf("'%.*s'", (int)(p - s), s);
11079                if (*p == '\0')
11080                        break;
11081                s = p;
11082 squote:
11083                /* s points to '; print "'''...'''" */
11084                putchar('"');
11085                do putchar('\''); while (*++s == '\'');
11086                putchar('"');
11087        } while (*s);
11088}
11089#endif
11090
11091#if ENABLE_HUSH_EXPORT || ENABLE_HUSH_LOCAL || ENABLE_HUSH_READONLY
11092static int helper_export_local(char **argv, unsigned flags)
11093{
11094        do {
11095                char *name = *argv;
11096                const char *name_end = endofname(name);
11097
11098                if (*name_end == '\0') {
11099                        struct variable *var, **vpp;
11100
11101                        vpp = get_ptr_to_local_var(name, name_end - name);
11102                        var = vpp ? *vpp : NULL;
11103
11104                        if (flags & SETFLAG_UNEXPORT) {
11105                                /* export -n NAME (without =VALUE) */
11106                                if (var) {
11107                                        var->flg_export = 0;
11108                                        debug_printf_env("%s: unsetenv '%s'\n", __func__, name);
11109                                        unsetenv(name);
11110                                } /* else: export -n NOT_EXISTING_VAR: no-op */
11111                                continue;
11112                        }
11113                        if (flags & SETFLAG_EXPORT) {
11114                                /* export NAME (without =VALUE) */
11115                                if (var) {
11116                                        var->flg_export = 1;
11117                                        debug_printf_env("%s: putenv '%s'\n", __func__, var->varstr);
11118                                        putenv(var->varstr);
11119                                        continue;
11120                                }
11121                        }
11122                        if (flags & SETFLAG_MAKE_RO) {
11123                                /* readonly NAME (without =VALUE) */
11124                                if (var) {
11125                                        var->flg_read_only = 1;
11126                                        continue;
11127                                }
11128                        }
11129# if ENABLE_HUSH_LOCAL
11130                        /* Is this "local" bltin? */
11131                        if (!(flags & (SETFLAG_EXPORT|SETFLAG_UNEXPORT|SETFLAG_MAKE_RO))) {
11132                                unsigned lvl = flags >> SETFLAG_VARLVL_SHIFT;
11133                                if (var && var->var_nest_level == lvl) {
11134                                        /* "local x=abc; ...; local x" - ignore second local decl */
11135                                        continue;
11136                                }
11137                        }
11138# endif
11139                        /* Exporting non-existing variable.
11140                         * bash does not put it in environment,
11141                         * but remembers that it is exported,
11142                         * and does put it in env when it is set later.
11143                         * We just set it to "" and export.
11144                         */
11145                        /* Or, it's "local NAME" (without =VALUE).
11146                         * bash sets the value to "".
11147                         */
11148                        /* Or, it's "readonly NAME" (without =VALUE).
11149                         * bash remembers NAME and disallows its creation
11150                         * in the future.
11151                         */
11152                        name = xasprintf("%s=", name);
11153                } else {
11154                        if (*name_end != '=') {
11155                                bb_error_msg("'%s': bad variable name", name);
11156                                /* do not parse following argv[]s: */
11157                                return 1;
11158                        }
11159                        /* (Un)exporting/making local NAME=VALUE */
11160                        name = xstrdup(name);
11161                        /* Testcase: export PS1='\w \$ ' */
11162                        unbackslash(name);
11163                }
11164                debug_printf_env("%s: set_local_var('%s')\n", __func__, name);
11165                if (set_local_var(name, flags))
11166                        return EXIT_FAILURE;
11167        } while (*++argv);
11168        return EXIT_SUCCESS;
11169}
11170#endif
11171
11172#if ENABLE_HUSH_EXPORT
11173static int FAST_FUNC builtin_export(char **argv)
11174{
11175        unsigned opt_unexport;
11176
11177# if ENABLE_HUSH_EXPORT_N
11178        /* "!": do not abort on errors */
11179        opt_unexport = getopt32(argv, "!n");
11180        if (opt_unexport == (uint32_t)-1)
11181                return EXIT_FAILURE;
11182        argv += optind;
11183# else
11184        opt_unexport = 0;
11185        argv++;
11186# endif
11187
11188        if (argv[0] == NULL) {
11189                char **e = environ;
11190                if (e) {
11191                        while (*e) {
11192# if 0
11193                                puts(*e++);
11194# else
11195                                /* ash emits: export VAR='VAL'
11196                                 * bash: declare -x VAR="VAL"
11197                                 * we follow ash example */
11198                                const char *s = *e++;
11199                                const char *p = strchr(s, '=');
11200
11201                                if (!p) /* wtf? take next variable */
11202                                        continue;
11203                                /* export var= */
11204                                printf("export %.*s", (int)(p - s) + 1, s);
11205                                print_escaped(p + 1);
11206                                putchar('\n');
11207# endif
11208                        }
11209                        /*fflush_all(); - done after each builtin anyway */
11210                }
11211                return EXIT_SUCCESS;
11212        }
11213
11214        return helper_export_local(argv, opt_unexport ? SETFLAG_UNEXPORT : SETFLAG_EXPORT);
11215}
11216#endif
11217
11218#if ENABLE_HUSH_LOCAL
11219static int FAST_FUNC builtin_local(char **argv)
11220{
11221        if (G.func_nest_level == 0) {
11222                bb_error_msg("%s: not in a function", argv[0]);
11223                return EXIT_FAILURE; /* bash compat */
11224        }
11225        argv++;
11226        /* Since all builtins run in a nested variable level,
11227         * need to use level - 1 here. Or else the variable will be removed at once
11228         * after builtin returns.
11229         */
11230        return helper_export_local(argv, (G.var_nest_level - 1) << SETFLAG_VARLVL_SHIFT);
11231}
11232#endif
11233
11234#if ENABLE_HUSH_READONLY
11235static int FAST_FUNC builtin_readonly(char **argv)
11236{
11237        argv++;
11238        if (*argv == NULL) {
11239                /* bash: readonly [-p]: list all readonly VARs
11240                 * (-p has no effect in bash)
11241                 */
11242                struct variable *e;
11243                for (e = G.top_var; e; e = e->next) {
11244                        if (e->flg_read_only) {
11245//TODO: quote value: readonly VAR='VAL'
11246                                printf("readonly %s\n", e->varstr);
11247                        }
11248                }
11249                return EXIT_SUCCESS;
11250        }
11251        return helper_export_local(argv, SETFLAG_MAKE_RO);
11252}
11253#endif
11254
11255#if ENABLE_HUSH_UNSET
11256/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#unset */
11257static int FAST_FUNC builtin_unset(char **argv)
11258{
11259        int ret;
11260        unsigned opts;
11261
11262        /* "!": do not abort on errors */
11263        /* "+": stop at 1st non-option */
11264        opts = getopt32(argv, "!+vf");
11265        if (opts == (unsigned)-1)
11266                return EXIT_FAILURE;
11267        if (opts == 3) {
11268                bb_simple_error_msg("unset: -v and -f are exclusive");
11269                return EXIT_FAILURE;
11270        }
11271        argv += optind;
11272
11273        ret = EXIT_SUCCESS;
11274        while (*argv) {
11275                if (!(opts & 2)) { /* not -f */
11276                        if (unset_local_var(*argv)) {
11277                                /* unset <nonexistent_var> doesn't fail.
11278                                 * Error is when one tries to unset RO var.
11279                                 * Message was printed by unset_local_var. */
11280                                ret = EXIT_FAILURE;
11281                        }
11282                }
11283# if ENABLE_HUSH_FUNCTIONS
11284                else {
11285                        unset_func(*argv);
11286                }
11287# endif
11288                argv++;
11289        }
11290        return ret;
11291}
11292#endif
11293
11294#if ENABLE_HUSH_SET
11295/* http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set
11296 * built-in 'set' handler
11297 * SUSv3 says:
11298 * set [-abCefhmnuvx] [-o option] [argument...]
11299 * set [+abCefhmnuvx] [+o option] [argument...]
11300 * set -- [argument...]
11301 * set -o
11302 * set +o
11303 * Implementations shall support the options in both their hyphen and
11304 * plus-sign forms. These options can also be specified as options to sh.
11305 * Examples:
11306 * Write out all variables and their values: set
11307 * Set $1, $2, and $3 and set "$#" to 3: set c a b
11308 * Turn on the -x and -v options: set -xv
11309 * Unset all positional parameters: set --
11310 * Set $1 to the value of x, even if it begins with '-' or '+': set -- "$x"
11311 * Set the positional parameters to the expansion of x, even if x expands
11312 * with a leading '-' or '+': set -- $x
11313 *
11314 * So far, we only support "set -- [argument...]" and some of the short names.
11315 */
11316static int FAST_FUNC builtin_set(char **argv)
11317{
11318        int n;
11319        char **pp, **g_argv;
11320        char *arg = *++argv;
11321
11322        if (arg == NULL) {
11323                struct variable *e;
11324                for (e = G.top_var; e; e = e->next)
11325                        puts(e->varstr);
11326                return EXIT_SUCCESS;
11327        }
11328
11329        do {
11330                if (strcmp(arg, "--") == 0) {
11331                        ++argv;
11332                        goto set_argv;
11333                }
11334                if (arg[0] != '+' && arg[0] != '-')
11335                        break;
11336                for (n = 1; arg[n]; ++n) {
11337                        if (set_mode((arg[0] == '-'), arg[n], argv[1])) {
11338                                bb_error_msg("%s: %s: invalid option", "set", arg);
11339                                return EXIT_FAILURE;
11340                        }
11341                        if (arg[n] == 'o' && argv[1])
11342                                argv++;
11343                }
11344        } while ((arg = *++argv) != NULL);
11345        /* Now argv[0] is 1st argument */
11346
11347        if (arg == NULL)
11348                return EXIT_SUCCESS;
11349 set_argv:
11350
11351        /* NB: G.global_argv[0] ($0) is never freed/changed */
11352        g_argv = G.global_argv;
11353        if (G.global_args_malloced) {
11354                pp = g_argv;
11355                while (*++pp)
11356                        free(*pp);
11357                g_argv[1] = NULL;
11358        } else {
11359                G.global_args_malloced = 1;
11360                pp = xzalloc(sizeof(pp[0]) * 2);
11361                pp[0] = g_argv[0]; /* retain $0 */
11362                g_argv = pp;
11363        }
11364        /* This realloc's G.global_argv */
11365        G.global_argv = pp = add_strings_to_strings(g_argv, argv, /*dup:*/ 1);
11366
11367        G.global_argc = 1 + string_array_len(pp + 1);
11368
11369        return EXIT_SUCCESS;
11370}
11371#endif
11372
11373static int FAST_FUNC builtin_shift(char **argv)
11374{
11375        int n = 1;
11376        argv = skip_dash_dash(argv);
11377        if (argv[0]) {
11378                n = bb_strtou(argv[0], NULL, 10);
11379                if (errno || n < 0) {
11380                        /* shared string with ash.c */
11381                        bb_error_msg("Illegal number: %s", argv[0]);
11382                        /*
11383                         * ash aborts in this case.
11384                         * bash prints error message and set $? to 1.
11385                         * Interestingly, for "shift 99999" bash does not
11386                         * print error message, but does set $? to 1
11387                         * (and does no shifting at all).
11388                         */
11389                }
11390        }
11391        if (n >= 0 && n < G.global_argc) {
11392                if (G_global_args_malloced) {
11393                        int m = 1;
11394                        while (m <= n)
11395                                free(G.global_argv[m++]);
11396                }
11397                G.global_argc -= n;
11398                memmove(&G.global_argv[1], &G.global_argv[n+1],
11399                                G.global_argc * sizeof(G.global_argv[0]));
11400                return EXIT_SUCCESS;
11401        }
11402        return EXIT_FAILURE;
11403}
11404
11405#if ENABLE_HUSH_GETOPTS
11406static int FAST_FUNC builtin_getopts(char **argv)
11407{
11408/* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/getopts.html
11409
11410TODO:
11411If a required argument is not found, and getopts is not silent,
11412a question mark (?) is placed in VAR, OPTARG is unset, and a
11413diagnostic message is printed.  If getopts is silent, then a
11414colon (:) is placed in VAR and OPTARG is set to the option
11415character found.
11416
11417Test that VAR is a valid variable name?
11418
11419"Whenever the shell is invoked, OPTIND shall be initialized to 1"
11420*/
11421        char cbuf[2];
11422        const char *cp, *optstring, *var;
11423        int c, n, exitcode, my_opterr;
11424        unsigned count;
11425
11426        optstring = *++argv;
11427        if (!optstring || !(var = *++argv)) {
11428                bb_simple_error_msg("usage: getopts OPTSTRING VAR [ARGS]");
11429                return EXIT_FAILURE;
11430        }
11431
11432        if (argv[1])
11433                argv[0] = G.global_argv[0]; /* for error messages in getopt() */
11434        else
11435                argv = G.global_argv;
11436        cbuf[1] = '\0';
11437
11438        my_opterr = 0;
11439        if (optstring[0] != ':') {
11440                cp = get_local_var_value("OPTERR");
11441                /* 0 if "OPTERR=0", 1 otherwise */
11442                my_opterr = (!cp || NOT_LONE_CHAR(cp, '0'));
11443        }
11444
11445        /* getopts stops on first non-option. Add "+" to force that */
11446        /*if (optstring[0] != '+')*/ {
11447                char *s = alloca(strlen(optstring) + 2);
11448                sprintf(s, "+%s", optstring);
11449                optstring = s;
11450        }
11451
11452        /* Naively, now we should just
11453         *      cp = get_local_var_value("OPTIND");
11454         *      optind = cp ? atoi(cp) : 0;
11455         *      optarg = NULL;
11456         *      opterr = my_opterr;
11457         *      c = getopt(string_array_len(argv), argv, optstring);
11458         * and be done? Not so fast...
11459         * Unlike normal getopt() usage in C programs, here
11460         * each successive call will (usually) have the same argv[] CONTENTS,
11461         * but not the ADDRESSES. Worse yet, it's possible that between
11462         * invocations of "getopts", there will be calls to shell builtins
11463         * which use getopt() internally. Example:
11464         *      while getopts "abc" RES -a -bc -abc de; do
11465         *              unset -ff func
11466         *      done
11467         * This would not work correctly: getopt() call inside "unset"
11468         * modifies internal libc state which is tracking position in
11469         * multi-option strings ("-abc"). At best, it can skip options
11470         * or return the same option infinitely. With glibc implementation
11471         * of getopt(), it would use outright invalid pointers and return
11472         * garbage even _without_ "unset" mangling internal state.
11473         *
11474         * We resort to resetting getopt() state and calling it N times,
11475         * until we get Nth result (or failure).
11476         * (N == G.getopt_count is reset to 0 whenever OPTIND is [un]set).
11477         */
11478        GETOPT_RESET();
11479        count = 0;
11480        n = string_array_len(argv);
11481        do {
11482                optarg = NULL;
11483                opterr = (count < G.getopt_count) ? 0 : my_opterr;
11484                c = getopt(n, argv, optstring);
11485                if (c < 0)
11486                        break;
11487                count++;
11488        } while (count <= G.getopt_count);
11489
11490        /* Set OPTIND. Prevent resetting of the magic counter! */
11491        set_local_var_from_halves("OPTIND", utoa(optind));
11492        G.getopt_count = count; /* "next time, give me N+1'th result" */
11493        GETOPT_RESET(); /* just in case */
11494
11495        /* Set OPTARG */
11496        /* Always set or unset, never left as-is, even on exit/error:
11497         * "If no option was found, or if the option that was found
11498         * does not have an option-argument, OPTARG shall be unset."
11499         */
11500        cp = optarg;
11501        if (c == '?') {
11502                /* If ":optstring" and unknown option is seen,
11503                 * it is stored to OPTARG.
11504                 */
11505                if (optstring[1] == ':') {
11506                        cbuf[0] = optopt;
11507                        cp = cbuf;
11508                }
11509        }
11510        if (cp)
11511                set_local_var_from_halves("OPTARG", cp);
11512        else
11513                unset_local_var("OPTARG");
11514
11515        /* Convert -1 to "?" */
11516        exitcode = EXIT_SUCCESS;
11517        if (c < 0) { /* -1: end of options */
11518                exitcode = EXIT_FAILURE;
11519                c = '?';
11520        }
11521
11522        /* Set VAR */
11523        cbuf[0] = c;
11524        set_local_var_from_halves(var, cbuf);
11525
11526        return exitcode;
11527}
11528#endif
11529
11530static int FAST_FUNC builtin_source(char **argv)
11531{
11532        char *arg_path, *filename;
11533        HFILE *input;
11534        save_arg_t sv;
11535        char *args_need_save;
11536#if ENABLE_HUSH_FUNCTIONS
11537        smallint sv_flg;
11538#endif
11539
11540        argv = skip_dash_dash(argv);
11541        filename = argv[0];
11542        if (!filename) {
11543                /* bash says: "bash: .: filename argument required" */
11544                return 2; /* bash compat */
11545        }
11546        arg_path = NULL;
11547        if (!strchr(filename, '/')) {
11548                arg_path = find_in_path(filename);
11549                if (arg_path)
11550                        filename = arg_path;
11551                else if (!ENABLE_HUSH_BASH_SOURCE_CURDIR) {
11552                        errno = ENOENT;
11553                        bb_simple_perror_msg(filename);
11554                        return EXIT_FAILURE;
11555                }
11556        }
11557        input = hfopen(filename);
11558        free(arg_path);
11559        if (!input) {
11560                bb_perror_msg("%s", filename);
11561                /* POSIX: non-interactive shell should abort here,
11562                 * not merely fail. So far no one complained :)
11563                 */
11564                return EXIT_FAILURE;
11565        }
11566
11567#if ENABLE_HUSH_FUNCTIONS
11568        sv_flg = G_flag_return_in_progress;
11569        /* "we are inside sourced file, ok to use return" */
11570        G_flag_return_in_progress = -1;
11571#endif
11572        args_need_save = argv[1]; /* used as a boolean variable */
11573        if (args_need_save)
11574                save_and_replace_G_args(&sv, argv);
11575
11576        /* "false; . ./empty_line; echo Zero:$?" should print 0 */
11577        G.last_exitcode = 0;
11578        parse_and_run_file(input);
11579        hfclose(input);
11580
11581        if (args_need_save) /* can't use argv[1] instead: "shift" can mangle it */
11582                restore_G_args(&sv, argv);
11583#if ENABLE_HUSH_FUNCTIONS
11584        G_flag_return_in_progress = sv_flg;
11585#endif
11586
11587        return G.last_exitcode;
11588}
11589
11590#if ENABLE_HUSH_TRAP
11591static int FAST_FUNC builtin_trap(char **argv)
11592{
11593        int sig;
11594        char *new_cmd;
11595
11596        if (!G_traps)
11597                G_traps = xzalloc(sizeof(G_traps[0]) * NSIG);
11598
11599        argv++;
11600        if (!*argv) {
11601                int i;
11602                /* No args: print all trapped */
11603                for (i = 0; i < NSIG; ++i) {
11604                        if (G_traps[i]) {
11605                                printf("trap -- ");
11606                                print_escaped(G_traps[i]);
11607                                /* note: bash adds "SIG", but only if invoked
11608                                 * as "bash". If called as "sh", or if set -o posix,
11609                                 * then it prints short signal names.
11610                                 * We are printing short names: */
11611                                printf(" %s\n", get_signame(i));
11612                        }
11613                }
11614                /*fflush_all(); - done after each builtin anyway */
11615                return EXIT_SUCCESS;
11616        }
11617
11618        new_cmd = NULL;
11619        /* If first arg is a number: reset all specified signals */
11620        sig = bb_strtou(*argv, NULL, 10);
11621        if (errno == 0) {
11622                int ret;
11623 process_sig_list:
11624                ret = EXIT_SUCCESS;
11625                while (*argv) {
11626                        sighandler_t handler;
11627
11628                        sig = get_signum(*argv++);
11629                        if (sig < 0) {
11630                                ret = EXIT_FAILURE;
11631                                /* Mimic bash message exactly */
11632                                bb_error_msg("trap: %s: invalid signal specification", argv[-1]);
11633                                continue;
11634                        }
11635
11636                        free(G_traps[sig]);
11637                        G_traps[sig] = xstrdup(new_cmd);
11638
11639                        debug_printf("trap: setting SIG%s (%i) to '%s'\n",
11640                                get_signame(sig), sig, G_traps[sig]);
11641
11642                        /* There is no signal for 0 (EXIT) */
11643                        if (sig == 0)
11644                                continue;
11645
11646                        if (new_cmd)
11647                                handler = (new_cmd[0] ? record_pending_signo : SIG_IGN);
11648                        else
11649                                /* We are removing trap handler */
11650                                handler = pick_sighandler(sig);
11651                        install_sighandler(sig, handler);
11652                }
11653                return ret;
11654        }
11655
11656        if (!argv[1]) { /* no second arg */
11657                bb_simple_error_msg("trap: invalid arguments");
11658                return EXIT_FAILURE;
11659        }
11660
11661        /* First arg is "-": reset all specified to default */
11662        /* First arg is "--": skip it, the rest is "handler SIGs..." */
11663        /* Everything else: set arg as signal handler
11664         * (includes "" case, which ignores signal) */
11665        if (argv[0][0] == '-') {
11666                if (argv[0][1] == '\0') { /* "-" */
11667                        /* new_cmd remains NULL: "reset these sigs" */
11668                        goto reset_traps;
11669                }
11670                if (argv[0][1] == '-' && argv[0][2] == '\0') { /* "--" */
11671                        argv++;
11672                }
11673                /* else: "-something", no special meaning */
11674        }
11675        new_cmd = *argv;
11676 reset_traps:
11677        argv++;
11678        goto process_sig_list;
11679}
11680#endif
11681
11682#if ENABLE_HUSH_JOB
11683static struct pipe *parse_jobspec(const char *str)
11684{
11685        struct pipe *pi;
11686        unsigned jobnum;
11687
11688        if (sscanf(str, "%%%u", &jobnum) != 1) {
11689                if (str[0] != '%'
11690                 || (str[1] != '%' && str[1] != '+' && str[1] != '\0')
11691                ) {
11692                        bb_error_msg("bad argument '%s'", str);
11693                        return NULL;
11694                }
11695                /* It is "%%", "%+" or "%" - current job */
11696                jobnum = G.last_jobid;
11697                if (jobnum == 0) {
11698                        bb_simple_error_msg("no current job");
11699                        return NULL;
11700                }
11701        }
11702        for (pi = G.job_list; pi; pi = pi->next) {
11703                if (pi->jobid == jobnum) {
11704                        return pi;
11705                }
11706        }
11707        bb_error_msg("%u: no such job", jobnum);
11708        return NULL;
11709}
11710
11711static int FAST_FUNC builtin_jobs(char **argv UNUSED_PARAM)
11712{
11713        struct pipe *job;
11714        const char *status_string;
11715
11716        checkjobs(NULL, 0 /*(no pid to wait for)*/);
11717        for (job = G.job_list; job; job = job->next) {
11718                if (job->alive_cmds == job->stopped_cmds)
11719                        status_string = "Stopped";
11720                else
11721                        status_string = "Running";
11722
11723                printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->cmdtext);
11724        }
11725
11726        clean_up_last_dead_job();
11727
11728        return EXIT_SUCCESS;
11729}
11730
11731/* built-in 'fg' and 'bg' handler */
11732static int FAST_FUNC builtin_fg_bg(char **argv)
11733{
11734        int i;
11735        struct pipe *pi;
11736
11737        if (!G_interactive_fd)
11738                return EXIT_FAILURE;
11739
11740        /* If they gave us no args, assume they want the last backgrounded task */
11741        if (!argv[1]) {
11742                for (pi = G.job_list; pi; pi = pi->next) {
11743                        if (pi->jobid == G.last_jobid) {
11744                                goto found;
11745                        }
11746                }
11747                bb_error_msg("%s: no current job", argv[0]);
11748                return EXIT_FAILURE;
11749        }
11750
11751        pi = parse_jobspec(argv[1]);
11752        if (!pi)
11753                return EXIT_FAILURE;
11754 found:
11755        /* TODO: bash prints a string representation
11756         * of job being foregrounded (like "sleep 1 | cat") */
11757        if (argv[0][0] == 'f' && G_saved_tty_pgrp) {
11758                /* Put the job into the foreground. */
11759                tcsetpgrp(G_interactive_fd, pi->pgrp);
11760        }
11761
11762        /* Restart the processes in the job */
11763        debug_printf_jobs("reviving %d procs, pgrp %d\n", pi->num_cmds, pi->pgrp);
11764        for (i = 0; i < pi->num_cmds; i++) {
11765                debug_printf_jobs("reviving pid %d\n", pi->cmds[i].pid);
11766        }
11767        pi->stopped_cmds = 0;
11768
11769        i = kill(- pi->pgrp, SIGCONT);
11770        if (i < 0) {
11771                if (errno == ESRCH) {
11772                        delete_finished_job(pi);
11773                        return EXIT_SUCCESS;
11774                }
11775                bb_simple_perror_msg("kill (SIGCONT)");
11776        }
11777
11778        if (argv[0][0] == 'f') {
11779                remove_job_from_table(pi); /* FG job shouldn't be in job table */
11780                return checkjobs_and_fg_shell(pi);
11781        }
11782        return EXIT_SUCCESS;
11783}
11784#endif
11785
11786#if ENABLE_HUSH_KILL
11787static int FAST_FUNC builtin_kill(char **argv)
11788{
11789        int ret = 0;
11790
11791# if ENABLE_HUSH_JOB
11792        if (argv[1] && strcmp(argv[1], "-l") != 0) {
11793                int i = 1;
11794
11795                do {
11796                        struct pipe *pi;
11797                        char *dst;
11798                        int j, n;
11799
11800                        if (argv[i][0] != '%')
11801                                continue;
11802                        /*
11803                         * "kill %N" - job kill
11804                         * Converting to pgrp / pid kill
11805                         */
11806                        pi = parse_jobspec(argv[i]);
11807                        if (!pi) {
11808                                /* Eat bad jobspec */
11809                                j = i;
11810                                do {
11811                                        j++;
11812                                        argv[j - 1] = argv[j];
11813                                } while (argv[j]);
11814                                ret = 1;
11815                                i--;
11816                                continue;
11817                        }
11818                        /*
11819                         * In jobs started under job control, we signal
11820                         * entire process group by kill -PGRP_ID.
11821                         * This happens, f.e., in interactive shell.
11822                         *
11823                         * Otherwise, we signal each child via
11824                         * kill PID1 PID2 PID3.
11825                         * Testcases:
11826                         * sh -c 'sleep 1|sleep 1 & kill %1'
11827                         * sh -c 'true|sleep 2 & sleep 1; kill %1'
11828                         * sh -c 'true|sleep 1 & sleep 2; kill %1'
11829                         */
11830                        n = G_interactive_fd ? 1 : pi->num_cmds;
11831                        dst = alloca(n * sizeof(int)*4);
11832                        argv[i] = dst;
11833                        if (G_interactive_fd)
11834                                dst += sprintf(dst, " -%u", (int)pi->pgrp);
11835                        else for (j = 0; j < n; j++) {
11836                                struct command *cmd = &pi->cmds[j];
11837                                /* Skip exited members of the job */
11838                                if (cmd->pid == 0)
11839                                        continue;
11840                                /*
11841                                 * kill_main has matching code to expect
11842                                 * leading space. Needed to not confuse
11843                                 * negative pids with "kill -SIGNAL_NO" syntax
11844                                 */
11845                                dst += sprintf(dst, " %u", (int)cmd->pid);
11846                        }
11847                        *dst = '\0';
11848                } while (argv[++i]);
11849        }
11850# endif
11851
11852        if (argv[1] || ret == 0) {
11853                ret = run_applet_main(argv, kill_main);
11854        }
11855        /* else: ret = 1, "kill %bad_jobspec" case */
11856        return ret;
11857}
11858#endif
11859
11860#if ENABLE_HUSH_WAIT
11861/* http://www.opengroup.org/onlinepubs/9699919799/utilities/wait.html */
11862# if !ENABLE_HUSH_JOB
11863#  define wait_for_child_or_signal(pipe,pid) wait_for_child_or_signal(pid)
11864# endif
11865static int wait_for_child_or_signal(struct pipe *waitfor_pipe, pid_t waitfor_pid)
11866{
11867        int ret = 0;
11868        for (;;) {
11869                int sig;
11870                sigset_t oldset;
11871
11872                if (!sigisemptyset(&G.pending_set))
11873                        goto check_sig;
11874
11875                /* waitpid is not interruptible by SA_RESTARTed
11876                 * signals which we use. Thus, this ugly dance:
11877                 */
11878
11879                /* Make sure possible SIGCHLD is stored in kernel's
11880                 * pending signal mask before we call waitpid.
11881                 * Or else we may race with SIGCHLD, lose it,
11882                 * and get stuck in sigsuspend...
11883                 */
11884                sigfillset(&oldset); /* block all signals, remember old set */
11885                sigprocmask2(SIG_SETMASK, &oldset);
11886
11887                if (!sigisemptyset(&G.pending_set)) {
11888                        /* Crap! we raced with some signal! */
11889                        goto restore;
11890                }
11891
11892                /*errno = 0; - checkjobs does this */
11893/* Can't pass waitfor_pipe into checkjobs(): it won't be interruptible */
11894                ret = checkjobs(NULL, waitfor_pid); /* waitpid(WNOHANG) inside */
11895                debug_printf_exec("checkjobs:%d\n", ret);
11896# if ENABLE_HUSH_JOB
11897                if (waitfor_pipe) {
11898                        int rcode = job_exited_or_stopped(waitfor_pipe);
11899                        debug_printf_exec("job_exited_or_stopped:%d\n", rcode);
11900                        if (rcode >= 0) {
11901                                ret = rcode;
11902                                sigprocmask(SIG_SETMASK, &oldset, NULL);
11903                                break;
11904                        }
11905                }
11906# endif
11907                /* if ECHILD, there are no children (ret is -1 or 0) */
11908                /* if ret == 0, no children changed state */
11909                /* if ret != 0, it's exitcode+1 of exited waitfor_pid child */
11910                if (errno == ECHILD || ret) {
11911                        ret--;
11912                        if (ret < 0) /* if ECHILD, may need to fix "ret" */
11913                                ret = 0;
11914# if ENABLE_HUSH_BASH_COMPAT
11915                        if (waitfor_pid == -1 && errno == ECHILD) {
11916                                /* exitcode of "wait -n" with no children is 127, not 0 */
11917                                ret = 127;
11918                        }
11919# endif
11920                        sigprocmask(SIG_SETMASK, &oldset, NULL);
11921                        break;
11922                }
11923                /* Wait for SIGCHLD or any other signal */
11924                /* It is vitally important for sigsuspend that SIGCHLD has non-DFL handler! */
11925                /* Note: sigsuspend invokes signal handler */
11926                sigsuspend(&oldset);
11927                /* ^^^ add "sigdelset(&oldset, SIGCHLD)" before sigsuspend
11928                 * to make sure SIGCHLD is not masked off?
11929                 * It was reported that this:
11930                 *      fn() { : | return; }
11931                 *      shopt -s lastpipe
11932                 *      fn
11933                 *      exec hush SCRIPT
11934                 * under bash 4.4.23 runs SCRIPT with SIGCHLD masked,
11935                 * making "wait" commands in SCRIPT block forever.
11936                 */
11937 restore:
11938                sigprocmask(SIG_SETMASK, &oldset, NULL);
11939 check_sig:
11940                /* So, did we get a signal? */
11941                sig = check_and_run_traps();
11942                if (sig /*&& sig != SIGCHLD - always true */) {
11943                        /* Do this for any (non-ignored) signal, not only for ^C */
11944                        ret = 128 | sig;
11945                        break;
11946                }
11947                /* SIGCHLD, or no signal, or ignored one, such as SIGQUIT. Repeat */
11948        }
11949        return ret;
11950}
11951
11952static int FAST_FUNC builtin_wait(char **argv)
11953{
11954        int ret;
11955        int status;
11956
11957        argv = skip_dash_dash(argv);
11958# if ENABLE_HUSH_BASH_COMPAT
11959        if (argv[0] && strcmp(argv[0], "-n") == 0) {
11960                /* wait -n */
11961                /* (bash accepts "wait -n PID" too and ignores PID) */
11962                G.dead_job_exitcode = -1;
11963                return wait_for_child_or_signal(NULL, -1 /*no job, wait for one job*/);
11964        }
11965# endif
11966        if (argv[0] == NULL) {
11967                /* Don't care about wait results */
11968                /* Note 1: must wait until there are no more children */
11969                /* Note 2: must be interruptible */
11970                /* Examples:
11971                 * $ sleep 3 & sleep 6 & wait
11972                 * [1] 30934 sleep 3
11973                 * [2] 30935 sleep 6
11974                 * [1] Done                   sleep 3
11975                 * [2] Done                   sleep 6
11976                 * $ sleep 3 & sleep 6 & wait
11977                 * [1] 30936 sleep 3
11978                 * [2] 30937 sleep 6
11979                 * [1] Done                   sleep 3
11980                 * ^C <-- after ~4 sec from keyboard
11981                 * $
11982                 */
11983                return wait_for_child_or_signal(NULL, 0 /*no job and no pid to wait for*/);
11984        }
11985
11986        do {
11987                pid_t pid = bb_strtou(*argv, NULL, 10);
11988                if (errno || pid <= 0) {
11989# if ENABLE_HUSH_JOB
11990                        if (argv[0][0] == '%') {
11991                                struct pipe *wait_pipe;
11992                                ret = 127; /* bash compat for bad jobspecs */
11993                                wait_pipe = parse_jobspec(*argv);
11994                                if (wait_pipe) {
11995                                        ret = job_exited_or_stopped(wait_pipe);
11996                                        if (ret < 0) {
11997                                                ret = wait_for_child_or_signal(wait_pipe, 0);
11998                                        } else {
11999                                                /* waiting on "last dead job" removes it */
12000                                                clean_up_last_dead_job();
12001                                        }
12002                                }
12003                                /* else: parse_jobspec() already emitted error msg */
12004                                continue;
12005                        }
12006# endif
12007                        /* mimic bash message */
12008                        bb_error_msg("wait: '%s': not a pid or valid job spec", *argv);
12009                        ret = EXIT_FAILURE;
12010                        continue; /* bash checks all argv[] */
12011                }
12012
12013                /* Do we have such child? */
12014                ret = waitpid(pid, &status, WNOHANG);
12015                if (ret < 0) {
12016                        /* No */
12017                        ret = 127;
12018                        if (errno == ECHILD) {
12019                                if (pid == G.last_bg_pid) {
12020                                        /* "wait $!" but last bg task has already exited. Try:
12021                                         * (sleep 1; exit 3) & sleep 2; echo $?; wait $!; echo $?
12022                                         * In bash it prints exitcode 0, then 3.
12023                                         * In dash, it is 127.
12024                                         */
12025                                        ret = G.last_bg_pid_exitcode;
12026                                } else {
12027                                        /* Example: "wait 1". mimic bash message */
12028                                        bb_error_msg("wait: pid %u is not a child of this shell", (unsigned)pid);
12029                                }
12030                        } else {
12031                                /* ??? */
12032                                bb_perror_msg("wait %s", *argv);
12033                        }
12034                        continue; /* bash checks all argv[] */
12035                }
12036                if (ret == 0) {
12037                        /* Yes, and it still runs */
12038                        ret = wait_for_child_or_signal(NULL, pid);
12039                } else {
12040                        /* Yes, and it just exited */
12041                        process_wait_result(NULL, pid, status);
12042                        ret = WEXITSTATUS(status);
12043                        if (WIFSIGNALED(status))
12044                                ret = 128 | WTERMSIG(status);
12045                }
12046        } while (*++argv);
12047
12048        return ret;
12049}
12050#endif
12051
12052#if ENABLE_HUSH_LOOPS || ENABLE_HUSH_FUNCTIONS
12053static unsigned parse_numeric_argv1(char **argv, unsigned def, unsigned def_min)
12054{
12055        if (argv[1]) {
12056                def = bb_strtou(argv[1], NULL, 10);
12057                if (errno || def < def_min || argv[2]) {
12058                        bb_error_msg("%s: bad arguments", argv[0]);
12059                        def = UINT_MAX;
12060                }
12061        }
12062        return def;
12063}
12064#endif
12065
12066#if ENABLE_HUSH_LOOPS
12067static int FAST_FUNC builtin_break(char **argv)
12068{
12069        unsigned depth;
12070        if (G.depth_of_loop == 0) {
12071                bb_error_msg("%s: only meaningful in a loop", argv[0]);
12072                /* if we came from builtin_continue(), need to undo "= 1" */
12073                G.flag_break_continue = 0;
12074                return EXIT_SUCCESS; /* bash compat */
12075        }
12076        G.flag_break_continue++; /* BC_BREAK = 1, or BC_CONTINUE = 2 */
12077
12078        G.depth_break_continue = depth = parse_numeric_argv1(argv, 1, 1);
12079        if (depth == UINT_MAX)
12080                G.flag_break_continue = BC_BREAK;
12081        if (G.depth_of_loop < depth)
12082                G.depth_break_continue = G.depth_of_loop;
12083
12084        return EXIT_SUCCESS;
12085}
12086
12087static int FAST_FUNC builtin_continue(char **argv)
12088{
12089        G.flag_break_continue = 1; /* BC_CONTINUE = 2 = 1+1 */
12090        return builtin_break(argv);
12091}
12092#endif
12093
12094#if ENABLE_HUSH_FUNCTIONS
12095static int FAST_FUNC builtin_return(char **argv)
12096{
12097        int rc;
12098
12099        if (G_flag_return_in_progress != -1) {
12100                bb_error_msg("%s: not in a function or sourced script", argv[0]);
12101                return EXIT_FAILURE; /* bash compat */
12102        }
12103
12104        G_flag_return_in_progress = 1;
12105
12106        /* bash:
12107         * out of range: wraps around at 256, does not error out
12108         * non-numeric param:
12109         * f() { false; return qwe; }; f; echo $?
12110         * bash: return: qwe: numeric argument required  <== we do this
12111         * 255  <== we also do this
12112         */
12113        rc = parse_numeric_argv1(argv, G.last_exitcode, 0);
12114# if ENABLE_HUSH_TRAP
12115        if (argv[1]) { /* "return ARG" inside a running trap sets $? */
12116                debug_printf_exec("G.return_exitcode=%d\n", rc);
12117                G.return_exitcode = rc;
12118        }
12119# endif
12120        return rc;
12121}
12122#endif
12123
12124#if ENABLE_HUSH_TIMES
12125static int FAST_FUNC builtin_times(char **argv UNUSED_PARAM)
12126{
12127        static const uint8_t times_tbl[] ALIGN1 = {
12128                ' ',  offsetof(struct tms, tms_utime),
12129                '\n', offsetof(struct tms, tms_stime),
12130                ' ',  offsetof(struct tms, tms_cutime),
12131                '\n', offsetof(struct tms, tms_cstime),
12132                0
12133        };
12134        const uint8_t *p;
12135        unsigned clk_tck;
12136        struct tms buf;
12137
12138        clk_tck = bb_clk_tck();
12139
12140        times(&buf);
12141        p = times_tbl;
12142        do {
12143                unsigned sec, frac;
12144                unsigned long t;
12145                t = *(clock_t *)(((char *) &buf) + p[1]);
12146                sec = t / clk_tck;
12147                frac = t % clk_tck;
12148                printf("%um%u.%03us%c",
12149                        sec / 60, sec % 60,
12150                        (frac * 1000) / clk_tck,
12151                        p[0]);
12152                p += 2;
12153        } while (*p);
12154
12155        return EXIT_SUCCESS;
12156}
12157#endif
12158
12159#if ENABLE_HUSH_MEMLEAK
12160static int FAST_FUNC builtin_memleak(char **argv UNUSED_PARAM)
12161{
12162        void *p;
12163        unsigned long l;
12164
12165# ifdef M_TRIM_THRESHOLD
12166        /* Optional. Reduces probability of false positives */
12167        malloc_trim(0);
12168# endif
12169        /* Crude attempt to find where "free memory" starts,
12170         * sans fragmentation. */
12171        p = malloc(240);
12172        l = (unsigned long)p;
12173        free(p);
12174        p = malloc(3400);
12175        if (l < (unsigned long)p) l = (unsigned long)p;
12176        free(p);
12177
12178
12179# if 0  /* debug */
12180        {
12181                struct mallinfo mi = mallinfo();
12182                printf("top alloc:0x%lx malloced:%d+%d=%d\n", l,
12183                        mi.arena, mi.hblkhd, mi.arena + mi.hblkhd);
12184        }
12185# endif
12186
12187        if (!G.memleak_value)
12188                G.memleak_value = l;
12189
12190        l -= G.memleak_value;
12191        if ((long)l < 0)
12192                l = 0;
12193        l /= 1024;
12194        if (l > 127)
12195                l = 127;
12196
12197        /* Exitcode is "how many kilobytes we leaked since 1st call" */
12198        return l;
12199}
12200#endif
12201