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 *      =~: regex operator
  67 *      let EXPR [EXPR...]
  68 *          Each EXPR is an arithmetic expression (ARITHMETIC EVALUATION)
  69 *          If the last arg evaluates to 0, let returns 1; 0 otherwise.
  70 *          NB: let `echo 'a=a + 1'` - error (IOW: multi-word expansion is used)
  71 *      ((EXPR))
  72 *          The EXPR is evaluated according to ARITHMETIC EVALUATION.
  73 *          This is exactly equivalent to let "EXPR".
  74 *      $[EXPR]: synonym for $((EXPR))
  75 *      indirect expansion: ${!VAR}
  76 *      substring op on @: ${@:n:m}
  77 *
  78 * Won't do:
  79 *      Some builtins mandated by standards:
  80 *          newgrp [GRP]: not a builtin in bash but a suid binary
  81 *              which spawns a new shell with new group ID
  82 *
  83 * Status of [[ support:
  84 * [[ args ]] are CMD_SINGLEWORD_NOGLOB:
  85 *   v='a b'; [[ $v = 'a b' ]]; echo 0:$?
  86 *   [[ /bin/n* ]]; echo 0:$?
  87 * TODO:
  88 * &&/|| are AND/OR ops, -a/-o are not
  89 * quoting needs to be considered (-f is an operator, "-f" and ""-f are not; etc)
  90 * = is glob match operator, not equality operator: STR = GLOB
  91 * (in GLOB, quoting is significant on char-by-char basis: a*cd"*")
  92 * == same as =
  93 * add =~ regex match operator: STR =~ REGEX
  94 */
  95//config:config HUSH
  96//config:       bool "hush (68 kb)"
  97//config:       default y
  98//config:       help
  99//config:       hush is a small shell. It handles the normal flow control
 100//config:       constructs such as if/then/elif/else/fi, for/in/do/done, while loops,
 101//config:       case/esac. Redirections, here documents, $((arithmetic))
 102//config:       and functions are supported.
 103//config:
 104//config:       It will compile and work on no-mmu systems.
 105//config:
 106//config:       It does not handle select, aliases, tilde expansion,
 107//config:       &>file and >&file redirection of stdout+stderr.
 108//config:
 109//config:config HUSH_BASH_COMPAT
 110//config:       bool "bash-compatible extensions"
 111//config:       default y
 112//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 113//config:
 114//config:config HUSH_BRACE_EXPANSION
 115//config:       bool "Brace expansion"
 116//config:       default y
 117//config:       depends on HUSH_BASH_COMPAT
 118//config:       help
 119//config:       Enable {abc,def} extension.
 120//config:
 121//config:config HUSH_LINENO_VAR
 122//config:       bool "$LINENO variable"
 123//config:       default y
 124//config:       depends on HUSH_BASH_COMPAT
 125//config:
 126//config:config HUSH_BASH_SOURCE_CURDIR
 127//config:       bool "'source' and '.' builtins search current directory after $PATH"
 128//config:       default n   # do not encourage non-standard behavior
 129//config:       depends on HUSH_BASH_COMPAT
 130//config:       help
 131//config:       This is not compliant with standards. Avoid if possible.
 132//config:
 133//config:config HUSH_INTERACTIVE
 134//config:       bool "Interactive mode"
 135//config:       default y
 136//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 137//config:       help
 138//config:       Enable interactive mode (prompt and command editing).
 139//config:       Without this, hush simply reads and executes commands
 140//config:       from stdin just like a shell script from a file.
 141//config:       No prompt, no PS1/PS2 magic shell variables.
 142//config:
 143//config:config HUSH_SAVEHISTORY
 144//config:       bool "Save command history to .hush_history"
 145//config:       default y
 146//config:       depends on HUSH_INTERACTIVE && FEATURE_EDITING_SAVEHISTORY
 147//config:
 148//config:config HUSH_JOB
 149//config:       bool "Job control"
 150//config:       default y
 151//config:       depends on HUSH_INTERACTIVE
 152//config:       help
 153//config:       Enable job control: Ctrl-Z backgrounds, Ctrl-C interrupts current
 154//config:       command (not entire shell), fg/bg builtins work. Without this option,
 155//config:       "cmd &" still works by simply spawning a process and immediately
 156//config:       prompting for next command (or executing next command in a script),
 157//config:       but no separate process group is formed.
 158//config:
 159//config:config HUSH_TICK
 160//config:       bool "Support command substitution"
 161//config:       default y
 162//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 163//config:       help
 164//config:       Enable `command` and $(command).
 165//config:
 166//config:config HUSH_IF
 167//config:       bool "Support if/then/elif/else/fi"
 168//config:       default y
 169//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 170//config:
 171//config:config HUSH_LOOPS
 172//config:       bool "Support for, while and until loops"
 173//config:       default y
 174//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 175//config:
 176//config:config HUSH_CASE
 177//config:       bool "Support case ... esac statement"
 178//config:       default y
 179//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 180//config:       help
 181//config:       Enable case ... esac statement. +400 bytes.
 182//config:
 183//config:config HUSH_FUNCTIONS
 184//config:       bool "Support funcname() { commands; } syntax"
 185//config:       default y
 186//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 187//config:       help
 188//config:       Enable support for shell functions. +800 bytes.
 189//config:
 190//config:config HUSH_LOCAL
 191//config:       bool "local builtin"
 192//config:       default y
 193//config:       depends on HUSH_FUNCTIONS
 194//config:       help
 195//config:       Enable support for local variables in functions.
 196//config:
 197//config:config HUSH_RANDOM_SUPPORT
 198//config:       bool "Pseudorandom generator and $RANDOM variable"
 199//config:       default y
 200//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 201//config:       help
 202//config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
 203//config:       Each read of "$RANDOM" will generate a new pseudorandom value.
 204//config:
 205//config:config HUSH_MODE_X
 206//config:       bool "Support 'hush -x' option and 'set -x' command"
 207//config:       default y
 208//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 209//config:       help
 210//config:       This instructs hush to print commands before execution.
 211//config:       Adds ~300 bytes.
 212//config:
 213//config:config HUSH_ECHO
 214//config:       bool "echo builtin"
 215//config:       default y
 216//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 217//config:
 218//config:config HUSH_PRINTF
 219//config:       bool "printf builtin"
 220//config:       default y
 221//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 222//config:
 223//config:config HUSH_TEST
 224//config:       bool "test builtin"
 225//config:       default y
 226//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 227//config:
 228//config:config HUSH_HELP
 229//config:       bool "help builtin"
 230//config:       default y
 231//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 232//config:
 233//config:config HUSH_EXPORT
 234//config:       bool "export builtin"
 235//config:       default y
 236//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 237//config:
 238//config:config HUSH_EXPORT_N
 239//config:       bool "Support 'export -n' option"
 240//config:       default y
 241//config:       depends on HUSH_EXPORT
 242//config:       help
 243//config:       export -n unexports variables. It is a bash extension.
 244//config:
 245//config:config HUSH_READONLY
 246//config:       bool "readonly builtin"
 247//config:       default y
 248//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 249//config:       help
 250//config:       Enable support for read-only variables.
 251//config:
 252//config:config HUSH_KILL
 253//config:       bool "kill builtin (supports kill %jobspec)"
 254//config:       default y
 255//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 256//config:
 257//config:config HUSH_WAIT
 258//config:       bool "wait builtin"
 259//config:       default y
 260//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 261//config:
 262//config:config HUSH_COMMAND
 263//config:       bool "command builtin"
 264//config:       default y
 265//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 266//config:
 267//config:config HUSH_TRAP
 268//config:       bool "trap builtin"
 269//config:       default y
 270//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 271//config:
 272//config:config HUSH_TYPE
 273//config:       bool "type builtin"
 274//config:       default y
 275//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 276//config:
 277//config:config HUSH_TIMES
 278//config:       bool "times builtin"
 279//config:       default y
 280//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 281//config:
 282//config:config HUSH_READ
 283//config:       bool "read builtin"
 284//config:       default y
 285//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 286//config:
 287//config:config HUSH_SET
 288//config:       bool "set builtin"
 289//config:       default y
 290//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 291//config:
 292//config:config HUSH_UNSET
 293//config:       bool "unset builtin"
 294//config:       default y
 295//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 296//config:
 297//config:config HUSH_ULIMIT
 298//config:       bool "ulimit builtin"
 299//config:       default y
 300//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 301//config:
 302//config:config HUSH_UMASK
 303//config:       bool "umask builtin"
 304//config:       default y
 305//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 306//config:
 307//config:config HUSH_GETOPTS
 308//config:       bool "getopts builtin"
 309//config:       default y
 310//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 311//config:
 312//config:config HUSH_MEMLEAK
 313//config:       bool "memleak builtin (debugging)"
 314//config:       default n
 315//config:       depends on HUSH || SH_IS_HUSH || BASH_IS_HUSH
 316
 317//applet:IF_HUSH(APPLET(hush, BB_DIR_BIN, BB_SUID_DROP))
 318//                       APPLET_ODDNAME:name  main  location    suid_type     help
 319//applet:IF_SH_IS_HUSH(  APPLET_ODDNAME(sh,   hush, BB_DIR_BIN, BB_SUID_DROP, hush))
 320//applet:IF_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, BB_DIR_BIN, BB_SUID_DROP, hush))
 321
 322//kbuild:lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o
 323//kbuild:lib-$(CONFIG_SH_IS_HUSH) += hush.o match.o shell_common.o
 324//kbuild:lib-$(CONFIG_BASH_IS_HUSH) += hush.o match.o shell_common.o
 325//kbuild:lib-$(CONFIG_HUSH_RANDOM_SUPPORT) += random.o
 326
 327/* -i (interactive) is also accepted,
 328 * but does nothing, therefore not shown in help.
 329 * NOMMU-specific options are not meant to be used by users,
 330 * therefore we don't show them either.
 331 */
 332//usage:#define hush_trivial_usage
 333//usage:        "[-enxl] [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS] / -s [ARGS]]"
 334//usage:#define hush_full_usage "\n\n"
 335//usage:        "Unix shell interpreter"
 336
 337#if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \
 338        || defined(__APPLE__) \
 339    )
 340# include <malloc.h>   /* for malloc_trim */
 341#endif
 342#include <glob.h>
 343/* #include <dmalloc.h> */
 344#if ENABLE_HUSH_CASE
 345# include <fnmatch.h>
 346#endif
 347#include <sys/times.h>
 348#include <sys/utsname.h> /* for setting $HOSTNAME */
 349
 350#include "busybox.h"  /* for APPLET_IS_NOFORK/NOEXEC */
 351#include "unicode.h"
 352#include "shell_common.h"
 353#include "math.h"
 354#include "match.h"
 355#if ENABLE_HUSH_RANDOM_SUPPORT
 356# include "random.h"
 357#else
 358# define CLEAR_RANDOM_T(rnd) ((void)0)
 359#endif
 360#ifndef O_CLOEXEC
 361# define O_CLOEXEC 0
 362#endif
 363#ifndef F_DUPFD_CLOEXEC
 364# define F_DUPFD_CLOEXEC F_DUPFD
 365#endif
 366
 367#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS && !(ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH)
 368# include "embedded_scripts.h"
 369#else
 370# define NUM_SCRIPTS 0
 371#endif
 372
 373/* So far, all bash compat is controlled by one config option */
 374/* Separate defines document which part of code implements what */
 375#define BASH_PATTERN_SUBST ENABLE_HUSH_BASH_COMPAT
 376#define BASH_SUBSTR        ENABLE_HUSH_BASH_COMPAT
 377#define BASH_SOURCE        ENABLE_HUSH_BASH_COMPAT
 378#define BASH_HOSTNAME_VAR  ENABLE_HUSH_BASH_COMPAT
 379#define BASH_EPOCH_VARS    ENABLE_HUSH_BASH_COMPAT
 380#define BASH_TEST2         (ENABLE_HUSH_BASH_COMPAT && ENABLE_HUSH_TEST)
 381#define BASH_READ_D        ENABLE_HUSH_BASH_COMPAT
 382
 383
 384/* Build knobs */
 385#define LEAK_HUNTING 0
 386#define BUILD_AS_NOMMU 0
 387/* Enable/disable sanity checks. Ok to enable in production,
 388 * only adds a bit of bloat. Set to >1 to get non-production level verbosity.
 389 * Keeping 1 for now even in released versions.
 390 */
 391#define HUSH_DEBUG 1
 392/* Slightly bigger (+200 bytes), but faster hush.
 393 * So far it only enables a trick with counting SIGCHLDs and forks,
 394 * which allows us to do fewer waitpid's.
 395 * (we can detect a case where neither forks were done nor SIGCHLDs happened
 396 * and therefore waitpid will return the same result as last time)
 397 */
 398#define ENABLE_HUSH_FAST 0
 399/* TODO: implement simplified code for users which do not need ${var%...} ops
 400 * So far ${var%...} ops are always enabled:
 401 */
 402#define ENABLE_HUSH_DOLLAR_OPS 1
 403
 404
 405#if BUILD_AS_NOMMU
 406# undef BB_MMU
 407# undef USE_FOR_NOMMU
 408# undef USE_FOR_MMU
 409# define BB_MMU 0
 410# define USE_FOR_NOMMU(...) __VA_ARGS__
 411# define USE_FOR_MMU(...)
 412#endif
 413
 414#include "NUM_APPLETS.h"
 415#if NUM_APPLETS == 1
 416/* STANDALONE does not make sense, and won't compile */
 417# undef CONFIG_FEATURE_SH_STANDALONE
 418# undef ENABLE_FEATURE_SH_STANDALONE
 419# undef IF_FEATURE_SH_STANDALONE
 420# undef IF_NOT_FEATURE_SH_STANDALONE
 421# define ENABLE_FEATURE_SH_STANDALONE 0
 422# define IF_FEATURE_SH_STANDALONE(...)
 423# define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
 424#endif
 425
 426#if !ENABLE_HUSH_INTERACTIVE
 427# undef ENABLE_FEATURE_EDITING
 428# define ENABLE_FEATURE_EDITING 0
 429# undef ENABLE_FEATURE_EDITING_FANCY_PROMPT
 430# define ENABLE_FEATURE_EDITING_FANCY_PROMPT 0
 431# undef ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
 432# define ENABLE_FEATURE_EDITING_SAVE_ON_EXIT 0
 433#endif
 434
 435/* Do we support ANY keywords? */
 436#if ENABLE_HUSH_IF || ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
 437# define HAS_KEYWORDS 1
 438# define IF_HAS_KEYWORDS(...) __VA_ARGS__
 439# define IF_HAS_NO_KEYWORDS(...)
 440#else
 441# define HAS_KEYWORDS 0
 442# define IF_HAS_KEYWORDS(...)
 443# define IF_HAS_NO_KEYWORDS(...) __VA_ARGS__
 444#endif
 445
 446/* If you comment out one of these below, it will be #defined later
 447 * to perform debug printfs to stderr: */
 448#define debug_printf(...)         do {} while (0)
 449/* Finer-grained debug switches */
 450#define debug_printf_parse(...)   do {} while (0)
 451#define debug_printf_heredoc(...) do {} while (0)
 452#define debug_print_tree(a, b)    do {} while (0)
 453#define debug_printf_exec(...)    do {} while (0)
 454#define debug_printf_env(...)     do {} while (0)
 455#define debug_printf_jobs(...)    do {} while (0)
 456#define debug_printf_expand(...)  do {} while (0)
 457#define debug_printf_varexp(...)  do {} while (0)
 458#define debug_printf_glob(...)    do {} while (0)
 459#define debug_printf_redir(...)   do {} while (0)
 460#define debug_printf_list(...)    do {} while (0)
 461#define debug_printf_subst(...)   do {} while (0)
 462#define debug_printf_prompt(...)  do {} while (0)
 463#define debug_printf_clean(...)   do {} while (0)
 464
 465#define ERR_PTR ((void*)(long)1)
 466
 467#define JOB_STATUS_FORMAT    "[%u] %-22s %.40s\n"
 468
 469#define _SPECIAL_VARS_STR     "_*@$!?#-"
 470#define SPECIAL_VARS_STR     ("_*@$!?#-" + 1)
 471#define NUMERIC_SPECVARS_STR ("_*@$!?#-" + 3)
 472#if BASH_PATTERN_SUBST
 473/* Support / and // replace ops */
 474/* Note that // is stored as \ in "encoded" string representation */
 475# define VAR_ENCODED_SUBST_OPS      "\\/%#:-=+?"
 476# define VAR_SUBST_OPS             ("\\/%#:-=+?" + 1)
 477# define MINUS_PLUS_EQUAL_QUESTION ("\\/%#:-=+?" + 5)
 478#else
 479# define VAR_ENCODED_SUBST_OPS      "%#:-=+?"
 480# define VAR_SUBST_OPS              "%#:-=+?"
 481# define MINUS_PLUS_EQUAL_QUESTION ("%#:-=+?" + 3)
 482#endif
 483
 484#define SPECIAL_VAR_SYMBOL_STR "\3"
 485#define SPECIAL_VAR_SYMBOL       3
 486/* The "variable" with name "\1" emits string "\3". Testcase: "echo ^C" */
 487#define SPECIAL_VAR_QUOTED_SVS   1
 488
 489struct variable;
 490
 491static const char hush_version_str[] ALIGN1 = "HUSH_VERSION="BB_VER;
 492
 493/* This supports saving pointers malloced in vfork child,
 494 * to be freed in the parent.
 495 */
 496#if !BB_MMU
 497typedef struct nommu_save_t {
 498        struct variable *old_vars;
 499        char **argv;
 500        char **argv_from_re_execing;
 501} nommu_save_t;
 502#endif
 503
 504enum {
 505        RES_NONE  = 0,
 506#if ENABLE_HUSH_IF
 507        RES_IF    ,
 508        RES_THEN  ,
 509        RES_ELIF  ,
 510        RES_ELSE  ,
 511        RES_FI    ,
 512#endif
 513#if ENABLE_HUSH_LOOPS
 514        RES_FOR   ,
 515        RES_WHILE ,
 516        RES_UNTIL ,
 517        RES_DO    ,
 518        RES_DONE  ,
 519#endif
 520#if ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
 521        RES_IN    ,
 522#endif
 523#if ENABLE_HUSH_CASE
 524        RES_CASE  ,
 525        /* three pseudo-keywords support contrived "case" syntax: */
 526        RES_CASE_IN,   /* "case ... IN", turns into RES_MATCH when IN is observed */
 527        RES_MATCH ,    /* "word)" */
 528        RES_CASE_BODY, /* "this command is inside CASE" */
 529        RES_ESAC  ,
 530#endif
 531        RES_XXXX  ,
 532        RES_SNTX
 533};
 534
 535typedef struct o_string {
 536        char *data;
 537        int length; /* position where data is appended */
 538        int maxlen;
 539        int o_expflags;
 540        /* At least some part of the string was inside '' or "",
 541         * possibly empty one: word"", wo''rd etc. */
 542        smallint has_quoted_part;
 543        smallint has_empty_slot;
 544        smallint ended_in_ifs;
 545} o_string;
 546enum {
 547        EXP_FLAG_SINGLEWORD     = 0x80, /* must be 0x80 */
 548        EXP_FLAG_GLOB           = 0x2,
 549        /* Protect newly added chars against globbing
 550         * by prepending \ to *, ?, [, \ */
 551        EXP_FLAG_ESC_GLOB_CHARS = 0x1,
 552};
 553/* Used for initialization: o_string foo = NULL_O_STRING; */
 554#define NULL_O_STRING { NULL }
 555
 556#ifndef debug_printf_parse
 557static const char *const assignment_flag[] = {
 558        "MAYBE_ASSIGNMENT",
 559        "DEFINITELY_ASSIGNMENT",
 560        "NOT_ASSIGNMENT",
 561        "WORD_IS_KEYWORD",
 562};
 563#endif
 564
 565/* We almost can use standard FILE api, but we need an ability to move
 566 * its fd when redirects coincide with it. No api exists for that
 567 * (RFE for it at https://sourceware.org/bugzilla/show_bug.cgi?id=21902).
 568 * HFILE is our internal alternative. Only supports reading.
 569 * Since we now can, we incorporate linked list of all opened HFILEs
 570 * into the struct (used to be a separate mini-list).
 571 */
 572typedef struct HFILE {
 573        char *cur;
 574        char *end;
 575        struct HFILE *next_hfile;
 576        int is_stdin;
 577        int fd;
 578        char buf[1024];
 579} HFILE;
 580
 581typedef struct in_str {
 582        const char *p;
 583        int peek_buf[2];
 584        int last_char;
 585        HFILE *file;
 586} in_str;
 587
 588/* The descrip member of this structure is only used to make
 589 * debugging output pretty */
 590static const struct {
 591        int mode;
 592        signed char default_fd;
 593        char descrip[3];
 594} redir_table[] = {
 595        { O_RDONLY,                  0, "<"  },
 596        { O_CREAT|O_TRUNC|O_WRONLY,  1, ">"  },
 597        { O_CREAT|O_APPEND|O_WRONLY, 1, ">>" },
 598        { O_CREAT|O_RDWR,            1, "<>" },
 599        { O_RDONLY,                  0, "<<" },
 600/* Should not be needed. Bogus default_fd helps in debugging */
 601/*      { O_RDONLY,                 77, "<<" }, */
 602};
 603
 604struct redir_struct {
 605        struct redir_struct *next;
 606        char *rd_filename;          /* filename */
 607        int rd_fd;                  /* fd to redirect */
 608        /* fd to redirect to, or -3 if rd_fd is to be closed (n>&-) */
 609        int rd_dup;
 610        smallint rd_type;           /* (enum redir_type) */
 611        /* note: for heredocs, rd_filename contains heredoc delimiter,
 612         * and subsequently heredoc itself; and rd_dup is a bitmask:
 613         * bit 0: do we need to trim leading tabs?
 614         * bit 1: is heredoc quoted (<<'delim' syntax) ?
 615         */
 616};
 617typedef enum redir_type {
 618        REDIRECT_INPUT     = 0,
 619        REDIRECT_OVERWRITE = 1,
 620        REDIRECT_APPEND    = 2,
 621        REDIRECT_IO        = 3,
 622        REDIRECT_HEREDOC   = 4,
 623        REDIRECT_HEREDOC2  = 5, /* REDIRECT_HEREDOC after heredoc is loaded */
 624
 625        REDIRFD_CLOSE      = -3,
 626        REDIRFD_SYNTAX_ERR = -2,
 627        REDIRFD_TO_FILE    = -1,
 628        /* otherwise, rd_fd is redirected to rd_dup */
 629
 630        HEREDOC_SKIPTABS = 1,
 631        HEREDOC_QUOTED   = 2,
 632} redir_type;
 633
 634
 635struct command {
 636        pid_t pid;                  /* 0 if exited */
 637        unsigned assignment_cnt;    /* how many argv[i] are assignments? */
 638#if ENABLE_HUSH_LINENO_VAR
 639        unsigned lineno;
 640#endif
 641        smallint cmd_type;          /* CMD_xxx */
 642#define CMD_NORMAL   0
 643#define CMD_SUBSHELL 1
 644#if BASH_TEST2 || ENABLE_HUSH_LOCAL || ENABLE_HUSH_EXPORT || ENABLE_HUSH_READONLY
 645/* used for "[[ EXPR ]]", and to prevent word splitting and globbing in
 646 * "export v=t*"
 647 */
 648# define CMD_SINGLEWORD_NOGLOB 2
 649#endif
 650#if ENABLE_HUSH_FUNCTIONS
 651# define CMD_FUNCDEF 3
 652#endif
 653
 654        smalluint cmd_exitcode;
 655        /* if non-NULL, this "command" is { list }, ( list ), or a compound statement */
 656        struct pipe *group;
 657#if !BB_MMU
 658        char *group_as_string;
 659#endif
 660#if ENABLE_HUSH_FUNCTIONS
 661        struct function *child_func;
 662/* This field is used to prevent a bug here:
 663 * while...do f1() {a;}; f1; f1() {b;}; f1; done
 664 * When we execute "f1() {a;}" cmd, we create new function and clear
 665 * cmd->group, cmd->group_as_string, cmd->argv[0].
 666 * When we execute "f1() {b;}", we notice that f1 exists,
 667 * and that its "parent cmd" struct is still "alive",
 668 * we put those fields back into cmd->xxx
 669 * (struct function has ->parent_cmd ptr to facilitate that).
 670 * When we loop back, we can execute "f1() {a;}" again and set f1 correctly.
 671 * Without this trick, loop would execute a;b;b;b;...
 672 * instead of correct sequence a;b;a;b;...
 673 * When command is freed, it severs the link
 674 * (sets ->child_func->parent_cmd to NULL).
 675 */
 676#endif
 677        char **argv;                /* command name and arguments */
 678/* argv vector may contain variable references (^Cvar^C, ^C0^C etc)
 679 * and on execution these are substituted with their values.
 680 * Substitution can make _several_ words out of one argv[n]!
 681 * Example: argv[0]=='.^C*^C.' here: echo .$*.
 682 * References of the form ^C`cmd arg^C are `cmd arg` substitutions.
 683 */
 684        struct redir_struct *redirects; /* I/O redirections */
 685};
 686/* Is there anything in this command at all? */
 687#define IS_NULL_CMD(cmd) \
 688        (!(cmd)->group && !(cmd)->argv && !(cmd)->redirects)
 689
 690struct pipe {
 691        struct pipe *next;
 692        int num_cmds;               /* total number of commands in pipe */
 693        int alive_cmds;             /* number of commands running (not exited) */
 694        int stopped_cmds;           /* number of commands alive, but stopped */
 695#if ENABLE_HUSH_JOB
 696        unsigned jobid;             /* job number */
 697        pid_t pgrp;                 /* process group ID for the job */
 698        char *cmdtext;              /* name of job */
 699#endif
 700        struct command *cmds;       /* array of commands in pipe */
 701        smallint followup;          /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */
 702        IF_HAS_KEYWORDS(smallint pi_inverted;) /* "! cmd | cmd" */
 703        IF_HAS_KEYWORDS(smallint res_word;) /* needed for if, for, while, until... */
 704};
 705typedef enum pipe_style {
 706        PIPE_SEQ = 0,
 707        PIPE_AND = 1,
 708        PIPE_OR  = 2,
 709        PIPE_BG  = 3,
 710} pipe_style;
 711/* Is there anything in this pipe at all? */
 712#define IS_NULL_PIPE(pi) \
 713        ((pi)->num_cmds == 0 IF_HAS_KEYWORDS( && (pi)->res_word == RES_NONE))
 714
 715/* This holds pointers to the various results of parsing */
 716struct parse_context {
 717        /* linked list of pipes */
 718        struct pipe *list_head;
 719        /* last pipe (being constructed right now) */
 720        struct pipe *pipe;
 721        /* last command in pipe (being constructed right now) */
 722        struct command *command;
 723        /* last redirect in command->redirects list */
 724        struct redir_struct *pending_redirect;
 725        o_string word;
 726#if !BB_MMU
 727        o_string as_string;
 728#endif
 729        smallint is_assignment; /* 0:maybe, 1:yes, 2:no, 3:keyword */
 730#if HAS_KEYWORDS
 731        smallint ctx_res_w;
 732        smallint ctx_inverted; /* "! cmd | cmd" */
 733#if ENABLE_HUSH_CASE
 734        smallint ctx_dsemicolon; /* ";;" seen */
 735#endif
 736        /* bitmask of FLAG_xxx, for figuring out valid reserved words */
 737        int old_flag;
 738        /* group we are enclosed in:
 739         * example: "if pipe1; pipe2; then pipe3; fi"
 740         * when we see "if" or "then", we malloc and copy current context,
 741         * and make ->stack point to it. then we parse pipeN.
 742         * when closing "then" / fi" / whatever is found,
 743         * we move list_head into ->stack->command->group,
 744         * copy ->stack into current context, and delete ->stack.
 745         * (parsing of { list } and ( list ) doesn't use this method)
 746         */
 747        struct parse_context *stack;
 748#endif
 749};
 750enum {
 751        MAYBE_ASSIGNMENT      = 0,
 752        DEFINITELY_ASSIGNMENT = 1,
 753        NOT_ASSIGNMENT        = 2,
 754        /* Not an assignment, but next word may be: "if v=xyz cmd;" */
 755        WORD_IS_KEYWORD       = 3,
 756};
 757
 758/* On program start, environ points to initial environment.
 759 * putenv adds new pointers into it, unsetenv removes them.
 760 * Neither of these (de)allocates the strings.
 761 * setenv allocates new strings in malloc space and does putenv,
 762 * and thus setenv is unusable (leaky) for shell's purposes */
 763#define setenv(...) setenv_is_leaky_dont_use()
 764struct variable {
 765        struct variable *next;
 766        char *varstr;        /* points to "name=" portion */
 767        int max_len;         /* if > 0, name is part of initial env; else name is malloced */
 768        uint16_t var_nest_level;
 769        smallint flg_export; /* putenv should be done on this var */
 770        smallint flg_read_only;
 771};
 772
 773enum {
 774        BC_BREAK = 1,
 775        BC_CONTINUE = 2,
 776};
 777
 778#if ENABLE_HUSH_FUNCTIONS
 779struct function {
 780        struct function *next;
 781        char *name;
 782        struct command *parent_cmd;
 783        struct pipe *body;
 784# if !BB_MMU
 785        char *body_as_string;
 786# endif
 787};
 788#endif
 789
 790
 791/* set -/+o OPT support. (TODO: make it optional)
 792 * bash supports the following opts:
 793 * allexport       off
 794 * braceexpand     on
 795 * emacs           on
 796 * errexit         off
 797 * errtrace        off
 798 * functrace       off
 799 * hashall         on
 800 * histexpand      off
 801 * history         on
 802 * ignoreeof       off
 803 * interactive-comments    on
 804 * keyword         off
 805 * monitor         on
 806 * noclobber       off
 807 * noexec          off
 808 * noglob          off
 809 * nolog           off
 810 * notify          off
 811 * nounset         off
 812 * onecmd          off
 813 * physical        off
 814 * pipefail        off
 815 * posix           off
 816 * privileged      off
 817 * verbose         off
 818 * vi              off
 819 * xtrace          off
 820 */
 821static const char o_opt_strings[] ALIGN1 =
 822        "pipefail\0"
 823        "noexec\0"
 824        "errexit\0"
 825#if ENABLE_HUSH_MODE_X
 826        "xtrace\0"
 827#endif
 828        ;
 829enum {
 830        OPT_O_PIPEFAIL,
 831        OPT_O_NOEXEC,
 832        OPT_O_ERREXIT,
 833#if ENABLE_HUSH_MODE_X
 834        OPT_O_XTRACE,
 835#endif
 836        NUM_OPT_O
 837};
 838
 839/* "Globals" within this file */
 840/* Sorted roughly by size (smaller offsets == smaller code) */
 841struct globals {
 842        /* interactive_fd != 0 means we are an interactive shell.
 843         * If we are, then saved_tty_pgrp can also be != 0, meaning
 844         * that controlling tty is available. With saved_tty_pgrp == 0,
 845         * job control still works, but terminal signals
 846         * (^C, ^Z, ^Y, ^\) won't work at all, and background
 847         * process groups can only be created with "cmd &".
 848         * With saved_tty_pgrp != 0, hush will use tcsetpgrp()
 849         * to give tty to the foreground process group,
 850         * and will take it back when the group is stopped (^Z)
 851         * or killed (^C).
 852         */
 853#if ENABLE_HUSH_INTERACTIVE
 854        /* 'interactive_fd' is a fd# open to ctty, if we have one
 855         * _AND_ if we decided to act interactively */
 856        int interactive_fd;
 857        IF_NOT_FEATURE_EDITING_FANCY_PROMPT(char *PS1;)
 858# define G_interactive_fd (G.interactive_fd)
 859#else
 860# define G_interactive_fd 0
 861#endif
 862#if ENABLE_FEATURE_EDITING
 863        line_input_t *line_input_state;
 864#endif
 865        pid_t root_pid;
 866        pid_t root_ppid;
 867        pid_t last_bg_pid;
 868#if ENABLE_HUSH_RANDOM_SUPPORT
 869        random_t random_gen;
 870#endif
 871#if ENABLE_HUSH_JOB
 872        int run_list_level;
 873        unsigned last_jobid;
 874        pid_t saved_tty_pgrp;
 875        struct pipe *job_list;
 876# define G_saved_tty_pgrp (G.saved_tty_pgrp)
 877#else
 878# define G_saved_tty_pgrp 0
 879#endif
 880        /* How deeply are we in context where "set -e" is ignored */
 881        int errexit_depth;
 882        /* "set -e" rules (do we follow them correctly?):
 883         * Exit if pipe, list, or compound command exits with a non-zero status.
 884         * Shell does not exit if failed command is part of condition in
 885         * if/while, part of && or || list except the last command, any command
 886         * in a pipe but the last, or if the command's return value is being
 887         * inverted with !. If a compound command other than a subshell returns a
 888         * non-zero status because a command failed while -e was being ignored, the
 889         * shell does not exit. A trap on ERR, if set, is executed before the shell
 890         * exits [ERR is a bashism].
 891         *
 892         * If a compound command or function executes in a context where -e is
 893         * ignored, none of the commands executed within are affected by the -e
 894         * setting. If a compound command or function sets -e while executing in a
 895         * context where -e is ignored, that setting does not have any effect until
 896         * the compound command or the command containing the function call completes.
 897         */
 898
 899        char o_opt[NUM_OPT_O];
 900#if ENABLE_HUSH_MODE_X
 901# define G_x_mode (G.o_opt[OPT_O_XTRACE])
 902#else
 903# define G_x_mode 0
 904#endif
 905        char opt_s;
 906        char opt_c;
 907#if ENABLE_HUSH_INTERACTIVE
 908        smallint promptmode; /* 0: PS1, 1: PS2 */
 909#endif
 910        smallint flag_SIGINT;
 911#if ENABLE_HUSH_LOOPS
 912        smallint flag_break_continue;
 913#endif
 914#if ENABLE_HUSH_FUNCTIONS
 915        /* 0: outside of a function (or sourced file)
 916         * -1: inside of a function, ok to use return builtin
 917         * 1: return is invoked, skip all till end of func
 918         */
 919        smallint flag_return_in_progress;
 920# define G_flag_return_in_progress (G.flag_return_in_progress)
 921#else
 922# define G_flag_return_in_progress 0
 923#endif
 924        smallint exiting; /* used to prevent EXIT trap recursion */
 925        /* These support $? */
 926        smalluint last_exitcode;
 927        smalluint expand_exitcode;
 928        smalluint last_bg_pid_exitcode;
 929#if ENABLE_HUSH_SET
 930        /* are global_argv and global_argv[1..n] malloced? (note: not [0]) */
 931        smalluint global_args_malloced;
 932# define G_global_args_malloced (G.global_args_malloced)
 933#else
 934# define G_global_args_malloced 0
 935#endif
 936#if ENABLE_HUSH_BASH_COMPAT
 937        int dead_job_exitcode; /* for "wait -n" */
 938#endif
 939        /* how many non-NULL argv's we have. NB: $# + 1 */
 940        int global_argc;
 941        char **global_argv;
 942#if !BB_MMU
 943        char *argv0_for_re_execing;
 944#endif
 945#if ENABLE_HUSH_LOOPS
 946        unsigned depth_break_continue;
 947        unsigned depth_of_loop;
 948#endif
 949#if ENABLE_HUSH_GETOPTS
 950        unsigned getopt_count;
 951#endif
 952        const char *ifs;
 953        char *ifs_whitespace; /* = G.ifs or malloced */
 954        const char *cwd;
 955        struct variable *top_var;
 956        char **expanded_assignments;
 957        struct variable **shadowed_vars_pp;
 958        unsigned var_nest_level;
 959#if ENABLE_HUSH_FUNCTIONS
 960# if ENABLE_HUSH_LOCAL
 961        unsigned func_nest_level; /* solely to prevent "local v" in non-functions */
 962# endif
 963        struct function *top_func;
 964#endif
 965        /* Signal and trap handling */
 966#if ENABLE_HUSH_FAST
 967        unsigned count_SIGCHLD;
 968        unsigned handled_SIGCHLD;
 969        smallint we_have_children;
 970#endif
 971#if ENABLE_HUSH_LINENO_VAR
 972        unsigned parse_lineno;
 973        unsigned execute_lineno;
 974#endif
 975        HFILE *HFILE_list;
 976        /* Which signals have non-DFL handler (even with no traps set)?
 977         * Set at the start to:
 978         * (SIGQUIT + maybe SPECIAL_INTERACTIVE_SIGS + maybe SPECIAL_JOBSTOP_SIGS)
 979         * SPECIAL_INTERACTIVE_SIGS are cleared after fork.
 980         * The rest is cleared right before execv syscalls.
 981         * Other than these two times, never modified.
 982         */
 983        unsigned special_sig_mask;
 984#if ENABLE_HUSH_JOB
 985        unsigned fatal_sig_mask;
 986# define G_fatal_sig_mask (G.fatal_sig_mask)
 987#else
 988# define G_fatal_sig_mask 0
 989#endif
 990#if ENABLE_HUSH_TRAP
 991        char **traps; /* char *traps[NSIG] */
 992# define G_traps G.traps
 993#else
 994# define G_traps ((char**)NULL)
 995#endif
 996        sigset_t pending_set;
 997#if ENABLE_HUSH_MEMLEAK
 998        unsigned long memleak_value;
 999#endif
1000#if ENABLE_HUSH_MODE_X
1001        unsigned x_mode_depth;
1002        /* "set -x" output should not be redirectable with subsequent 2>FILE.
1003         * We dup fd#2 to x_mode_fd when "set -x" is executed, and use it
1004         * for all subsequent output.
1005         */
1006        int x_mode_fd;
1007        o_string x_mode_buf;
1008#endif
1009#if HUSH_DEBUG >= 2
1010        int debug_indent;
1011#endif
1012        struct sigaction sa;
1013        char optstring_buf[sizeof("eixcs")];
1014#if BASH_EPOCH_VARS
1015        char epoch_buf[sizeof("%lu.nnnnnn") + sizeof(long)*3];
1016#endif
1017#if ENABLE_FEATURE_EDITING
1018        char user_input_buf[CONFIG_FEATURE_EDITING_MAX_LEN];
1019#endif
1020};
1021#define G (*ptr_to_globals)
1022/* Not #defining name to G.name - this quickly gets unwieldy
1023 * (too many defines). Also, I actually prefer to see when a variable
1024 * is global, thus "G." prefix is a useful hint */
1025#define INIT_G() do { \
1026        SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
1027        /* memset(&G.sa, 0, sizeof(G.sa)); */  \
1028        sigfillset(&G.sa.sa_mask); \
1029        G.sa.sa_flags = SA_RESTART; \
1030} while (0)
1031
1032
1033/* Function prototypes for builtins */
1034static int builtin_cd(char **argv) FAST_FUNC;
1035#if ENABLE_HUSH_ECHO
1036static int builtin_echo(char **argv) FAST_FUNC;
1037#endif
1038static int builtin_eval(char **argv) FAST_FUNC;
1039static int builtin_exec(char **argv) FAST_FUNC;
1040static int builtin_exit(char **argv) FAST_FUNC;
1041#if ENABLE_HUSH_EXPORT
1042static int builtin_export(char **argv) FAST_FUNC;
1043#endif
1044#if ENABLE_HUSH_READONLY
1045static int builtin_readonly(char **argv) FAST_FUNC;
1046#endif
1047#if ENABLE_HUSH_JOB
1048static int builtin_fg_bg(char **argv) FAST_FUNC;
1049static int builtin_jobs(char **argv) FAST_FUNC;
1050#endif
1051#if ENABLE_HUSH_GETOPTS
1052static int builtin_getopts(char **argv) FAST_FUNC;
1053#endif
1054#if ENABLE_HUSH_HELP
1055static int builtin_help(char **argv) FAST_FUNC;
1056#endif
1057#if MAX_HISTORY && ENABLE_FEATURE_EDITING
1058static int builtin_history(char **argv) FAST_FUNC;
1059#endif
1060#if ENABLE_HUSH_LOCAL
1061static int builtin_local(char **argv) FAST_FUNC;
1062#endif
1063#if ENABLE_HUSH_MEMLEAK
1064static int builtin_memleak(char **argv) FAST_FUNC;
1065#endif
1066#if ENABLE_HUSH_PRINTF
1067static int builtin_printf(char **argv) FAST_FUNC;
1068#endif
1069static int builtin_pwd(char **argv) FAST_FUNC;
1070#if ENABLE_HUSH_READ
1071static int builtin_read(char **argv) FAST_FUNC;
1072#endif
1073#if ENABLE_HUSH_SET
1074static int builtin_set(char **argv) FAST_FUNC;
1075#endif
1076static int builtin_shift(char **argv) FAST_FUNC;
1077static int builtin_source(char **argv) FAST_FUNC;
1078#if ENABLE_HUSH_TEST || BASH_TEST2
1079static int builtin_test(char **argv) FAST_FUNC;
1080#endif
1081#if ENABLE_HUSH_TRAP
1082static int builtin_trap(char **argv) FAST_FUNC;
1083#endif
1084#if ENABLE_HUSH_TYPE
1085static int builtin_type(char **argv) FAST_FUNC;
1086#endif
1087#if ENABLE_HUSH_TIMES
1088static int builtin_times(char **argv) FAST_FUNC;
1089#endif
1090static int builtin_true(char **argv) FAST_FUNC;
1091#if ENABLE_HUSH_UMASK
1092static int builtin_umask(char **argv) FAST_FUNC;
1093#endif
1094#if ENABLE_HUSH_UNSET
1095static int builtin_unset(char **argv) FAST_FUNC;
1096#endif
1097#if ENABLE_HUSH_KILL
1098static int builtin_kill(char **argv) FAST_FUNC;
1099#endif
1100#if ENABLE_HUSH_WAIT
1101static int builtin_wait(char **argv) FAST_FUNC;
1102#endif
1103#if ENABLE_HUSH_LOOPS
1104static int builtin_break(char **argv) FAST_FUNC;
1105static int builtin_continue(char **argv) FAST_FUNC;
1106#endif
1107#if ENABLE_HUSH_FUNCTIONS
1108static int builtin_return(char **argv) FAST_FUNC;
1109#endif
1110
1111/* Table of built-in functions.  They can be forked or not, depending on
1112 * context: within pipes, they fork.  As simple commands, they do not.
1113 * When used in non-forking context, they can change global variables
1114 * in the parent shell process.  If forked, of course they cannot.
1115 * For example, 'unset foo | whatever' will parse and run, but foo will
1116 * still be set at the end. */
1117struct built_in_command {
1118        const char *b_cmd;
1119        int (*b_function)(char **argv) FAST_FUNC;
1120#if ENABLE_HUSH_HELP
1121        const char *b_descr;
1122# define BLTIN(cmd, func, help) { cmd, func, help }
1123#else
1124# define BLTIN(cmd, func, help) { cmd, func }
1125#endif
1126};
1127
1128static const struct built_in_command bltins1[] = {
1129        BLTIN("."        , builtin_source  , "Run commands in file"),
1130        BLTIN(":"        , builtin_true    , NULL),
1131#if ENABLE_HUSH_JOB
1132        BLTIN("bg"       , builtin_fg_bg   , "Resume job in background"),
1133#endif
1134#if ENABLE_HUSH_LOOPS
1135        BLTIN("break"    , builtin_break   , "Exit loop"),
1136#endif
1137        BLTIN("cd"       , builtin_cd      , "Change directory"),
1138#if ENABLE_HUSH_LOOPS
1139        BLTIN("continue" , builtin_continue, "Start new loop iteration"),
1140#endif
1141        BLTIN("eval"     , builtin_eval    , "Construct and run shell command"),
1142        BLTIN("exec"     , builtin_exec    , "Execute command, don't return to shell"),
1143        BLTIN("exit"     , builtin_exit    , NULL),
1144#if ENABLE_HUSH_EXPORT
1145        BLTIN("export"   , builtin_export  , "Set environment variables"),
1146#endif
1147#if ENABLE_HUSH_JOB
1148        BLTIN("fg"       , builtin_fg_bg   , "Bring job to foreground"),
1149#endif
1150#if ENABLE_HUSH_GETOPTS
1151        BLTIN("getopts"  , builtin_getopts , NULL),
1152#endif
1153#if ENABLE_HUSH_HELP
1154        BLTIN("help"     , builtin_help    , NULL),
1155#endif
1156#if MAX_HISTORY && ENABLE_FEATURE_EDITING
1157        BLTIN("history"  , builtin_history , "Show history"),
1158#endif
1159#if ENABLE_HUSH_JOB
1160        BLTIN("jobs"     , builtin_jobs    , "List jobs"),
1161#endif
1162#if ENABLE_HUSH_KILL
1163        BLTIN("kill"     , builtin_kill    , "Send signals to processes"),
1164#endif
1165#if ENABLE_HUSH_LOCAL
1166        BLTIN("local"    , builtin_local   , "Set local variables"),
1167#endif
1168#if ENABLE_HUSH_MEMLEAK
1169        BLTIN("memleak"  , builtin_memleak , NULL),
1170#endif
1171#if ENABLE_HUSH_READ
1172        BLTIN("read"     , builtin_read    , "Input into variable"),
1173#endif
1174#if ENABLE_HUSH_READONLY
1175        BLTIN("readonly" , builtin_readonly, "Make variables read-only"),
1176#endif
1177#if ENABLE_HUSH_FUNCTIONS
1178        BLTIN("return"   , builtin_return  , "Return from function"),
1179#endif
1180#if ENABLE_HUSH_SET
1181        BLTIN("set"      , builtin_set     , "Set positional parameters"),
1182#endif
1183        BLTIN("shift"    , builtin_shift   , "Shift positional parameters"),
1184#if BASH_SOURCE
1185        BLTIN("source"   , builtin_source  , NULL),
1186#endif
1187#if ENABLE_HUSH_TIMES
1188        BLTIN("times"    , builtin_times   , NULL),
1189#endif
1190#if ENABLE_HUSH_TRAP
1191        BLTIN("trap"     , builtin_trap    , "Trap signals"),
1192#endif
1193        BLTIN("true"     , builtin_true    , NULL),
1194#if ENABLE_HUSH_TYPE
1195        BLTIN("type"     , builtin_type    , "Show command type"),
1196#endif
1197#if ENABLE_HUSH_ULIMIT
1198        BLTIN("ulimit"   , shell_builtin_ulimit, "Control resource limits"),
1199#endif
1200#if ENABLE_HUSH_UMASK
1201        BLTIN("umask"    , builtin_umask   , "Set file creation mask"),
1202#endif
1203#if ENABLE_HUSH_UNSET
1204        BLTIN("unset"    , builtin_unset   , "Unset variables"),
1205#endif
1206#if ENABLE_HUSH_WAIT
1207        BLTIN("wait"     , builtin_wait    , "Wait for process to finish"),
1208#endif
1209};
1210/* These builtins won't be used if we are on NOMMU and need to re-exec
1211 * (it's cheaper to run an external program in this case):
1212 */
1213static const struct built_in_command bltins2[] = {
1214#if ENABLE_HUSH_TEST
1215        BLTIN("["        , builtin_test    , NULL),
1216#endif
1217#if BASH_TEST2
1218        BLTIN("[["       , builtin_test    , NULL),
1219#endif
1220#if ENABLE_HUSH_ECHO
1221        BLTIN("echo"     , builtin_echo    , NULL),
1222#endif
1223#if ENABLE_HUSH_PRINTF
1224        BLTIN("printf"   , builtin_printf  , NULL),
1225#endif
1226        BLTIN("pwd"      , builtin_pwd     , NULL),
1227#if ENABLE_HUSH_TEST
1228        BLTIN("test"     , builtin_test    , NULL),
1229#endif
1230};
1231
1232
1233/* Debug printouts.
1234 */
1235#if HUSH_DEBUG >= 2
1236/* prevent disasters with G.debug_indent < 0 */
1237# define indent() fdprintf(2, "%*s", (G.debug_indent * 2) & 0xff, "")
1238# define debug_enter() (G.debug_indent++)
1239# define debug_leave() (G.debug_indent--)
1240#else
1241# define indent()      ((void)0)
1242# define debug_enter() ((void)0)
1243# define debug_leave() ((void)0)
1244#endif
1245
1246#ifndef debug_printf
1247# define debug_printf(...) (indent(), fdprintf(2, __VA_ARGS__))
1248#endif
1249
1250#ifndef debug_printf_parse
1251# define debug_printf_parse(...) (indent(), fdprintf(2, __VA_ARGS__))
1252#endif
1253
1254#ifndef debug_printf_heredoc
1255# define debug_printf_heredoc(...) (indent(), fdprintf(2, __VA_ARGS__))
1256#endif
1257
1258#ifndef debug_printf_exec
1259#define debug_printf_exec(...) (indent(), fdprintf(2, __VA_ARGS__))
1260#endif
1261
1262#ifndef debug_printf_env
1263# define debug_printf_env(...) (indent(), fdprintf(2, __VA_ARGS__))
1264#endif
1265
1266#ifndef debug_printf_jobs
1267# define debug_printf_jobs(...) (indent(), fdprintf(2, __VA_ARGS__))
1268# define DEBUG_JOBS 1
1269#else
1270# define DEBUG_JOBS 0
1271#endif
1272
1273#ifndef debug_printf_expand
1274# define debug_printf_expand(...) (indent(), fdprintf(2, __VA_ARGS__))
1275# define DEBUG_EXPAND 1
1276#else
1277# define DEBUG_EXPAND 0
1278#endif
1279
1280#ifndef debug_printf_varexp
1281# define debug_printf_varexp(...) (indent(), fdprintf(2, __VA_ARGS__))
1282#endif
1283
1284#ifndef debug_printf_glob
1285# define debug_printf_glob(...) (indent(), fdprintf(2, __VA_ARGS__))
1286# define DEBUG_GLOB 1
1287#else
1288# define DEBUG_GLOB 0
1289#endif
1290
1291#ifndef debug_printf_redir
1292# define debug_printf_redir(...) (indent(), fdprintf(2, __VA_ARGS__))
1293#endif
1294
1295#ifndef debug_printf_list
1296# define debug_printf_list(...) (indent(), fdprintf(2, __VA_ARGS__))
1297#endif
1298
1299#ifndef debug_printf_subst
1300# define debug_printf_subst(...) (indent(), fdprintf(2, __VA_ARGS__))
1301#endif
1302
1303#ifndef debug_printf_prompt
1304# define debug_printf_prompt(...) (indent(), fdprintf(2, __VA_ARGS__))
1305#endif
1306
1307#ifndef debug_printf_clean
1308# define debug_printf_clean(...) (indent(), fdprintf(2, __VA_ARGS__))
1309# define DEBUG_CLEAN 1
1310#else
1311# define DEBUG_CLEAN 0
1312#endif
1313
1314#if DEBUG_EXPAND
1315static void debug_print_strings(const char *prefix, char **vv)
1316{
1317        indent();
1318        fdprintf(2, "%s:\n", prefix);
1319        while (*vv)
1320                fdprintf(2, " '%s'\n", *vv++);
1321}
1322#else
1323# define debug_print_strings(prefix, vv) ((void)0)
1324#endif
1325
1326
1327/* Leak hunting. Use hush_leaktool.sh for post-processing.
1328 */
1329#if LEAK_HUNTING
1330static void *xxmalloc(int lineno, size_t size)
1331{
1332        void *ptr = xmalloc((size + 0xff) & ~0xff);
1333        fdprintf(2, "line %d: malloc %p\n", lineno, ptr);
1334        return ptr;
1335}
1336static void *xxrealloc(int lineno, void *ptr, size_t size)
1337{
1338        ptr = xrealloc(ptr, (size + 0xff) & ~0xff);
1339        fdprintf(2, "line %d: realloc %p\n", lineno, ptr);
1340        return ptr;
1341}
1342static char *xxstrdup(int lineno, const char *str)
1343{
1344        char *ptr = xstrdup(str);
1345        fdprintf(2, "line %d: strdup %p\n", lineno, ptr);
1346        return ptr;
1347}
1348static void xxfree(void *ptr)
1349{
1350        fdprintf(2, "free %p\n", ptr);
1351        free(ptr);
1352}
1353# define xmalloc(s)     xxmalloc(__LINE__, s)
1354# define xrealloc(p, s) xxrealloc(__LINE__, p, s)
1355# define xstrdup(s)     xxstrdup(__LINE__, s)
1356# define free(p)        xxfree(p)
1357#endif
1358
1359
1360/* Syntax and runtime errors. They always abort scripts.
1361 * In interactive use they usually discard unparsed and/or unexecuted commands
1362 * and return to the prompt.
1363 * HUSH_DEBUG >= 2 prints line number in this file where it was detected.
1364 */
1365#if HUSH_DEBUG < 2
1366# define msg_and_die_if_script(lineno, ...)     msg_and_die_if_script(__VA_ARGS__)
1367# define syntax_error(lineno, msg)              syntax_error(msg)
1368# define syntax_error_at(lineno, msg)           syntax_error_at(msg)
1369# define syntax_error_unterm_ch(lineno, ch)     syntax_error_unterm_ch(ch)
1370# define syntax_error_unterm_str(lineno, s)     syntax_error_unterm_str(s)
1371# define syntax_error_unexpected_ch(lineno, ch) syntax_error_unexpected_ch(ch)
1372#endif
1373
1374static void die_if_script(void)
1375{
1376        if (!G_interactive_fd) {
1377                if (G.last_exitcode) /* sometines it's 2, not 1 (bash compat) */
1378                        xfunc_error_retval = G.last_exitcode;
1379                xfunc_die();
1380        }
1381}
1382
1383static void msg_and_die_if_script(unsigned lineno, const char *fmt, ...)
1384{
1385        va_list p;
1386
1387#if HUSH_DEBUG >= 2
1388        bb_error_msg("hush.c:%u", lineno);
1389#endif
1390        va_start(p, fmt);
1391        bb_verror_msg(fmt, p, NULL);
1392        va_end(p);
1393        die_if_script();
1394}
1395
1396static void syntax_error(unsigned lineno UNUSED_PARAM, const char *msg)
1397{
1398        if (msg)
1399                bb_error_msg("syntax error: %s", msg);
1400        else
1401                bb_error_msg("syntax error");
1402        die_if_script();
1403}
1404
1405static void syntax_error_at(unsigned lineno UNUSED_PARAM, const char *msg)
1406{
1407        bb_error_msg("syntax error at '%s'", msg);
1408        die_if_script();
1409}
1410
1411static void syntax_error_unterm_str(unsigned lineno UNUSED_PARAM, const char *s)
1412{
1413        bb_error_msg("syntax error: unterminated %s", s);
1414//? source4.tests fails: in bash, echo ${^} in script does not terminate the script
1415//      die_if_script();
1416}
1417
1418static void syntax_error_unterm_ch(unsigned lineno, char ch)
1419{
1420        char msg[2] = { ch, '\0' };
1421        syntax_error_unterm_str(lineno, msg);
1422}
1423
1424static void syntax_error_unexpected_ch(unsigned lineno UNUSED_PARAM, int ch)
1425{
1426        char msg[2];
1427        msg[0] = ch;
1428        msg[1] = '\0';
1429#if HUSH_DEBUG >= 2
1430        bb_error_msg("hush.c:%u", lineno);
1431#endif
1432        bb_error_msg("syntax error: unexpected %s", ch == EOF ? "EOF" : msg);
1433        die_if_script();
1434}
1435
1436#if HUSH_DEBUG < 2
1437# undef msg_and_die_if_script
1438# undef syntax_error
1439# undef syntax_error_at
1440# undef syntax_error_unterm_ch
1441# undef syntax_error_unterm_str
1442# undef syntax_error_unexpected_ch
1443#else
1444# define msg_and_die_if_script(...)     msg_and_die_if_script(__LINE__, __VA_ARGS__)
1445# define syntax_error(msg)              syntax_error(__LINE__, msg)
1446# define syntax_error_at(msg)           syntax_error_at(__LINE__, msg)
1447# define syntax_error_unterm_ch(ch)     syntax_error_unterm_ch(__LINE__, ch)
1448# define syntax_error_unterm_str(s)     syntax_error_unterm_str(__LINE__, s)
1449# define syntax_error_unexpected_ch(ch) syntax_error_unexpected_ch(__LINE__, ch)
1450#endif
1451
1452
1453/* Utility functions
1454 */
1455/* Replace each \x with x in place, return ptr past NUL. */
1456static char *unbackslash(char *src)
1457{
1458        char *dst = src = strchrnul(src, '\\');
1459        while (1) {
1460                if (*src == '\\') {
1461                        src++;
1462                        if (*src != '\0') {
1463                                /* \x -> x */
1464                                *dst++ = *src++;
1465                                continue;
1466                        }
1467                        /* else: "\<nul>". Do not delete this backslash.
1468                         * Testcase: eval 'echo ok\'
1469                         */
1470                        *dst++ = '\\';
1471                        /* fallthrough */
1472                }
1473                if ((*dst++ = *src++) == '\0')
1474                        break;
1475        }
1476        return dst;
1477}
1478
1479static char **add_strings_to_strings(char **strings, char **add, int need_to_dup)
1480{
1481        int i;
1482        unsigned count1;
1483        unsigned count2;
1484        char **v;
1485
1486        v = strings;
1487        count1 = 0;
1488        if (v) {
1489                while (*v) {
1490                        count1++;
1491                        v++;
1492                }
1493        }
1494        count2 = 0;
1495        v = add;
1496        while (*v) {
1497                count2++;
1498                v++;
1499        }
1500        v = xrealloc(strings, (count1 + count2 + 1) * sizeof(char*));
1501        v[count1 + count2] = NULL;
1502        i = count2;
1503        while (--i >= 0)
1504                v[count1 + i] = (need_to_dup ? xstrdup(add[i]) : add[i]);
1505        return v;
1506}
1507#if LEAK_HUNTING
1508static char **xx_add_strings_to_strings(int lineno, char **strings, char **add, int need_to_dup)
1509{
1510        char **ptr = add_strings_to_strings(strings, add, need_to_dup);
1511        fdprintf(2, "line %d: add_strings_to_strings %p\n", lineno, ptr);
1512        return ptr;
1513}
1514#define add_strings_to_strings(strings, add, need_to_dup) \
1515        xx_add_strings_to_strings(__LINE__, strings, add, need_to_dup)
1516#endif
1517
1518/* Note: takes ownership of "add" ptr (it is not strdup'ed) */
1519static char **add_string_to_strings(char **strings, char *add)
1520{
1521        char *v[2];
1522        v[0] = add;
1523        v[1] = NULL;
1524        return add_strings_to_strings(strings, v, /*dup:*/ 0);
1525}
1526#if LEAK_HUNTING
1527static char **xx_add_string_to_strings(int lineno, char **strings, char *add)
1528{
1529        char **ptr = add_string_to_strings(strings, add);
1530        fdprintf(2, "line %d: add_string_to_strings %p\n", lineno, ptr);
1531        return ptr;
1532}
1533#define add_string_to_strings(strings, add) \
1534        xx_add_string_to_strings(__LINE__, strings, add)
1535#endif
1536
1537static void free_strings(char **strings)
1538{
1539        char **v;
1540
1541        if (!strings)
1542                return;
1543        v = strings;
1544        while (*v) {
1545                free(*v);
1546                v++;
1547        }
1548        free(strings);
1549}
1550
1551static int dup_CLOEXEC(int fd, int avoid_fd)
1552{
1553        int newfd;
1554 repeat:
1555        newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
1556        if (newfd >= 0) {
1557                if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
1558                        fcntl(newfd, F_SETFD, FD_CLOEXEC);
1559        } else { /* newfd < 0 */
1560                if (errno == EBUSY)
1561                        goto repeat;
1562                if (errno == EINTR)
1563                        goto repeat;
1564        }
1565        return newfd;
1566}
1567
1568static int xdup_CLOEXEC_and_close(int fd, int avoid_fd)
1569{
1570        int newfd;
1571 repeat:
1572        newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
1573        if (newfd < 0) {
1574                if (errno == EBUSY)
1575                        goto repeat;
1576                if (errno == EINTR)
1577                        goto repeat;
1578                /* fd was not open? */
1579                if (errno == EBADF)
1580                        return fd;
1581                xfunc_die();
1582        }
1583        if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
1584                fcntl(newfd, F_SETFD, FD_CLOEXEC);
1585        close(fd);
1586        return newfd;
1587}
1588
1589
1590/* Manipulating HFILEs */
1591static HFILE *hfopen(const char *name)
1592{
1593        HFILE *fp;
1594        int fd;
1595
1596        fd = STDIN_FILENO;
1597        if (name) {
1598                fd = open(name, O_RDONLY | O_CLOEXEC);
1599                if (fd < 0)
1600                        return NULL;
1601                if (O_CLOEXEC == 0) /* ancient libc */
1602                        close_on_exec_on(fd);
1603        }
1604
1605        fp = xmalloc(sizeof(*fp));
1606        fp->is_stdin = (name == NULL);
1607        fp->fd = fd;
1608        fp->cur = fp->end = fp->buf;
1609        fp->next_hfile = G.HFILE_list;
1610        G.HFILE_list = fp;
1611        return fp;
1612}
1613static void hfclose(HFILE *fp)
1614{
1615        HFILE **pp = &G.HFILE_list;
1616        while (*pp) {
1617                HFILE *cur = *pp;
1618                if (cur == fp) {
1619                        *pp = cur->next_hfile;
1620                        break;
1621                }
1622                pp = &cur->next_hfile;
1623        }
1624        if (fp->fd >= 0)
1625                close(fp->fd);
1626        free(fp);
1627}
1628static int refill_HFILE_and_getc(HFILE *fp)
1629{
1630        int n;
1631
1632        if (fp->fd < 0) {
1633                /* Already saw EOF */
1634                return EOF;
1635        }
1636        /* Try to buffer more input */
1637        fp->cur = fp->buf;
1638        n = safe_read(fp->fd, fp->buf, sizeof(fp->buf));
1639        if (n < 0) {
1640                bb_perror_msg("read error");
1641                n = 0;
1642        }
1643        fp->end = fp->buf + n;
1644        if (n == 0) {
1645                /* EOF/error */
1646                close(fp->fd);
1647                fp->fd = -1;
1648                return EOF;
1649        }
1650        return (unsigned char)(*fp->cur++);
1651}
1652/* Inlined for common case of non-empty buffer.
1653 */
1654static ALWAYS_INLINE int hfgetc(HFILE *fp)
1655{
1656        if (fp->cur < fp->end)
1657                return (unsigned char)(*fp->cur++);
1658        /* Buffer empty */
1659        return refill_HFILE_and_getc(fp);
1660}
1661static int move_HFILEs_on_redirect(int fd, int avoid_fd)
1662{
1663        HFILE *fl = G.HFILE_list;
1664        while (fl) {
1665                if (fd == fl->fd) {
1666                        /* We use it only on script files, they are all CLOEXEC */
1667                        fl->fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
1668                        debug_printf_redir("redirect_fd %d: matches a script fd, moving it to %d\n", fd, fl->fd);
1669                        return 1; /* "found and moved" */
1670                }
1671                fl = fl->next_hfile;
1672        }
1673#if ENABLE_HUSH_MODE_X
1674        if (G.x_mode_fd > 0 && fd == G.x_mode_fd) {
1675                G.x_mode_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
1676                return 1; /* "found and moved" */
1677        }
1678#endif
1679        return 0; /* "not in the list" */
1680}
1681#if ENABLE_FEATURE_SH_STANDALONE && BB_MMU
1682static void close_all_HFILE_list(void)
1683{
1684        HFILE *fl = G.HFILE_list;
1685        while (fl) {
1686                /* hfclose would also free HFILE object.
1687                 * It is disastrous if we share memory with a vforked parent.
1688                 * I'm not sure we never come here after vfork.
1689                 * Therefore just close fd, nothing more.
1690                 *
1691                 * ">" instead of ">=": we don't close fd#0,
1692                 * interactive shell uses hfopen(NULL) as stdin input
1693                 * which has fl->fd == 0, but fd#0 gets redirected in pipes.
1694                 * If we'd close it here, then e.g. interactive "set | sort"
1695                 * with NOFORKed sort, would have sort's input fd closed.
1696                 */
1697                if (fl->fd > 0)
1698                        /*hfclose(fl); - unsafe */
1699                        close(fl->fd);
1700                fl = fl->next_hfile;
1701        }
1702}
1703#endif
1704static int fd_in_HFILEs(int fd)
1705{
1706        HFILE *fl = G.HFILE_list;
1707        while (fl) {
1708                if (fl->fd == fd)
1709                        return 1;
1710                fl = fl->next_hfile;
1711        }
1712        return 0;
1713}
1714
1715
1716/* Helpers for setting new $n and restoring them back
1717 */
1718typedef struct save_arg_t {
1719        char *sv_argv0;
1720        char **sv_g_argv;
1721        int sv_g_argc;
1722        IF_HUSH_SET(smallint sv_g_malloced;)
1723} save_arg_t;
1724
1725static void save_and_replace_G_args(save_arg_t *sv, char **argv)
1726{
1727        sv->sv_argv0 = argv[0];
1728        sv->sv_g_argv = G.global_argv;
1729        sv->sv_g_argc = G.global_argc;
1730        IF_HUSH_SET(sv->sv_g_malloced = G.global_args_malloced;)
1731
1732        argv[0] = G.global_argv[0]; /* retain $0 */
1733        G.global_argv = argv;
1734        IF_HUSH_SET(G.global_args_malloced = 0;)
1735
1736        G.global_argc = 1 + string_array_len(argv + 1);
1737}
1738
1739static void restore_G_args(save_arg_t *sv, char **argv)
1740{
1741#if ENABLE_HUSH_SET
1742        if (G.global_args_malloced) {
1743                /* someone ran "set -- arg1 arg2 ...", undo */
1744                char **pp = G.global_argv;
1745                while (*++pp) /* note: does not free $0 */
1746                        free(*pp);
1747                free(G.global_argv);
1748        }
1749#endif
1750        argv[0] = sv->sv_argv0;
1751        G.global_argv = sv->sv_g_argv;
1752        G.global_argc = sv->sv_g_argc;
1753        IF_HUSH_SET(G.global_args_malloced = sv->sv_g_malloced;)
1754}
1755
1756
1757/* Basic theory of signal handling in shell
1758 * ========================================
1759 * This does not describe what hush does, rather, it is current understanding
1760 * what it _should_ do. If it doesn't, it's a bug.
1761 * http://www.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#trap
1762 *
1763 * Signals are handled only after each pipe ("cmd | cmd | cmd" thing)
1764 * is finished or backgrounded. It is the same in interactive and
1765 * non-interactive shells, and is the same regardless of whether
1766 * a user trap handler is installed or a shell special one is in effect.
1767 * ^C or ^Z from keyboard seems to execute "at once" because it usually
1768 * backgrounds (i.e. stops) or kills all members of currently running
1769 * pipe.
1770 *
1771 * Wait builtin is interruptible by signals for which user trap is set
1772 * or by SIGINT in interactive shell.
1773 *
1774 * Trap handlers will execute even within trap handlers. (right?)
1775 *
1776 * User trap handlers are forgotten when subshell ("(cmd)") is entered,
1777 * except for handlers set to '' (empty string).
1778 *
1779 * If job control is off, backgrounded commands ("cmd &")
1780 * have SIGINT, SIGQUIT set to SIG_IGN.
1781 *
1782 * Commands which are run in command substitution ("`cmd`")
1783 * have SIGTTIN, SIGTTOU, SIGTSTP set to SIG_IGN.
1784 *
1785 * Ordinary commands have signals set to SIG_IGN/DFL as inherited
1786 * by the shell from its parent.
1787 *
1788 * Signals which differ from SIG_DFL action
1789 * (note: child (i.e., [v]forked) shell is not an interactive shell):
1790 *
1791 * SIGQUIT: ignore
1792 * SIGTERM (interactive): ignore
1793 * SIGHUP (interactive):
1794 *    send SIGCONT to stopped jobs, send SIGHUP to all jobs and exit
1795 * SIGTTIN, SIGTTOU, SIGTSTP (if job control is on): ignore
1796 *    Note that ^Z is handled not by trapping SIGTSTP, but by seeing
1797 *    that all pipe members are stopped. Try this in bash:
1798 *    while :; do :; done - ^Z does not background it
1799 *    (while :; do :; done) - ^Z backgrounds it
1800 * SIGINT (interactive): wait for last pipe, ignore the rest
1801 *    of the command line, show prompt. NB: ^C does not send SIGINT
1802 *    to interactive shell while shell is waiting for a pipe,
1803 *    since shell is bg'ed (is not in foreground process group).
1804 *    Example 1: this waits 5 sec, but does not execute ls:
1805 *    "echo $$; sleep 5; ls -l" + "kill -INT <pid>"
1806 *    Example 2: this does not wait and does not execute ls:
1807 *    "echo $$; sleep 5 & wait; ls -l" + "kill -INT <pid>"
1808 *    Example 3: this does not wait 5 sec, but executes ls:
1809 *    "sleep 5; ls -l" + press ^C
1810 *    Example 4: this does not wait and does not execute ls:
1811 *    "sleep 5 & wait; ls -l" + press ^C
1812 *
1813 * (What happens to signals which are IGN on shell start?)
1814 * (What happens with signal mask on shell start?)
1815 *
1816 * Old implementation
1817 * ==================
1818 * We use in-kernel pending signal mask to determine which signals were sent.
1819 * We block all signals which we don't want to take action immediately,
1820 * i.e. we block all signals which need to have special handling as described
1821 * above, and all signals which have traps set.
1822 * After each pipe execution, we extract any pending signals via sigtimedwait()
1823 * and act on them.
1824 *
1825 * unsigned special_sig_mask: a mask of such "special" signals
1826 * sigset_t blocked_set:  current blocked signal set
1827 *
1828 * "trap - SIGxxx":
1829 *    clear bit in blocked_set unless it is also in special_sig_mask
1830 * "trap 'cmd' SIGxxx":
1831 *    set bit in blocked_set (even if 'cmd' is '')
1832 * after [v]fork, if we plan to be a shell:
1833 *    unblock signals with special interactive handling
1834 *    (child shell is not interactive),
1835 *    unset all traps except '' (note: regardless of child shell's type - {}, (), etc)
1836 * after [v]fork, if we plan to exec:
1837 *    POSIX says fork clears pending signal mask in child - no need to clear it.
1838 *    Restore blocked signal set to one inherited by shell just prior to exec.
1839 *
1840 * Note: as a result, we do not use signal handlers much. The only uses
1841 * are to count SIGCHLDs
1842 * and to restore tty pgrp on signal-induced exit.
1843 *
1844 * Note 2 (compat):
1845 * Standard says "When a subshell is entered, traps that are not being ignored
1846 * are set to the default actions". bash interprets it so that traps which
1847 * are set to '' (ignore) are NOT reset to defaults. We do the same.
1848 *
1849 * Problem: the above approach makes it unwieldy to catch signals while
1850 * we are in read builtin, or while we read commands from stdin:
1851 * masked signals are not visible!
1852 *
1853 * New implementation
1854 * ==================
1855 * We record each signal we are interested in by installing signal handler
1856 * for them - a bit like emulating kernel pending signal mask in userspace.
1857 * We are interested in: signals which need to have special handling
1858 * as described above, and all signals which have traps set.
1859 * Signals are recorded in pending_set.
1860 * After each pipe execution, we extract any pending signals
1861 * and act on them.
1862 *
1863 * unsigned special_sig_mask: a mask of shell-special signals.
1864 * unsigned fatal_sig_mask: a mask of signals on which we restore tty pgrp.
1865 * char *traps[sig] if trap for sig is set (even if it's '').
1866 * sigset_t pending_set: set of sigs we received.
1867 *
1868 * "trap - SIGxxx":
1869 *    if sig is in special_sig_mask, set handler back to:
1870 *        record_pending_signo, or to IGN if it's a tty stop signal
1871 *    if sig is in fatal_sig_mask, set handler back to sigexit.
1872 *    else: set handler back to SIG_DFL
1873 * "trap 'cmd' SIGxxx":
1874 *    set handler to record_pending_signo.
1875 * "trap '' SIGxxx":
1876 *    set handler to SIG_IGN.
1877 * after [v]fork, if we plan to be a shell:
1878 *    set signals with special interactive handling to SIG_DFL
1879 *    (because child shell is not interactive),
1880 *    unset all traps except '' (note: regardless of child shell's type - {}, (), etc)
1881 * after [v]fork, if we plan to exec:
1882 *    POSIX says fork clears pending signal mask in child - no need to clear it.
1883 *
1884 * To make wait builtin interruptible, we handle SIGCHLD as special signal,
1885 * otherwise (if we leave it SIG_DFL) sigsuspend in wait builtin will not wake up on it.
1886 *
1887 * Note (compat):
1888 * Standard says "When a subshell is entered, traps that are not being ignored
1889 * are set to the default actions". bash interprets it so that traps which
1890 * are set to '' (ignore) are NOT reset to defaults. We do the same.
1891 */
1892enum {
1893        SPECIAL_INTERACTIVE_SIGS = 0
1894                | (1 << SIGTERM)
1895                | (1 << SIGINT)
1896                | (1 << SIGHUP)
1897                ,
1898        SPECIAL_JOBSTOP_SIGS = 0
1899#if ENABLE_HUSH_JOB
1900                | (1 << SIGTTIN)
1901                | (1 << SIGTTOU)
1902                | (1 << SIGTSTP)
1903#endif
1904                ,
1905};
1906
1907static void record_pending_signo(int sig)
1908{
1909        sigaddset(&G.pending_set, sig);
1910#if ENABLE_HUSH_FAST
1911        if (sig == SIGCHLD) {
1912                G.count_SIGCHLD++;
1913//bb_error_msg("[%d] SIGCHLD_handler: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
1914        }
1915#endif
1916}
1917
1918static sighandler_t install_sighandler(int sig, sighandler_t handler)
1919{
1920        struct sigaction old_sa;
1921
1922        /* We could use signal() to install handlers... almost:
1923         * except that we need to mask ALL signals while handlers run.
1924         * I saw signal nesting in strace, race window isn't small.
1925         * SA_RESTART is also needed, but in Linux, signal()
1926         * sets SA_RESTART too.
1927         */
1928        /* memset(&G.sa, 0, sizeof(G.sa)); - already done */
1929        /* sigfillset(&G.sa.sa_mask);      - already done */
1930        /* G.sa.sa_flags = SA_RESTART;     - already done */
1931        G.sa.sa_handler = handler;
1932        sigaction(sig, &G.sa, &old_sa);
1933        return old_sa.sa_handler;
1934}
1935
1936static void hush_exit(int exitcode) NORETURN;
1937
1938static void restore_ttypgrp_and__exit(void) NORETURN;
1939static void restore_ttypgrp_and__exit(void)
1940{
1941        /* xfunc has failed! die die die */
1942        /* no EXIT traps, this is an escape hatch! */
1943        G.exiting = 1;
1944        hush_exit(xfunc_error_retval);
1945}
1946
1947#if ENABLE_HUSH_JOB
1948
1949/* Needed only on some libc:
1950 * It was observed that on exit(), fgetc'ed buffered data
1951 * gets "unwound" via lseek(fd, -NUM, SEEK_CUR).
1952 * With the net effect that even after fork(), not vfork(),
1953 * exit() in NOEXECed applet in "sh SCRIPT":
1954 *      noexec_applet_here
1955 *      echo END_OF_SCRIPT
1956 * lseeks fd in input FILE object from EOF to "e" in "echo END_OF_SCRIPT".
1957 * This makes "echo END_OF_SCRIPT" executed twice.
1958 * Similar problems can be seen with msg_and_die_if_script() -> xfunc_die()
1959 * and in `cmd` handling.
1960 * If set as die_func(), this makes xfunc_die() exit via _exit(), not exit():
1961 */
1962static void fflush_and__exit(void) NORETURN;
1963static void fflush_and__exit(void)
1964{
1965        fflush_all();
1966        _exit(xfunc_error_retval);
1967}
1968
1969/* After [v]fork, in child: do not restore tty pgrp on xfunc death */
1970# define disable_restore_tty_pgrp_on_exit() (die_func = fflush_and__exit)
1971/* After [v]fork, in parent: restore tty pgrp on xfunc death */
1972# define enable_restore_tty_pgrp_on_exit()  (die_func = restore_ttypgrp_and__exit)
1973
1974/* Restores tty foreground process group, and exits.
1975 * May be called as signal handler for fatal signal
1976 * (will resend signal to itself, producing correct exit state)
1977 * or called directly with -EXITCODE.
1978 * We also call it if xfunc is exiting.
1979 */
1980static void sigexit(int sig) NORETURN;
1981static void sigexit(int sig)
1982{
1983        /* Careful: we can end up here after [v]fork. Do not restore
1984         * tty pgrp then, only top-level shell process does that */
1985        if (G_saved_tty_pgrp && getpid() == G.root_pid) {
1986                /* Disable all signals: job control, SIGPIPE, etc.
1987                 * Mostly paranoid measure, to prevent infinite SIGTTOU.
1988                 */
1989                sigprocmask_allsigs(SIG_BLOCK);
1990                tcsetpgrp(G_interactive_fd, G_saved_tty_pgrp);
1991        }
1992
1993        /* Not a signal, just exit */
1994        if (sig <= 0)
1995                _exit(- sig);
1996
1997        kill_myself_with_sig(sig); /* does not return */
1998}
1999#else
2000
2001# define disable_restore_tty_pgrp_on_exit() ((void)0)
2002# define enable_restore_tty_pgrp_on_exit()  ((void)0)
2003
2004#endif
2005
2006static sighandler_t pick_sighandler(unsigned sig)
2007{
2008        sighandler_t handler = SIG_DFL;
2009        if (sig < sizeof(unsigned)*8) {
2010                unsigned sigmask = (1 << sig);
2011
2012#if ENABLE_HUSH_JOB
2013                /* is sig fatal? */
2014                if (G_fatal_sig_mask & sigmask)
2015                        handler = sigexit;
2016                else
2017#endif
2018                /* sig has special handling? */
2019                if (G.special_sig_mask & sigmask) {
2020                        handler = record_pending_signo;
2021                        /* TTIN/TTOU/TSTP can't be set to record_pending_signo
2022                         * in order to ignore them: they will be raised
2023                         * in an endless loop when we try to do some
2024                         * terminal ioctls! We do have to _ignore_ these.
2025                         */
2026                        if (SPECIAL_JOBSTOP_SIGS & sigmask)
2027                                handler = SIG_IGN;
2028                }
2029        }
2030        return handler;
2031}
2032
2033/* Restores tty foreground process group, and exits. */
2034static void hush_exit(int exitcode)
2035{
2036#if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
2037        if (G.line_input_state)
2038                save_history(G.line_input_state);
2039#endif
2040
2041        fflush_all();
2042        if (G.exiting <= 0 && G_traps && G_traps[0] && G_traps[0][0]) {
2043                char *argv[3];
2044                /* argv[0] is unused */
2045                argv[1] = xstrdup(G_traps[0]); /* copy, since EXIT trap handler may modify G_traps[0] */
2046                argv[2] = NULL;
2047                G.exiting = 1; /* prevent EXIT trap recursion */
2048                /* Note: G_traps[0] is not cleared!
2049                 * "trap" will still show it, if executed
2050                 * in the handler */
2051                builtin_eval(argv);
2052        }
2053
2054#if ENABLE_FEATURE_CLEAN_UP
2055        {
2056                struct variable *cur_var;
2057                if (G.cwd != bb_msg_unknown)
2058                        free((char*)G.cwd);
2059                cur_var = G.top_var;
2060                while (cur_var) {
2061                        struct variable *tmp = cur_var;
2062                        if (!cur_var->max_len)
2063                                free(cur_var->varstr);
2064                        cur_var = cur_var->next;
2065                        free(tmp);
2066                }
2067        }
2068#endif
2069
2070        fflush_all();
2071#if ENABLE_HUSH_JOB
2072        sigexit(- (exitcode & 0xff));
2073#else
2074        _exit(exitcode);
2075#endif
2076}
2077
2078
2079//TODO: return a mask of ALL handled sigs?
2080static int check_and_run_traps(void)
2081{
2082        int last_sig = 0;
2083
2084        while (1) {
2085                int sig;
2086
2087                if (sigisemptyset(&G.pending_set))
2088                        break;
2089                sig = 0;
2090                do {
2091                        sig++;
2092                        if (sigismember(&G.pending_set, sig)) {
2093                                sigdelset(&G.pending_set, sig);
2094                                goto got_sig;
2095                        }
2096                } while (sig < NSIG);
2097                break;
2098 got_sig:
2099                if (G_traps && G_traps[sig]) {
2100                        debug_printf_exec("%s: sig:%d handler:'%s'\n", __func__, sig, G.traps[sig]);
2101                        if (G_traps[sig][0]) {
2102                                /* We have user-defined handler */
2103                                smalluint save_rcode;
2104                                char *argv[3];
2105                                /* argv[0] is unused */
2106                                argv[1] = xstrdup(G_traps[sig]);
2107                                /* why strdup? trap can modify itself: trap 'trap "echo oops" INT' INT */
2108                                argv[2] = NULL;
2109                                save_rcode = G.last_exitcode;
2110                                builtin_eval(argv);
2111                                free(argv[1]);
2112//FIXME: shouldn't it be set to 128 + sig instead?
2113                                G.last_exitcode = save_rcode;
2114                                last_sig = sig;
2115                        } /* else: "" trap, ignoring signal */
2116                        continue;
2117                }
2118                /* not a trap: special action */
2119                switch (sig) {
2120                case SIGINT:
2121                        debug_printf_exec("%s: sig:%d default SIGINT handler\n", __func__, sig);
2122                        G.flag_SIGINT = 1;
2123                        last_sig = sig;
2124                        break;
2125#if ENABLE_HUSH_JOB
2126                case SIGHUP: {
2127//TODO: why are we doing this? ash and dash don't do this,
2128//they have no handler for SIGHUP at all,
2129//they rely on kernel to send SIGHUP+SIGCONT to orphaned process groups
2130                        struct pipe *job;
2131                        debug_printf_exec("%s: sig:%d default SIGHUP handler\n", __func__, sig);
2132                        /* bash is observed to signal whole process groups,
2133                         * not individual processes */
2134                        for (job = G.job_list; job; job = job->next) {
2135                                if (job->pgrp <= 0)
2136                                        continue;
2137                                debug_printf_exec("HUPing pgrp %d\n", job->pgrp);
2138                                if (kill(- job->pgrp, SIGHUP) == 0)
2139                                        kill(- job->pgrp, SIGCONT);
2140                        }
2141                        sigexit(SIGHUP);
2142                }
2143#endif
2144#if ENABLE_HUSH_FAST
2145                case SIGCHLD:
2146                        debug_printf_exec("%s: sig:%d default SIGCHLD handler\n", __func__, sig);
2147                        G.count_SIGCHLD++;
2148//bb_error_msg("[%d] check_and_run_traps: G.count_SIGCHLD:%d G.handled_SIGCHLD:%d", getpid(), G.count_SIGCHLD, G.handled_SIGCHLD);
2149                        /* Note:
2150                         * We don't do 'last_sig = sig' here -> NOT returning this sig.
2151                         * This simplifies wait builtin a bit.
2152                         */
2153                        break;
2154#endif
2155                default: /* ignored: */
2156                        debug_printf_exec("%s: sig:%d default handling is to ignore\n", __func__, sig);
2157                        /* SIGTERM, SIGQUIT, SIGTTIN, SIGTTOU, SIGTSTP */
2158                        /* Note:
2159                         * We don't do 'last_sig = sig' here -> NOT returning this sig.
2160                         * Example: wait is not interrupted by TERM
2161                         * in interactive shell, because TERM is ignored.
2162                         */
2163                        break;
2164                }
2165        }
2166        return last_sig;
2167}
2168
2169
2170static const char *get_cwd(int force)
2171{
2172        if (force || G.cwd == NULL) {
2173                /* xrealloc_getcwd_or_warn(arg) calls free(arg),
2174                 * we must not try to free(bb_msg_unknown) */
2175                if (G.cwd == bb_msg_unknown)
2176                        G.cwd = NULL;
2177                G.cwd = xrealloc_getcwd_or_warn((char *)G.cwd);
2178                if (!G.cwd)
2179                        G.cwd = bb_msg_unknown;
2180        }
2181        return G.cwd;
2182}
2183
2184
2185/*
2186 * Shell and environment variable support
2187 */
2188static struct variable **get_ptr_to_local_var(const char *name, unsigned len)
2189{
2190        struct variable **pp;
2191        struct variable *cur;
2192
2193        pp = &G.top_var;
2194        while ((cur = *pp) != NULL) {
2195                if (strncmp(cur->varstr, name, len) == 0 && cur->varstr[len] == '=')
2196                        return pp;
2197                pp = &cur->next;
2198        }
2199        return NULL;
2200}
2201
2202static const char* FAST_FUNC get_local_var_value(const char *name)
2203{
2204        struct variable **vpp;
2205        unsigned len = strlen(name);
2206
2207        if (G.expanded_assignments) {
2208                char **cpp = G.expanded_assignments;
2209                while (*cpp) {
2210                        char *cp = *cpp;
2211                        if (strncmp(cp, name, len) == 0 && cp[len] == '=')
2212                                return cp + len + 1;
2213                        cpp++;
2214                }
2215        }
2216
2217        vpp = get_ptr_to_local_var(name, len);
2218        if (vpp)
2219                return (*vpp)->varstr + len + 1;
2220
2221        if (strcmp(name, "PPID") == 0)
2222                return utoa(G.root_ppid);
2223        // bash compat: UID? EUID?
2224#if ENABLE_HUSH_RANDOM_SUPPORT
2225        if (strcmp(name, "RANDOM") == 0)
2226                return utoa(next_random(&G.random_gen));
2227#endif
2228#if ENABLE_HUSH_LINENO_VAR
2229        if (strcmp(name, "LINENO") == 0)
2230                return utoa(G.execute_lineno);
2231#endif
2232#if BASH_EPOCH_VARS
2233        {
2234                const char *fmt = NULL;
2235                if (strcmp(name, "EPOCHSECONDS") == 0)
2236                        fmt = "%lu";
2237                else if (strcmp(name, "EPOCHREALTIME") == 0)
2238                        fmt = "%lu.%06u";
2239                if (fmt) {
2240                        struct timeval tv;
2241                        gettimeofday(&tv, NULL);
2242                        sprintf(G.epoch_buf, fmt, (unsigned long)tv.tv_sec,
2243                                        (unsigned)tv.tv_usec);
2244                        return G.epoch_buf;
2245                }
2246        }
2247#endif
2248        return NULL;
2249}
2250
2251#if ENABLE_HUSH_GETOPTS
2252static void handle_changed_special_names(const char *name, unsigned name_len)
2253{
2254        if (name_len == 6) {
2255                if (strncmp(name, "OPTIND", 6) == 0) {
2256                        G.getopt_count = 0;
2257                        return;
2258                }
2259        }
2260}
2261#else
2262/* Do not even bother evaluating arguments */
2263# define handle_changed_special_names(...) ((void)0)
2264#endif
2265
2266/* str holds "NAME=VAL" and is expected to be malloced.
2267 * We take ownership of it.
2268 */
2269#define SETFLAG_EXPORT   (1 << 0)
2270#define SETFLAG_UNEXPORT (1 << 1)
2271#define SETFLAG_MAKE_RO  (1 << 2)
2272#define SETFLAG_VARLVL_SHIFT   3
2273static int set_local_var(char *str, unsigned flags)
2274{
2275        struct variable **cur_pp;
2276        struct variable *cur;
2277        char *free_me = NULL;
2278        char *eq_sign;
2279        int name_len;
2280        int retval;
2281        unsigned local_lvl = (flags >> SETFLAG_VARLVL_SHIFT);
2282
2283        eq_sign = strchr(str, '=');
2284        if (HUSH_DEBUG && !eq_sign)
2285                bb_error_msg_and_die("BUG in setvar");
2286
2287        name_len = eq_sign - str + 1; /* including '=' */
2288        cur_pp = &G.top_var;
2289        while ((cur = *cur_pp) != NULL) {
2290                if (strncmp(cur->varstr, str, name_len) != 0) {
2291                        cur_pp = &cur->next;
2292                        continue;
2293                }
2294
2295                /* We found an existing var with this name */
2296                if (cur->flg_read_only) {
2297                        bb_error_msg("%s: readonly variable", str);
2298                        free(str);
2299//NOTE: in bash, assignment in "export READONLY_VAR=Z" fails, and sets $?=1,
2300//but export per se succeeds (does put the var in env). We don't mimic that.
2301                        return -1;
2302                }
2303                if (flags & SETFLAG_UNEXPORT) { // && cur->flg_export ?
2304                        debug_printf_env("%s: unsetenv '%s'\n", __func__, str);
2305                        *eq_sign = '\0';
2306                        unsetenv(str);
2307                        *eq_sign = '=';
2308                }
2309                if (cur->var_nest_level < local_lvl) {
2310                        /* bash 3.2.33(1) and exported vars:
2311                         * # export z=z
2312                         * # f() { local z=a; env | grep ^z; }
2313                         * # f
2314                         * z=a
2315                         * # env | grep ^z
2316                         * z=z
2317                         */
2318                        if (cur->flg_export)
2319                                flags |= SETFLAG_EXPORT;
2320                        /* New variable is local ("local VAR=VAL" or
2321                         * "VAR=VAL cmd")
2322                         * and existing one is global, or local
2323                         * on a lower level that new one.
2324                         * Remove it from global variable list:
2325                         */
2326                        *cur_pp = cur->next;
2327                        if (G.shadowed_vars_pp) {
2328                                /* Save in "shadowed" list */
2329                                debug_printf_env("shadowing %s'%s'/%u by '%s'/%u\n",
2330                                        cur->flg_export ? "exported " : "",
2331                                        cur->varstr, cur->var_nest_level, str, local_lvl
2332                                );
2333                                cur->next = *G.shadowed_vars_pp;
2334                                *G.shadowed_vars_pp = cur;
2335                        } else {
2336                                /* Came from pseudo_exec_argv(), no need to save: delete it */
2337                                debug_printf_env("shadow-deleting %s'%s'/%u by '%s'/%u\n",
2338                                        cur->flg_export ? "exported " : "",
2339                                        cur->varstr, cur->var_nest_level, str, local_lvl
2340                                );
2341                                if (cur->max_len == 0) /* allocated "VAR=VAL"? */
2342                                        free_me = cur->varstr; /* then free it later */
2343                                free(cur);
2344                        }
2345                        break;
2346                }
2347
2348                if (strcmp(cur->varstr + name_len, eq_sign + 1) == 0) {
2349                        debug_printf_env("assignement '%s' does not change anything\n", str);
2350 free_and_exp:
2351                        free(str);
2352                        goto exp;
2353                }
2354
2355                /* Replace the value in the found "struct variable" */
2356                if (cur->max_len != 0) {
2357                        if (cur->max_len >= strnlen(str, cur->max_len + 1)) {
2358                                /* This one is from startup env, reuse space */
2359                                debug_printf_env("reusing startup env for '%s'\n", str);
2360                                strcpy(cur->varstr, str);
2361                                goto free_and_exp;
2362                        }
2363                        /* Can't reuse */
2364                        cur->max_len = 0;
2365                        goto set_str_and_exp;
2366                }
2367                /* max_len == 0 signifies "malloced" var, which we can
2368                 * (and have to) free. But we can't free(cur->varstr) here:
2369                 * if cur->flg_export is 1, it is in the environment.
2370                 * We should either unsetenv+free, or wait until putenv,
2371                 * then putenv(new)+free(old).
2372                 */
2373                free_me = cur->varstr;
2374                goto set_str_and_exp;
2375        }
2376
2377        /* Not found or shadowed - create new variable struct */
2378        debug_printf_env("%s: alloc new var '%s'/%u\n", __func__, str, local_lvl);
2379        cur = xzalloc(sizeof(*cur));
2380        cur->var_nest_level = local_lvl;
2381        cur->next = *cur_pp;
2382        *cur_pp = cur;
2383
2384 set_str_and_exp:
2385        cur->varstr = str;
2386 exp:
2387#if !BB_MMU || ENABLE_HUSH_READONLY
2388        if (flags & SETFLAG_MAKE_RO) {
2389                cur->flg_read_only = 1;
2390        }
2391#endif
2392        if (flags & SETFLAG_EXPORT)
2393                cur->flg_export = 1;
2394        retval = 0;
2395        if (cur->flg_export) {
2396                if (flags & SETFLAG_UNEXPORT) {
2397                        cur->flg_export = 0;
2398                        /* unsetenv was already done */
2399                } else {
2400                        debug_printf_env("%s: putenv '%s'/%u\n", __func__, cur->varstr, cur->var_nest_level);
2401                        retval = putenv(cur->varstr);
2402                        /* fall through to "free(free_me)" -
2403                         * only now we can free old exported malloced string
2404                         */
2405                }
2406        }
2407        free(free_me);
2408
2409        handle_changed_special_names(cur->varstr, name_len - 1);
2410
2411        return retval;
2412}
2413
2414static void FAST_FUNC set_local_var_from_halves(const char *name, const char *val)
2415{
2416        char *var = xasprintf("%s=%s", name, val);
2417        set_local_var(var, /*flag:*/ 0);
2418}
2419
2420/* Used at startup and after each cd */
2421static void set_pwd_var(unsigned flag)
2422{
2423        set_local_var(xasprintf("PWD=%s", get_cwd(/*force:*/ 1)), flag);
2424}
2425
2426#if ENABLE_HUSH_UNSET || ENABLE_HUSH_GETOPTS
2427static int unset_local_var_len(const char *name, int name_len)
2428{
2429        struct variable *cur;
2430        struct variable **cur_pp;
2431
2432        cur_pp = &G.top_var;
2433        while ((cur = *cur_pp) != NULL) {
2434                if (strncmp(cur->varstr, name, name_len) == 0
2435                 && cur->varstr[name_len] == '='
2436                ) {
2437                        if (cur->flg_read_only) {
2438                                bb_error_msg("%s: readonly variable", name);
2439                                return EXIT_FAILURE;
2440                        }
2441
2442                        *cur_pp = cur->next;
2443                        debug_printf_env("%s: unsetenv '%s'\n", __func__, cur->varstr);
2444                        bb_unsetenv(cur->varstr);
2445                        if (!cur->max_len)
2446                                free(cur->varstr);
2447                        free(cur);
2448
2449                        break;
2450                }
2451                cur_pp = &cur->next;
2452        }
2453
2454        /* Handle "unset LINENO" et al even if did not find the variable to unset */
2455        handle_changed_special_names(name, name_len);
2456
2457        return EXIT_SUCCESS;
2458}
2459
2460static int unset_local_var(const char *name)
2461{
2462        return unset_local_var_len(name, strlen(name));
2463}
2464#endif
2465
2466
2467/*
2468 * Helpers for "var1=val1 var2=val2 cmd" feature
2469 */
2470static void add_vars(struct variable *var)
2471{
2472        struct variable *next;
2473
2474        while (var) {
2475                next = var->next;
2476                var->next = G.top_var;
2477                G.top_var = var;
2478                if (var->flg_export) {
2479                        debug_printf_env("%s: restoring exported '%s'/%u\n", __func__, var->varstr, var->var_nest_level);
2480                        putenv(var->varstr);
2481                } else {
2482                        debug_printf_env("%s: restoring variable '%s'/%u\n", __func__, var->varstr, var->var_nest_level);
2483                }
2484                var = next;
2485        }
2486}
2487
2488/* We put strings[i] into variable table and possibly putenv them.
2489 * If variable is read only, we can free the strings[i]
2490 * which attempts to overwrite it.
2491 * The strings[] vector itself is freed.
2492 */
2493static void set_vars_and_save_old(char **strings)
2494{
2495        char **s;
2496
2497        if (!strings)
2498                return;
2499
2500        s = strings;
2501        while (*s) {
2502                struct variable *var_p;
2503                struct variable **var_pp;
2504                char *eq;
2505
2506                eq = strchr(*s, '=');
2507                if (HUSH_DEBUG && !eq)
2508                        bb_error_msg_and_die("BUG in varexp4");
2509                var_pp = get_ptr_to_local_var(*s, eq - *s);
2510                if (var_pp) {
2511                        var_p = *var_pp;
2512                        if (var_p->flg_read_only) {
2513                                char **p;
2514                                bb_error_msg("%s: readonly variable", *s);
2515                                /*
2516                                 * "VAR=V BLTIN" unsets VARs after BLTIN completes.
2517                                 * If VAR is readonly, leaving it in the list
2518                                 * after asssignment error (msg above)
2519                                 * causes doubled error message later, on unset.
2520                                 */
2521                                debug_printf_env("removing/freeing '%s' element\n", *s);
2522                                free(*s);
2523                                p = s;
2524                                do { *p = p[1]; p++; } while (*p);
2525                                goto next;
2526                        }
2527                        /* below, set_local_var() with nest level will
2528                         * "shadow" (remove) this variable from
2529                         * global linked list.
2530                         */
2531                }
2532                debug_printf_env("%s: env override '%s'/%u\n", __func__, *s, G.var_nest_level);
2533                set_local_var(*s, (G.var_nest_level << SETFLAG_VARLVL_SHIFT) | SETFLAG_EXPORT);
2534                s++;
2535 next: ;
2536        }
2537        free(strings);
2538}
2539
2540
2541/*
2542 * Unicode helper
2543 */
2544static void reinit_unicode_for_hush(void)
2545{
2546        /* Unicode support should be activated even if LANG is set
2547         * _during_ shell execution, not only if it was set when
2548         * shell was started. Therefore, re-check LANG every time:
2549         */
2550        if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2551         || ENABLE_UNICODE_USING_LOCALE
2552        ) {
2553                const char *s = get_local_var_value("LC_ALL");
2554                if (!s) s = get_local_var_value("LC_CTYPE");
2555                if (!s) s = get_local_var_value("LANG");
2556                reinit_unicode(s);
2557        }
2558}
2559
2560/*
2561 * in_str support (strings, and "strings" read from files).
2562 */
2563
2564#if ENABLE_HUSH_INTERACTIVE
2565/* To test correct lineedit/interactive behavior, type from command line:
2566 *      echo $P\
2567 *      \
2568 *      AT\
2569 *      H\
2570 *      \
2571 * It exercises a lot of corner cases.
2572 */
2573static const char *setup_prompt_string(void)
2574{
2575        const char *prompt_str;
2576
2577        debug_printf_prompt("%s promptmode:%d\n", __func__, G.promptmode);
2578
2579# if ENABLE_FEATURE_EDITING_FANCY_PROMPT
2580        prompt_str = get_local_var_value(G.promptmode == 0 ? "PS1" : "PS2");
2581        if (!prompt_str)
2582                prompt_str = "";
2583# else
2584        prompt_str = "> "; /* if PS2, else... */
2585        if (G.promptmode == 0) { /* PS1 */
2586                /* No fancy prompts supported, (re)generate "CURDIR $ " by hand */
2587                free(G.PS1);
2588                /* bash uses $PWD value, even if it is set by user.
2589                 * It uses current dir only if PWD is unset.
2590                 * We always use current dir. */
2591                G.PS1 = xasprintf("%s %c ", get_cwd(0), (geteuid() != 0) ? '$' : '#');
2592        }
2593# endif
2594        debug_printf("prompt_str '%s'\n", prompt_str);
2595        return prompt_str;
2596}
2597static int get_user_input(struct in_str *i)
2598{
2599        int r;
2600        const char *prompt_str;
2601
2602        prompt_str = setup_prompt_string();
2603# if ENABLE_FEATURE_EDITING
2604        for (;;) {
2605                reinit_unicode_for_hush();
2606                if (G.flag_SIGINT) {
2607                        /* There was ^C'ed, make it look prettier: */
2608                        bb_putchar('\n');
2609                        G.flag_SIGINT = 0;
2610                }
2611                /* buglet: SIGINT will not make new prompt to appear _at once_,
2612                 * only after <Enter>. (^C works immediately) */
2613                r = read_line_input(G.line_input_state, prompt_str,
2614                                G.user_input_buf, CONFIG_FEATURE_EDITING_MAX_LEN-1
2615                );
2616                /* read_line_input intercepts ^C, "convert" it to SIGINT */
2617                if (r == 0)
2618                        raise(SIGINT);
2619                check_and_run_traps();
2620                if (r != 0 && !G.flag_SIGINT)
2621                        break;
2622                /* ^C or SIGINT: repeat */
2623                /* bash prints ^C even on real SIGINT (non-kbd generated) */
2624                write(STDOUT_FILENO, "^C", 2);
2625                G.last_exitcode = 128 + SIGINT;
2626        }
2627        if (r < 0) {
2628                /* EOF/error detected */
2629                i->p = NULL;
2630                i->peek_buf[0] = r = EOF;
2631                return r;
2632        }
2633        i->p = G.user_input_buf;
2634        return (unsigned char)*i->p++;
2635# else
2636        for (;;) {
2637                G.flag_SIGINT = 0;
2638                if (i->last_char == '\0' || i->last_char == '\n') {
2639                        /* Why check_and_run_traps here? Try this interactively:
2640                         * $ trap 'echo INT' INT; (sleep 2; kill -INT $$) &
2641                         * $ <[enter], repeatedly...>
2642                         * Without check_and_run_traps, handler never runs.
2643                         */
2644                        check_and_run_traps();
2645                        fputs(prompt_str, stdout);
2646                }
2647                fflush_all();
2648//FIXME: here ^C or SIGINT will have effect only after <Enter>
2649                r = hfgetc(i->file);
2650                /* In !ENABLE_FEATURE_EDITING we don't use read_line_input,
2651                 * no ^C masking happens during fgetc, no special code for ^C:
2652                 * it generates SIGINT as usual.
2653                 */
2654                check_and_run_traps();
2655                if (G.flag_SIGINT)
2656                        G.last_exitcode = 128 + SIGINT;
2657                if (r != '\0')
2658                        break;
2659        }
2660        return r;
2661# endif
2662}
2663/* This is the magic location that prints prompts
2664 * and gets data back from the user */
2665static int fgetc_interactive(struct in_str *i)
2666{
2667        int ch;
2668        /* If it's interactive stdin, get new line. */
2669        if (G_interactive_fd && i->file->is_stdin) {
2670                /* Returns first char (or EOF), the rest is in i->p[] */
2671                ch = get_user_input(i);
2672                G.promptmode = 1; /* PS2 */
2673                debug_printf_prompt("%s promptmode=%d\n", __func__, G.promptmode);
2674        } else {
2675                /* Not stdin: script file, sourced file, etc */
2676                do ch = hfgetc(i->file); while (ch == '\0');
2677        }
2678        return ch;
2679}
2680#else
2681static ALWAYS_INLINE int fgetc_interactive(struct in_str *i)
2682{
2683        int ch;
2684        do ch = hfgetc(i->file); while (ch == '\0');
2685        return ch;
2686}
2687#endif  /* INTERACTIVE */
2688
2689static int i_getch(struct in_str *i)
2690{
2691        int ch;
2692
2693        if (!i->file) {
2694                /* string-based in_str */
2695                ch = (unsigned char)*i->p;
2696                if (ch != '\0') {
2697                        i->p++;
2698                        i->last_char = ch;
2699                        return ch;
2700                }
2701                return EOF;
2702        }
2703
2704        /* FILE-based in_str */
2705
2706#if ENABLE_FEATURE_EDITING
2707        /* This can be stdin, check line editing char[] buffer */
2708        if (i->p && *i->p != '\0') {
2709                ch = (unsigned char)*i->p++;
2710                goto out;
2711        }
2712#endif
2713        /* peek_buf[] is an int array, not char. Can contain EOF. */
2714        ch = i->peek_buf[0];
2715        if (ch != 0) {
2716                int ch2 = i->peek_buf[1];
2717                i->peek_buf[0] = ch2;
2718                if (ch2 == 0) /* very likely, avoid redundant write */
2719                        goto out;
2720                i->peek_buf[1] = 0;
2721                goto out;
2722        }
2723
2724        ch = fgetc_interactive(i);
2725 out:
2726        debug_printf("file_get: got '%c' %d\n", ch, ch);
2727        i->last_char = ch;
2728#if ENABLE_HUSH_LINENO_VAR
2729        if (ch == '\n') {
2730                G.parse_lineno++;
2731                debug_printf_parse("G.parse_lineno++ = %u\n", G.parse_lineno);
2732        }
2733#endif
2734        return ch;
2735}
2736
2737static int i_peek(struct in_str *i)
2738{
2739        int ch;
2740
2741        if (!i->file) {
2742                /* string-based in_str */
2743                /* Doesn't report EOF on NUL. None of the callers care. */
2744                return (unsigned char)*i->p;
2745        }
2746
2747        /* FILE-based in_str */
2748
2749#if ENABLE_FEATURE_EDITING && ENABLE_HUSH_INTERACTIVE
2750        /* This can be stdin, check line editing char[] buffer */
2751        if (i->p && *i->p != '\0')
2752                return (unsigned char)*i->p;
2753#endif
2754        /* peek_buf[] is an int array, not char. Can contain EOF. */
2755        ch = i->peek_buf[0];
2756        if (ch != 0)
2757                return ch;
2758
2759        /* Need to get a new char */
2760        ch = fgetc_interactive(i);
2761        debug_printf("file_peek: got '%c' %d\n", ch, ch);
2762
2763        /* Save it by either rolling back line editing buffer, or in i->peek_buf[0] */
2764#if ENABLE_FEATURE_EDITING && ENABLE_HUSH_INTERACTIVE
2765        if (i->p) {
2766                i->p -= 1;
2767                return ch;
2768        }
2769#endif
2770        i->peek_buf[0] = ch;
2771        /*i->peek_buf[1] = 0; - already is */
2772        return ch;
2773}
2774
2775/* Only ever called if i_peek() was called, and did not return EOF.
2776 * IOW: we know the previous peek saw an ordinary char, not EOF, not NUL,
2777 * not end-of-line. Therefore we never need to read a new editing line here.
2778 */
2779static int i_peek2(struct in_str *i)
2780{
2781        int ch;
2782
2783        /* There are two cases when i->p[] buffer exists.
2784         * (1) it's a string in_str.
2785         * (2) It's a file, and we have a saved line editing buffer.
2786         * In both cases, we know that i->p[0] exists and not NUL, and
2787         * the peek2 result is in i->p[1].
2788         */
2789        if (i->p)
2790                return (unsigned char)i->p[1];
2791
2792        /* Now we know it is a file-based in_str. */
2793
2794        /* peek_buf[] is an int array, not char. Can contain EOF. */
2795        /* Is there 2nd char? */
2796        ch = i->peek_buf[1];
2797        if (ch == 0) {
2798                /* We did not read it yet, get it now */
2799                do ch = hfgetc(i->file); while (ch == '\0');
2800                i->peek_buf[1] = ch;
2801        }
2802
2803        debug_printf("file_peek2: got '%c' %d\n", ch, ch);
2804        return ch;
2805}
2806
2807static int i_getch_and_eat_bkslash_nl(struct in_str *input)
2808{
2809        for (;;) {
2810                int ch, ch2;
2811
2812                ch = i_getch(input);
2813                if (ch != '\\')
2814                        return ch;
2815                ch2 = i_peek(input);
2816                if (ch2 != '\n')
2817                        return ch;
2818                /* backslash+newline, skip it */
2819                i_getch(input);
2820        }
2821}
2822
2823/* Note: this function _eats_ \<newline> pairs, safe to use plain
2824 * i_getch() after it instead of i_getch_and_eat_bkslash_nl().
2825 */
2826static int i_peek_and_eat_bkslash_nl(struct in_str *input)
2827{
2828        for (;;) {
2829                int ch, ch2;
2830
2831                ch = i_peek(input);
2832                if (ch != '\\')
2833                        return ch;
2834                ch2 = i_peek2(input);
2835                if (ch2 != '\n')
2836                        return ch;
2837                /* backslash+newline, skip it */
2838                i_getch(input);
2839                i_getch(input);
2840        }
2841}
2842
2843static void setup_file_in_str(struct in_str *i, HFILE *fp)
2844{
2845        memset(i, 0, sizeof(*i));
2846        i->file = fp;
2847        /* i->p = NULL; */
2848}
2849
2850static void setup_string_in_str(struct in_str *i, const char *s)
2851{
2852        memset(i, 0, sizeof(*i));
2853        /*i->file = NULL */;
2854        i->p = s;
2855}
2856
2857
2858/*
2859 * o_string support
2860 */
2861#define B_CHUNK  (32 * sizeof(char*))
2862
2863static void o_reset_to_empty_unquoted(o_string *o)
2864{
2865        o->length = 0;
2866        o->has_quoted_part = 0;
2867        if (o->data)
2868                o->data[0] = '\0';
2869}
2870
2871static void o_free_and_set_NULL(o_string *o)
2872{
2873        free(o->data);
2874        memset(o, 0, sizeof(*o));
2875}
2876
2877static ALWAYS_INLINE void o_free(o_string *o)
2878{
2879        free(o->data);
2880}
2881
2882static void o_grow_by(o_string *o, int len)
2883{
2884        if (o->length + len > o->maxlen) {
2885                o->maxlen += (2 * len) | (B_CHUNK-1);
2886                o->data = xrealloc(o->data, 1 + o->maxlen);
2887        }
2888}
2889
2890static void o_addchr(o_string *o, int ch)
2891{
2892        debug_printf("o_addchr: '%c' o->length=%d o=%p\n", ch, o->length, o);
2893        if (o->length < o->maxlen) {
2894                /* likely. avoid o_grow_by() call */
2895 add:
2896                o->data[o->length] = ch;
2897                o->length++;
2898                o->data[o->length] = '\0';
2899                return;
2900        }
2901        o_grow_by(o, 1);
2902        goto add;
2903}
2904
2905#if 0
2906/* Valid only if we know o_string is not empty */
2907static void o_delchr(o_string *o)
2908{
2909        o->length--;
2910        o->data[o->length] = '\0';
2911}
2912#endif
2913
2914static void o_addblock(o_string *o, const char *str, int len)
2915{
2916        o_grow_by(o, len);
2917        ((char*)mempcpy(&o->data[o->length], str, len))[0] = '\0';
2918        o->length += len;
2919}
2920
2921static void o_addstr(o_string *o, const char *str)
2922{
2923        o_addblock(o, str, strlen(str));
2924}
2925
2926static void o_addstr_with_NUL(o_string *o, const char *str)
2927{
2928        o_addblock(o, str, strlen(str) + 1);
2929}
2930
2931#if !BB_MMU
2932static void nommu_addchr(o_string *o, int ch)
2933{
2934        if (o)
2935                o_addchr(o, ch);
2936}
2937#else
2938# define nommu_addchr(o, str) ((void)0)
2939#endif
2940
2941#if ENABLE_HUSH_MODE_X
2942static void x_mode_addchr(int ch)
2943{
2944        o_addchr(&G.x_mode_buf, ch);
2945}
2946static void x_mode_addstr(const char *str)
2947{
2948        o_addstr(&G.x_mode_buf, str);
2949}
2950static void x_mode_addblock(const char *str, int len)
2951{
2952        o_addblock(&G.x_mode_buf, str, len);
2953}
2954static void x_mode_prefix(void)
2955{
2956        int n = G.x_mode_depth;
2957        do x_mode_addchr('+'); while (--n >= 0);
2958}
2959static void x_mode_flush(void)
2960{
2961        int len = G.x_mode_buf.length;
2962        if (len <= 0)
2963                return;
2964        if (G.x_mode_fd > 0) {
2965                G.x_mode_buf.data[len] = '\n';
2966                full_write(G.x_mode_fd, G.x_mode_buf.data, len + 1);
2967        }
2968        G.x_mode_buf.length = 0;
2969}
2970#endif
2971
2972/*
2973 * HUSH_BRACE_EXPANSION code needs corresponding quoting on variable expansion side.
2974 * Currently, "v='{q,w}'; echo $v" erroneously expands braces in $v.
2975 * Apparently, on unquoted $v bash still does globbing
2976 * ("v='*.txt'; echo $v" prints all .txt files),
2977 * but NOT brace expansion! Thus, there should be TWO independent
2978 * quoting mechanisms on $v expansion side: one protects
2979 * $v from brace expansion, and other additionally protects "$v" against globbing.
2980 * We have only second one.
2981 */
2982
2983#if ENABLE_HUSH_BRACE_EXPANSION
2984# define MAYBE_BRACES "{}"
2985#else
2986# define MAYBE_BRACES ""
2987#endif
2988
2989/* My analysis of quoting semantics tells me that state information
2990 * is associated with a destination, not a source.
2991 */
2992static void o_addqchr(o_string *o, int ch)
2993{
2994        int sz = 1;
2995        char *found = strchr("*?[\\" MAYBE_BRACES, ch);
2996        if (found)
2997                sz++;
2998        o_grow_by(o, sz);
2999        if (found) {
3000                o->data[o->length] = '\\';
3001                o->length++;
3002        }
3003        o->data[o->length] = ch;
3004        o->length++;
3005        o->data[o->length] = '\0';
3006}
3007
3008static void o_addQchr(o_string *o, int ch)
3009{
3010        int sz = 1;
3011        if ((o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)
3012         && strchr("*?[\\" MAYBE_BRACES, ch)
3013        ) {
3014                sz++;
3015                o->data[o->length] = '\\';
3016                o->length++;
3017        }
3018        o_grow_by(o, sz);
3019        o->data[o->length] = ch;
3020        o->length++;
3021        o->data[o->length] = '\0';
3022}
3023
3024static void o_addqblock(o_string *o, const char *str, int len)
3025{
3026        while (len) {
3027                char ch;
3028                int sz;
3029                int ordinary_cnt = strcspn(str, "*?[\\" MAYBE_BRACES);
3030                if (ordinary_cnt > len) /* paranoia */
3031                        ordinary_cnt = len;
3032                o_addblock(o, str, ordinary_cnt);
3033                if (ordinary_cnt == len)
3034                        return; /* NUL is already added by o_addblock */
3035                str += ordinary_cnt;
3036                len -= ordinary_cnt + 1; /* we are processing + 1 char below */
3037
3038                ch = *str++;
3039                sz = 1;
3040                if (ch) { /* it is necessarily one of "*?[\\" MAYBE_BRACES */
3041                        sz++;
3042                        o->data[o->length] = '\\';
3043                        o->length++;
3044                }
3045                o_grow_by(o, sz);
3046                o->data[o->length] = ch;
3047                o->length++;
3048        }
3049        o->data[o->length] = '\0';
3050}
3051
3052static void o_addQblock(o_string *o, const char *str, int len)
3053{
3054        if (!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS)) {
3055                o_addblock(o, str, len);
3056                return;
3057        }
3058        o_addqblock(o, str, len);
3059}
3060
3061static void o_addQstr(o_string *o, const char *str)
3062{
3063        o_addQblock(o, str, strlen(str));
3064}
3065
3066/* A special kind of o_string for $VAR and `cmd` expansion.
3067 * It contains char* list[] at the beginning, which is grown in 16 element
3068 * increments. Actual string data starts at the next multiple of 16 * (char*).
3069 * list[i] contains an INDEX (int!) into this string data.
3070 * It means that if list[] needs to grow, data needs to be moved higher up
3071 * but list[i]'s need not be modified.
3072 * NB: remembering how many list[i]'s you have there is crucial.
3073 * o_finalize_list() operation post-processes this structure - calculates
3074 * and stores actual char* ptrs in list[]. Oh, it NULL terminates it as well.
3075 */
3076#if DEBUG_EXPAND || DEBUG_GLOB
3077static void debug_print_list(const char *prefix, o_string *o, int n)
3078{
3079        char **list = (char**)o->data;
3080        int string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
3081        int i = 0;
3082
3083        indent();
3084        fdprintf(2, "%s: list:%p n:%d string_start:%d length:%d maxlen:%d glob:%d quoted:%d escape:%d\n",
3085                        prefix, list, n, string_start, o->length, o->maxlen,
3086                        !!(o->o_expflags & EXP_FLAG_GLOB),
3087                        o->has_quoted_part,
3088                        !!(o->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
3089        while (i < n) {
3090                indent();
3091                fdprintf(2, " list[%d]=%d '%s' %p\n", i, (int)(uintptr_t)list[i],
3092                                o->data + (int)(uintptr_t)list[i] + string_start,
3093                                o->data + (int)(uintptr_t)list[i] + string_start);
3094                i++;
3095        }
3096        if (n) {
3097                const char *p = o->data + (int)(uintptr_t)list[n - 1] + string_start;
3098                indent();
3099                fdprintf(2, " total_sz:%ld\n", (long)((p + strlen(p) + 1) - o->data));
3100        }
3101}
3102#else
3103# define debug_print_list(prefix, o, n) ((void)0)
3104#endif
3105
3106/* n = o_save_ptr_helper(str, n) "starts new string" by storing an index value
3107 * in list[n] so that it points past last stored byte so far.
3108 * It returns n+1. */
3109static int o_save_ptr_helper(o_string *o, int n)
3110{
3111        char **list = (char**)o->data;
3112        int string_start;
3113        int string_len;
3114
3115        if (!o->has_empty_slot) {
3116                string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
3117                string_len = o->length - string_start;
3118                if (!(n & 0xf)) { /* 0, 0x10, 0x20...? */
3119                        debug_printf_list("list[%d]=%d string_start=%d (growing)\n", n, string_len, string_start);
3120                        /* list[n] points to string_start, make space for 16 more pointers */
3121                        o->maxlen += 0x10 * sizeof(list[0]);
3122                        o->data = xrealloc(o->data, o->maxlen + 1);
3123                        list = (char**)o->data;
3124                        memmove(list + n + 0x10, list + n, string_len);
3125                        /*
3126                         * expand_on_ifs() has a "previous argv[] ends in IFS?"
3127                         * check. (grep for -prev-ifs-check-).
3128                         * Ensure that argv[-1][last] is not garbage
3129                         * but zero bytes, to save index check there.
3130                         */
3131                        list[n + 0x10 - 1] = 0;
3132                        o->length += 0x10 * sizeof(list[0]);
3133                } else {
3134                        debug_printf_list("list[%d]=%d string_start=%d\n",
3135                                        n, string_len, string_start);
3136                }
3137        } else {
3138                /* We have empty slot at list[n], reuse without growth */
3139                string_start = ((n+1 + 0xf) & ~0xf) * sizeof(list[0]); /* NB: n+1! */
3140                string_len = o->length - string_start;
3141                debug_printf_list("list[%d]=%d string_start=%d (empty slot)\n",
3142                                n, string_len, string_start);
3143                o->has_empty_slot = 0;
3144        }
3145        o->has_quoted_part = 0;
3146        list[n] = (char*)(uintptr_t)string_len;
3147        return n + 1;
3148}
3149
3150/* "What was our last o_save_ptr'ed position (byte offset relative o->data)?" */
3151static int o_get_last_ptr(o_string *o, int n)
3152{
3153        char **list = (char**)o->data;
3154        int string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
3155
3156        return ((int)(uintptr_t)list[n-1]) + string_start;
3157}
3158
3159/*
3160 * Globbing routines.
3161 *
3162 * Most words in commands need to be globbed, even ones which are
3163 * (single or double) quoted. This stems from the possiblity of
3164 * constructs like "abc"* and 'abc'* - these should be globbed.
3165 * Having a different code path for fully-quoted strings ("abc",
3166 * 'abc') would only help performance-wise, but we still need
3167 * code for partially-quoted strings.
3168 *
3169 * Unfortunately, if we want to match bash and ash behavior in all cases,
3170 * the logic can't be "shell-syntax argument is first transformed
3171 * to a string, then globbed, and if globbing does not match anything,
3172 * it is used verbatim". Here are two examples where it fails:
3173 *
3174 *      echo 'b\*'?
3175 *
3176 * The globbing can't be avoided (because of '?' at the end).
3177 * The glob pattern is: b\\\*? - IOW, both \ and * are literals
3178 * and are glob-escaped. If this does not match, bash/ash print b\*?
3179 * - IOW: they "unbackslash" the glob pattern.
3180 * Now, look at this:
3181 *
3182 *      v='\\\*'; echo b$v?
3183 *
3184 * The glob pattern is the same here: b\\\*? - the unquoted $v expansion
3185 * should be used as glob pattern with no changes. However, if glob
3186 * does not match, bash/ash print b\\\*? - NOT THE SAME as first example!
3187 *
3188 * ash implements this by having an encoded representation of the word
3189 * to glob, which IS NOT THE SAME as the glob pattern - it has more data.
3190 * Glob pattern is derived from it. If glob fails, the decision what result
3191 * should be is made using that encoded representation. Not glob pattern.
3192 */
3193
3194#if ENABLE_HUSH_BRACE_EXPANSION
3195/* There in a GNU extension, GLOB_BRACE, but it is not usable:
3196 * first, it processes even {a} (no commas), second,
3197 * I didn't manage to make it return strings when they don't match
3198 * existing files. Need to re-implement it.
3199 */
3200
3201/* Helper */
3202static int glob_needed(const char *s)
3203{
3204        while (*s) {
3205                if (*s == '\\') {
3206                        if (!s[1])
3207                                return 0;
3208                        s += 2;
3209                        continue;
3210                }
3211                if (*s == '*' || *s == '[' || *s == '?' || *s == '{')
3212                        return 1;
3213                s++;
3214        }
3215        return 0;
3216}
3217/* Return pointer to next closing brace or to comma */
3218static const char *next_brace_sub(const char *cp)
3219{
3220        unsigned depth = 0;
3221        cp++;
3222        while (*cp != '\0') {
3223                if (*cp == '\\') {
3224                        if (*++cp == '\0')
3225                                break;
3226                        cp++;
3227                        continue;
3228                }
3229                if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0))
3230                        break;
3231                if (*cp++ == '{')
3232                        depth++;
3233        }
3234
3235        return *cp != '\0' ? cp : NULL;
3236}
3237/* Recursive brace globber. Note: may garble pattern[]. */
3238static int glob_brace(char *pattern, o_string *o, int n)
3239{
3240        char *new_pattern_buf;
3241        const char *begin;
3242        const char *next;
3243        const char *rest;
3244        const char *p;
3245        size_t rest_len;
3246
3247        debug_printf_glob("glob_brace('%s')\n", pattern);
3248
3249        begin = pattern;
3250        while (1) {
3251                if (*begin == '\0')
3252                        goto simple_glob;
3253                if (*begin == '{') {
3254                        /* Find the first sub-pattern and at the same time
3255                         * find the rest after the closing brace */
3256                        next = next_brace_sub(begin);
3257                        if (next == NULL) {
3258                                /* An illegal expression */
3259                                goto simple_glob;
3260                        }
3261                        if (*next == '}') {
3262                                /* "{abc}" with no commas - illegal
3263                                 * brace expr, disregard and skip it */
3264                                begin = next + 1;
3265                                continue;
3266                        }
3267                        break;
3268                }
3269                if (*begin == '\\' && begin[1] != '\0')
3270                        begin++;
3271                begin++;
3272        }
3273        debug_printf_glob("begin:%s\n", begin);
3274        debug_printf_glob("next:%s\n", next);
3275
3276        /* Now find the end of the whole brace expression */
3277        rest = next;
3278        while (*rest != '}') {
3279                rest = next_brace_sub(rest);
3280                if (rest == NULL) {
3281                        /* An illegal expression */
3282                        goto simple_glob;
3283                }
3284                debug_printf_glob("rest:%s\n", rest);
3285        }
3286        rest_len = strlen(++rest) + 1;
3287
3288        /* We are sure the brace expression is well-formed */
3289
3290        /* Allocate working buffer large enough for our work */
3291        new_pattern_buf = xmalloc(strlen(pattern));
3292
3293        /* We have a brace expression.  BEGIN points to the opening {,
3294         * NEXT points past the terminator of the first element, and REST
3295         * points past the final }.  We will accumulate result names from
3296         * recursive runs for each brace alternative in the buffer using
3297         * GLOB_APPEND.  */
3298
3299        p = begin + 1;
3300        while (1) {
3301                /* Construct the new glob expression */
3302                memcpy(
3303                        mempcpy(
3304                                mempcpy(new_pattern_buf,
3305                                        /* We know the prefix for all sub-patterns */
3306                                        pattern, begin - pattern),
3307                                p, next - p),
3308                        rest, rest_len);
3309
3310                /* Note: glob_brace() may garble new_pattern_buf[].
3311                 * That's why we re-copy prefix every time (1st memcpy above).
3312                 */
3313                n = glob_brace(new_pattern_buf, o, n);
3314                if (*next == '}') {
3315                        /* We saw the last entry */
3316                        break;
3317                }
3318                p = next + 1;
3319                next = next_brace_sub(next);
3320        }
3321        free(new_pattern_buf);
3322        return n;
3323
3324 simple_glob:
3325        {
3326                int gr;
3327                glob_t globdata;
3328
3329                memset(&globdata, 0, sizeof(globdata));
3330                gr = glob(pattern, 0, NULL, &globdata);
3331                debug_printf_glob("glob('%s'):%d\n", pattern, gr);
3332                if (gr != 0) {
3333                        if (gr == GLOB_NOMATCH) {
3334                                globfree(&globdata);
3335                                /* NB: garbles parameter */
3336                                unbackslash(pattern);
3337                                o_addstr_with_NUL(o, pattern);
3338                                debug_printf_glob("glob pattern '%s' is literal\n", pattern);
3339                                return o_save_ptr_helper(o, n);
3340                        }
3341                        if (gr == GLOB_NOSPACE)
3342                                bb_die_memory_exhausted();
3343                        /* GLOB_ABORTED? Only happens with GLOB_ERR flag,
3344                         * but we didn't specify it. Paranoia again. */
3345                        bb_error_msg_and_die("glob error %d on '%s'", gr, pattern);
3346                }
3347                if (globdata.gl_pathv && globdata.gl_pathv[0]) {
3348                        char **argv = globdata.gl_pathv;
3349                        while (1) {
3350                                o_addstr_with_NUL(o, *argv);
3351                                n = o_save_ptr_helper(o, n);
3352                                argv++;
3353                                if (!*argv)
3354                                        break;
3355                        }
3356                }
3357                globfree(&globdata);
3358        }
3359        return n;
3360}
3361/* Performs globbing on last list[],
3362 * saving each result as a new list[].
3363 */
3364static int perform_glob(o_string *o, int n)
3365{
3366        char *pattern, *copy;
3367
3368        debug_printf_glob("start perform_glob: n:%d o->data:%p\n", n, o->data);
3369        if (!o->data)
3370                return o_save_ptr_helper(o, n);
3371        pattern = o->data + o_get_last_ptr(o, n);
3372        debug_printf_glob("glob pattern '%s'\n", pattern);
3373        if (!glob_needed(pattern)) {
3374                /* unbackslash last string in o in place, fix length */
3375                o->length = unbackslash(pattern) - o->data;
3376                debug_printf_glob("glob pattern '%s' is literal\n", pattern);
3377                return o_save_ptr_helper(o, n);
3378        }
3379
3380        copy = xstrdup(pattern);
3381        /* "forget" pattern in o */
3382        o->length = pattern - o->data;
3383        n = glob_brace(copy, o, n);
3384        free(copy);
3385        if (DEBUG_GLOB)
3386                debug_print_list("perform_glob returning", o, n);
3387        return n;
3388}
3389
3390#else /* !HUSH_BRACE_EXPANSION */
3391
3392/* Helper */
3393static int glob_needed(const char *s)
3394{
3395        while (*s) {
3396                if (*s == '\\') {
3397                        if (!s[1])
3398                                return 0;
3399                        s += 2;
3400                        continue;
3401                }
3402                if (*s == '*' || *s == '[' || *s == '?')
3403                        return 1;
3404                s++;
3405        }
3406        return 0;
3407}
3408/* Performs globbing on last list[],
3409 * saving each result as a new list[].
3410 */
3411static int perform_glob(o_string *o, int n)
3412{
3413        glob_t globdata;
3414        int gr;
3415        char *pattern;
3416
3417        debug_printf_glob("start perform_glob: n:%d o->data:%p\n", n, o->data);
3418        if (!o->data)
3419                return o_save_ptr_helper(o, n);
3420        pattern = o->data + o_get_last_ptr(o, n);
3421        debug_printf_glob("glob pattern '%s'\n", pattern);
3422        if (!glob_needed(pattern)) {
3423 literal:
3424                /* unbackslash last string in o in place, fix length */
3425                o->length = unbackslash(pattern) - o->data;
3426                debug_printf_glob("glob pattern '%s' is literal\n", pattern);
3427                return o_save_ptr_helper(o, n);
3428        }
3429
3430        memset(&globdata, 0, sizeof(globdata));
3431        /* Can't use GLOB_NOCHECK: it does not unescape the string.
3432         * If we glob "*.\*" and don't find anything, we need
3433         * to fall back to using literal "*.*", but GLOB_NOCHECK
3434         * will return "*.\*"!
3435         */
3436        gr = glob(pattern, 0, NULL, &globdata);
3437        debug_printf_glob("glob('%s'):%d\n", pattern, gr);
3438        if (gr != 0) {
3439                if (gr == GLOB_NOMATCH) {
3440                        globfree(&globdata);
3441                        goto literal;
3442                }
3443                if (gr == GLOB_NOSPACE)
3444                        bb_die_memory_exhausted();
3445                /* GLOB_ABORTED? Only happens with GLOB_ERR flag,
3446                 * but we didn't specify it. Paranoia again. */
3447                bb_error_msg_and_die("glob error %d on '%s'", gr, pattern);
3448        }
3449        if (globdata.gl_pathv && globdata.gl_pathv[0]) {
3450                char **argv = globdata.gl_pathv;
3451                /* "forget" pattern in o */
3452                o->length = pattern - o->data;
3453                while (1) {
3454                        o_addstr_with_NUL(o, *argv);
3455                        n = o_save_ptr_helper(o, n);
3456                        argv++;
3457                        if (!*argv)
3458                                break;
3459                }
3460        }
3461        globfree(&globdata);
3462        if (DEBUG_GLOB)
3463                debug_print_list("perform_glob returning", o, n);
3464        return n;
3465}
3466
3467#endif /* !HUSH_BRACE_EXPANSION */
3468
3469/* If o->o_expflags & EXP_FLAG_GLOB, glob the string so far remembered.
3470 * Otherwise, just finish current list[] and start new */
3471static int o_save_ptr(o_string *o, int n)
3472{
3473        if (o->o_expflags & EXP_FLAG_GLOB) {
3474                /* If o->has_empty_slot, list[n] was already globbed
3475                 * (if it was requested back then when it was filled)
3476                 * so don't do that again! */
3477                if (!o->has_empty_slot)
3478                        return perform_glob(o, n); /* o_save_ptr_helper is inside */
3479        }
3480        return o_save_ptr_helper(o, n);
3481}
3482
3483/* "Please convert list[n] to real char* ptrs, and NULL terminate it." */
3484static char **o_finalize_list(o_string *o, int n)
3485{
3486        char **list;
3487        int string_start;
3488
3489        if (DEBUG_EXPAND)
3490                debug_print_list("finalized", o, n);
3491        debug_printf_expand("finalized n:%d\n", n);
3492        list = (char**)o->data;
3493        string_start = ((n + 0xf) & ~0xf) * sizeof(list[0]);
3494        list[--n] = NULL;
3495        while (n) {
3496                n--;
3497                list[n] = o->data + (int)(uintptr_t)list[n] + string_start;
3498        }
3499        return list;
3500}
3501
3502static void free_pipe_list(struct pipe *pi);
3503
3504/* Returns pi->next - next pipe in the list */
3505static struct pipe *free_pipe(struct pipe *pi)
3506{
3507        struct pipe *next;
3508        int i;
3509
3510        debug_printf_clean("free_pipe (pid %d)\n", getpid());
3511        for (i = 0; i < pi->num_cmds; i++) {
3512                struct command *command;
3513                struct redir_struct *r, *rnext;
3514
3515                command = &pi->cmds[i];
3516                debug_printf_clean("  command %d:\n", i);
3517                if (command->argv) {
3518                        if (DEBUG_CLEAN) {
3519                                int a;
3520                                char **p;
3521                                for (a = 0, p = command->argv; *p; a++, p++) {
3522                                        debug_printf_clean("   argv[%d] = %s\n", a, *p);
3523                                }
3524                        }
3525                        free_strings(command->argv);
3526                        //command->argv = NULL;
3527                }
3528                /* not "else if": on syntax error, we may have both! */
3529                if (command->group) {
3530                        debug_printf_clean("   begin group (cmd_type:%d)\n",
3531                                        command->cmd_type);
3532                        free_pipe_list(command->group);
3533                        debug_printf_clean("   end group\n");
3534                        //command->group = NULL;
3535                }
3536                /* else is crucial here.
3537                 * If group != NULL, child_func is meaningless */
3538#if ENABLE_HUSH_FUNCTIONS
3539                else if (command->child_func) {
3540                        debug_printf_exec("cmd %p releases child func at %p\n", command, command->child_func);
3541                        command->child_func->parent_cmd = NULL;
3542                }
3543#endif
3544#if !BB_MMU
3545                free(command->group_as_string);
3546                //command->group_as_string = NULL;
3547#endif
3548                for (r = command->redirects; r; r = rnext) {
3549                        debug_printf_clean("   redirect %d%s",
3550                                        r->rd_fd, redir_table[r->rd_type].descrip);
3551                        /* guard against the case >$FOO, where foo is unset or blank */
3552                        if (r->rd_filename) {
3553                                debug_printf_clean(" fname:'%s'\n", r->rd_filename);
3554                                free(r->rd_filename);
3555                                //r->rd_filename = NULL;
3556                        }
3557                        debug_printf_clean(" rd_dup:%d\n", r->rd_dup);
3558                        rnext = r->next;
3559                        free(r);
3560                }
3561                //command->redirects = NULL;
3562        }
3563        free(pi->cmds);   /* children are an array, they get freed all at once */
3564        //pi->cmds = NULL;
3565#if ENABLE_HUSH_JOB
3566        free(pi->cmdtext);
3567        //pi->cmdtext = NULL;
3568#endif
3569
3570        next = pi->next;
3571        free(pi);
3572        return next;
3573}
3574
3575static void free_pipe_list(struct pipe *pi)
3576{
3577        while (pi) {
3578#if HAS_KEYWORDS
3579                debug_printf_clean("pipe reserved word %d\n", pi->res_word);
3580#endif
3581                debug_printf_clean("pipe followup code %d\n", pi->followup);
3582                pi = free_pipe(pi);
3583        }
3584}
3585
3586
3587/*** Parsing routines ***/
3588
3589#ifndef debug_print_tree
3590static void debug_print_tree(struct pipe *pi, int lvl)
3591{
3592        static const char *const PIPE[] = {
3593                [PIPE_SEQ] = "SEQ",
3594                [PIPE_AND] = "AND",
3595                [PIPE_OR ] = "OR" ,
3596                [PIPE_BG ] = "BG" ,
3597        };
3598        static const char *RES[] = {
3599                [RES_NONE ] = "NONE" ,
3600# if ENABLE_HUSH_IF
3601                [RES_IF   ] = "IF"   ,
3602                [RES_THEN ] = "THEN" ,
3603                [RES_ELIF ] = "ELIF" ,
3604                [RES_ELSE ] = "ELSE" ,
3605                [RES_FI   ] = "FI"   ,
3606# endif
3607# if ENABLE_HUSH_LOOPS
3608                [RES_FOR  ] = "FOR"  ,
3609                [RES_WHILE] = "WHILE",
3610                [RES_UNTIL] = "UNTIL",
3611                [RES_DO   ] = "DO"   ,
3612                [RES_DONE ] = "DONE" ,
3613# endif
3614# if ENABLE_HUSH_LOOPS || ENABLE_HUSH_CASE
3615                [RES_IN   ] = "IN"   ,
3616# endif
3617# if ENABLE_HUSH_CASE
3618                [RES_CASE ] = "CASE" ,
3619                [RES_CASE_IN ] = "CASE_IN" ,
3620                [RES_MATCH] = "MATCH",
3621                [RES_CASE_BODY] = "CASE_BODY",
3622                [RES_ESAC ] = "ESAC" ,
3623# endif
3624                [RES_XXXX ] = "XXXX" ,
3625                [RES_SNTX ] = "SNTX" ,
3626        };
3627        static const char *const CMDTYPE[] = {
3628                "{}",
3629                "()",
3630                "[noglob]",
3631# if ENABLE_HUSH_FUNCTIONS
3632                "func()",
3633# endif
3634        };
3635
3636        int pin, prn;
3637
3638        pin = 0;
3639        while (pi) {
3640                fdprintf(2, "%*spipe %d %sres_word=%s followup=%d %s\n",
3641                                lvl*2, "",
3642                                pin,
3643                                (IF_HAS_KEYWORDS(pi->pi_inverted ? "! " :) ""),
3644                                RES[pi->res_word],
3645                                pi->followup, PIPE[pi->followup]
3646                );
3647                prn = 0;
3648                while (prn < pi->num_cmds) {
3649                        struct command *command = &pi->cmds[prn];
3650                        char **argv = command->argv;
3651
3652                        fdprintf(2, "%*s cmd %d assignment_cnt:%d",
3653                                        lvl*2, "", prn,
3654                                        command->assignment_cnt);
3655#if ENABLE_HUSH_LINENO_VAR
3656                        fdprintf(2, " LINENO:%u", command->lineno);
3657#endif
3658                        if (command->group) {
3659                                fdprintf(2, " group %s: (argv=%p)%s%s\n",
3660                                                CMDTYPE[command->cmd_type],
3661                                                argv
3662# if !BB_MMU
3663                                                , " group_as_string:", command->group_as_string
3664# else
3665                                                , "", ""
3666# endif
3667                                );
3668                                debug_print_tree(command->group, lvl+1);
3669                                prn++;
3670                                continue;
3671                        }
3672                        if (argv) while (*argv) {
3673                                fdprintf(2, " '%s'", *argv);
3674                                argv++;
3675                        }
3676                        if (command->redirects)
3677                                fdprintf(2, " {redir}");
3678                        fdprintf(2, "\n");
3679                        prn++;
3680                }
3681                pi = pi->next;
3682                pin++;
3683        }
3684}
3685#endif /* debug_print_tree */
3686
3687static struct pipe *new_pipe(void)
3688{
3689        struct pipe *pi;
3690        pi = xzalloc(sizeof(struct pipe));
3691        /*pi->res_word = RES_NONE; - RES_NONE is 0 anyway */
3692        return pi;
3693}
3694
3695/* Command (member of a pipe) is complete, or we start a new pipe
3696 * if ctx->command is NULL.
3697 * No errors possible here.
3698 */
3699static int done_command(struct parse_context *ctx)
3700{
3701        /* The command is really already in the pipe structure, so
3702         * advance the pipe counter and make a new, null command. */
3703        struct pipe *pi = ctx->pipe;
3704        struct command *command = ctx->command;
3705
3706#if 0   /* Instead we emit error message at run time */
3707        if (ctx->pending_redirect) {
3708                /* For example, "cmd >" (no filename to redirect to) */
3709                syntax_error("invalid redirect");
3710                ctx->pending_redirect = NULL;
3711        }
3712#endif
3713
3714        if (command) {
3715                if (IS_NULL_CMD(command)) {
3716                        debug_printf_parse("done_command: skipping null cmd, num_cmds=%d\n", pi->num_cmds);
3717                        goto clear_and_ret;
3718                }
3719                pi->num_cmds++;
3720                debug_printf_parse("done_command: ++num_cmds=%d\n", pi->num_cmds);
3721                //debug_print_tree(ctx->list_head, 20);
3722        } else {
3723                debug_printf_parse("done_command: initializing, num_cmds=%d\n", pi->num_cmds);
3724        }
3725
3726        /* Only real trickiness here is that the uncommitted
3727         * command structure is not counted in pi->num_cmds. */
3728        pi->cmds = xrealloc(pi->cmds, sizeof(*pi->cmds) * (pi->num_cmds+1));
3729        ctx->command = command = &pi->cmds[pi->num_cmds];
3730 clear_and_ret:
3731        memset(command, 0, sizeof(*command));
3732#if ENABLE_HUSH_LINENO_VAR
3733        command->lineno = G.parse_lineno;
3734        debug_printf_parse("command->lineno = G.parse_lineno (%u)\n", G.parse_lineno);
3735#endif
3736        return pi->num_cmds; /* used only for 0/nonzero check */
3737}
3738
3739static void done_pipe(struct parse_context *ctx, pipe_style type)
3740{
3741        int not_null;
3742
3743        debug_printf_parse("done_pipe entered, followup %d\n", type);
3744        /* Close previous command */
3745        not_null = done_command(ctx);
3746#if HAS_KEYWORDS
3747        ctx->pipe->pi_inverted = ctx->ctx_inverted;
3748        ctx->ctx_inverted = 0;
3749        ctx->pipe->res_word = ctx->ctx_res_w;
3750#endif
3751        if (type == PIPE_BG && ctx->list_head != ctx->pipe) {
3752                /* Necessary since && and || have precedence over &:
3753                 * "cmd1 && cmd2 &" must spawn both cmds, not only cmd2,
3754                 * in a backgrounded subshell.
3755                 */
3756                struct pipe *pi;
3757                struct command *command;
3758
3759                /* Is this actually this construct, all pipes end with && or ||? */
3760                pi = ctx->list_head;
3761                while (pi != ctx->pipe) {
3762                        if (pi->followup != PIPE_AND && pi->followup != PIPE_OR)
3763                                goto no_conv;
3764                        pi = pi->next;
3765                }
3766
3767                debug_printf_parse("BG with more than one pipe, converting to { p1 &&...pN; } &\n");
3768                pi->followup = PIPE_SEQ; /* close pN _not_ with "&"! */
3769                pi = xzalloc(sizeof(*pi));
3770                pi->followup = PIPE_BG;
3771                pi->num_cmds = 1;
3772                pi->cmds = xzalloc(sizeof(pi->cmds[0]));
3773                command = &pi->cmds[0];
3774                if (CMD_NORMAL != 0) /* "if xzalloc didn't do that already" */
3775                        command->cmd_type = CMD_NORMAL;
3776                command->group = ctx->list_head;
3777#if !BB_MMU
3778                command->group_as_string = xstrndup(
3779                            ctx->as_string.data,
3780                            ctx->as_string.length - 1 /* do not copy last char, "&" */
3781                );
3782#endif
3783                /* Replace all pipes in ctx with one newly created */
3784                ctx->list_head = ctx->pipe = pi;
3785        } else {
3786 no_conv:
3787                ctx->pipe->followup = type;
3788        }
3789
3790        /* Without this check, even just <enter> on command line generates
3791         * tree of three NOPs (!). Which is harmless but annoying.
3792         * IOW: it is safe to do it unconditionally. */
3793        if (not_null
3794#if ENABLE_HUSH_IF
3795         || ctx->ctx_res_w == RES_FI
3796#endif
3797#if ENABLE_HUSH_LOOPS
3798         || ctx->ctx_res_w == RES_DONE
3799         || ctx->ctx_res_w == RES_FOR
3800         || ctx->ctx_res_w == RES_IN
3801#endif
3802#if ENABLE_HUSH_CASE
3803         || ctx->ctx_res_w == RES_ESAC
3804#endif
3805        ) {
3806                struct pipe *new_p;
3807                debug_printf_parse("done_pipe: adding new pipe: "
3808                                "not_null:%d ctx->ctx_res_w:%d\n",
3809                                not_null, ctx->ctx_res_w);
3810                new_p = new_pipe();
3811                ctx->pipe->next = new_p;
3812                ctx->pipe = new_p;
3813                /* RES_THEN, RES_DO etc are "sticky" -
3814                 * they remain set for pipes inside if/while.
3815                 * This is used to control execution.
3816                 * RES_FOR and RES_IN are NOT sticky (needed to support
3817                 * cases where variable or value happens to match a keyword):
3818                 */
3819#if ENABLE_HUSH_LOOPS
3820                if (ctx->ctx_res_w == RES_FOR
3821                 || ctx->ctx_res_w == RES_IN)
3822                        ctx->ctx_res_w = RES_NONE;
3823#endif
3824#if ENABLE_HUSH_CASE
3825                if (ctx->ctx_res_w == RES_MATCH)
3826                        ctx->ctx_res_w = RES_CASE_BODY;
3827                if (ctx->ctx_res_w == RES_CASE)
3828                        ctx->ctx_res_w = RES_CASE_IN;
3829#endif
3830                ctx->command = NULL; /* trick done_command below */
3831                /* Create the memory for command, roughly:
3832                 * ctx->pipe->cmds = new struct command;
3833                 * ctx->command = &ctx->pipe->cmds[0];
3834                 */
3835                done_command(ctx);
3836                //debug_print_tree(ctx->list_head, 10);
3837        }
3838        debug_printf_parse("done_pipe return\n");
3839}
3840
3841static void initialize_context(struct parse_context *ctx)
3842{
3843        memset(ctx, 0, sizeof(*ctx));
3844        if (MAYBE_ASSIGNMENT != 0)
3845                ctx->is_assignment = MAYBE_ASSIGNMENT;
3846        ctx->pipe = ctx->list_head = new_pipe();
3847        /* Create the memory for command, roughly:
3848         * ctx->pipe->cmds = new struct command;
3849         * ctx->command = &ctx->pipe->cmds[0];
3850         */
3851        done_command(ctx);
3852}
3853
3854/* If a reserved word is found and processed, parse context is modified
3855 * and 1 is returned.
3856 */
3857#if HAS_KEYWORDS
3858struct reserved_combo {
3859        char literal[6];
3860        unsigned char res;
3861        unsigned char assignment_flag;
3862        int flag;
3863};
3864enum {
3865        FLAG_END   = (1 << RES_NONE ),
3866# if ENABLE_HUSH_IF
3867        FLAG_IF    = (1 << RES_IF   ),
3868        FLAG_THEN  = (1 << RES_THEN ),
3869        FLAG_ELIF  = (1 << RES_ELIF ),
3870        FLAG_ELSE  = (1 << RES_ELSE ),
3871        FLAG_FI    = (1 << RES_FI   ),
3872# endif
3873# if ENABLE_HUSH_LOOPS
3874        FLAG_FOR   = (1 << RES_FOR  ),
3875        FLAG_WHILE = (1 << RES_WHILE),
3876        FLAG_UNTIL = (1 << RES_UNTIL),
3877        FLAG_DO    = (1 << RES_DO   ),
3878        FLAG_DONE  = (1 << RES_DONE ),
3879        FLAG_IN    = (1 << RES_IN   ),
3880# endif
3881# if ENABLE_HUSH_CASE
3882        FLAG_MATCH = (1 << RES_MATCH),
3883        FLAG_ESAC  = (1 << RES_ESAC ),
3884# endif
3885        FLAG_START = (1 << RES_XXXX ),
3886};
3887
3888static const struct reserved_combo* match_reserved_word(o_string *word)
3889{
3890        /* Mostly a list of accepted follow-up reserved words.
3891         * FLAG_END means we are done with the sequence, and are ready
3892         * to turn the compound list into a command.
3893         * FLAG_START means the word must start a new compound list.
3894         */
3895        static const struct reserved_combo reserved_list[] = {
3896# if ENABLE_HUSH_IF
3897                { "!",     RES_NONE,  NOT_ASSIGNMENT  , 0 },
3898                { "if",    RES_IF,    MAYBE_ASSIGNMENT, FLAG_THEN | FLAG_START },
3899                { "then",  RES_THEN,  MAYBE_ASSIGNMENT, FLAG_ELIF | FLAG_ELSE | FLAG_FI },
3900                { "elif",  RES_ELIF,  MAYBE_ASSIGNMENT, FLAG_THEN },
3901                { "else",  RES_ELSE,  MAYBE_ASSIGNMENT, FLAG_FI   },
3902                { "fi",    RES_FI,    NOT_ASSIGNMENT  , FLAG_END  },
3903# endif
3904# if ENABLE_HUSH_LOOPS
3905                { "for",   RES_FOR,   NOT_ASSIGNMENT  , FLAG_IN | FLAG_DO | FLAG_START },
3906                { "while", RES_WHILE, MAYBE_ASSIGNMENT, FLAG_DO | FLAG_START },
3907                { "until", RES_UNTIL, MAYBE_ASSIGNMENT, FLAG_DO | FLAG_START },
3908                { "in",    RES_IN,    NOT_ASSIGNMENT  , FLAG_DO   },
3909                { "do",    RES_DO,    MAYBE_ASSIGNMENT, FLAG_DONE },
3910                { "done",  RES_DONE,  NOT_ASSIGNMENT  , FLAG_END  },
3911# endif
3912# if ENABLE_HUSH_CASE
3913                { "case",  RES_CASE,  NOT_ASSIGNMENT  , FLAG_MATCH | FLAG_START },
3914                { "esac",  RES_ESAC,  NOT_ASSIGNMENT  , FLAG_END  },
3915# endif
3916        };
3917        const struct reserved_combo *r;
3918
3919        for (r = reserved_list; r < reserved_list + ARRAY_SIZE(reserved_list); r++) {
3920                if (strcmp(word->data, r->literal) == 0)
3921                        return r;
3922        }
3923        return NULL;
3924}
3925/* Return NULL: not a keyword, else: keyword
3926 */
3927static const struct reserved_combo* reserved_word(struct parse_context *ctx)
3928{
3929# if ENABLE_HUSH_CASE
3930        static const struct reserved_combo reserved_match = {
3931                "",        RES_MATCH, NOT_ASSIGNMENT , FLAG_MATCH | FLAG_ESAC
3932        };
3933# endif
3934        const struct reserved_combo *r;
3935
3936        if (ctx->word.has_quoted_part)
3937                return 0;
3938        r = match_reserved_word(&ctx->word);
3939        if (!r)
3940                return r; /* NULL */
3941
3942        debug_printf("found reserved word %s, res %d\n", r->literal, r->res);
3943# if ENABLE_HUSH_CASE
3944        if (r->res == RES_IN && ctx->ctx_res_w == RES_CASE_IN) {
3945                /* "case word IN ..." - IN part starts first MATCH part */
3946                r = &reserved_match;
3947        } else
3948# endif
3949        if (r->flag == 0) { /* '!' */
3950                if (ctx->ctx_inverted) { /* bash doesn't accept '! ! true' */
3951                        syntax_error("! ! command");
3952                        ctx->ctx_res_w = RES_SNTX;
3953                }
3954                ctx->ctx_inverted = 1;
3955                return r;
3956        }
3957        if (r->flag & FLAG_START) {
3958                struct parse_context *old;
3959
3960                old = xmemdup(ctx, sizeof(*ctx));
3961                debug_printf_parse("push stack %p\n", old);
3962                initialize_context(ctx);
3963                ctx->stack = old;
3964        } else if (/*ctx->ctx_res_w == RES_NONE ||*/ !(ctx->old_flag & (1 << r->res))) {
3965                syntax_error_at(ctx->word.data);
3966                ctx->ctx_res_w = RES_SNTX;
3967                return r;
3968        } else {
3969                /* "{...} fi" is ok. "{...} if" is not
3970                 * Example:
3971                 * if { echo foo; } then { echo bar; } fi */
3972                if (ctx->command->group)
3973                        done_pipe(ctx, PIPE_SEQ);
3974        }
3975
3976        ctx->ctx_res_w = r->res;
3977        ctx->old_flag = r->flag;
3978        ctx->is_assignment = r->assignment_flag;
3979        debug_printf_parse("ctx->is_assignment='%s'\n", assignment_flag[ctx->is_assignment]);
3980
3981        if (ctx->old_flag & FLAG_END) {
3982                struct parse_context *old;
3983
3984                done_pipe(ctx, PIPE_SEQ);
3985                debug_printf_parse("pop stack %p\n", ctx->stack);
3986                old = ctx->stack;
3987                old->command->group = ctx->list_head;
3988                old->command->cmd_type = CMD_NORMAL;
3989# if !BB_MMU
3990                /* At this point, the compound command's string is in
3991                 * ctx->as_string... except for the leading keyword!
3992                 * Consider this example: "echo a | if true; then echo a; fi"
3993                 * ctx->as_string will contain "true; then echo a; fi",
3994                 * with "if " remaining in old->as_string!
3995                 */
3996                {
3997                        char *str;
3998                        int len = old->as_string.length;
3999                        /* Concatenate halves */
4000                        o_addstr(&old->as_string, ctx->as_string.data);
4001                        o_free(&ctx->as_string);
4002                        /* Find where leading keyword starts in first half */
4003                        str = old->as_string.data + len;
4004                        if (str > old->as_string.data)
4005                                str--; /* skip whitespace after keyword */
4006                        while (str > old->as_string.data && isalpha(str[-1]))
4007                                str--;
4008                        /* Ugh, we're done with this horrid hack */
4009                        old->command->group_as_string = xstrdup(str);
4010                        debug_printf_parse("pop, remembering as:'%s'\n",
4011                                        old->command->group_as_string);
4012                }
4013# endif
4014                *ctx = *old;   /* physical copy */
4015                free(old);
4016        }
4017        return r;
4018}
4019#endif /* HAS_KEYWORDS */
4020
4021/* Word is complete, look at it and update parsing context.
4022 * Normal return is 0. Syntax errors return 1.
4023 * Note: on return, word is reset, but not o_free'd!
4024 */
4025static int done_word(struct parse_context *ctx)
4026{
4027        struct command *command = ctx->command;
4028
4029        debug_printf_parse("done_word entered: '%s' %p\n", ctx->word.data, command);
4030        if (ctx->word.length == 0 && !ctx->word.has_quoted_part) {
4031                debug_printf_parse("done_word return 0: true null, ignored\n");
4032                return 0;
4033        }
4034
4035        if (ctx->pending_redirect) {
4036                /* We do not glob in e.g. >*.tmp case. bash seems to glob here
4037                 * only if run as "bash", not "sh" */
4038                /* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
4039                 * "2.7 Redirection
4040                 * If the redirection operator is "<<" or "<<-", the word
4041                 * that follows the redirection operator shall be
4042                 * subjected to quote removal; it is unspecified whether
4043                 * any of the other expansions occur. For the other
4044                 * redirection operators, the word that follows the
4045                 * redirection operator shall be subjected to tilde
4046                 * expansion, parameter expansion, command substitution,
4047                 * arithmetic expansion, and quote removal.
4048                 * Pathname expansion shall not be performed
4049                 * on the word by a non-interactive shell; an interactive
4050                 * shell may perform it, but shall do so only when
4051                 * the expansion would result in one word."
4052                 */
4053//bash does not do parameter/command substitution or arithmetic expansion
4054//for _heredoc_ redirection word: these constructs look for exact eof marker
4055// as written:
4056// <<EOF$t
4057// <<EOF$((1))
4058// <<EOF`true`  [this case also makes heredoc "quoted", a-la <<"EOF". Probably bash-4.3.43 bug]
4059
4060                ctx->pending_redirect->rd_filename = xstrdup(ctx->word.data);
4061                /* Cater for >\file case:
4062                 * >\a creates file a; >\\a, >"\a", >"\\a" create file \a
4063                 * Same with heredocs:
4064                 * for <<\H delim is H; <<\\H, <<"\H", <<"\\H" - \H
4065                 */
4066                if (ctx->pending_redirect->rd_type == REDIRECT_HEREDOC) {
4067                        unbackslash(ctx->pending_redirect->rd_filename);
4068                        /* Is it <<"HEREDOC"? */
4069                        if (ctx->word.has_quoted_part) {
4070                                ctx->pending_redirect->rd_dup |= HEREDOC_QUOTED;
4071                        }
4072                }
4073                debug_printf_parse("word stored in rd_filename: '%s'\n", ctx->word.data);
4074                ctx->pending_redirect = NULL;
4075        } else {
4076#if HAS_KEYWORDS
4077# if ENABLE_HUSH_CASE
4078                if (ctx->ctx_dsemicolon
4079                 && strcmp(ctx->word.data, "esac") != 0 /* not "... pattern) cmd;; esac" */
4080                ) {
4081                        /* already done when ctx_dsemicolon was set to 1: */
4082                        /* ctx->ctx_res_w = RES_MATCH; */
4083                        ctx->ctx_dsemicolon = 0;
4084                } else
4085# endif
4086                if (!command->argv /* if it's the first word... */
4087# if ENABLE_HUSH_LOOPS
4088                 && ctx->ctx_res_w != RES_FOR /* ...not after FOR or IN */
4089                 && ctx->ctx_res_w != RES_IN
4090# endif
4091# if ENABLE_HUSH_CASE
4092                 && ctx->ctx_res_w != RES_CASE
4093# endif
4094                ) {
4095                        const struct reserved_combo *reserved;
4096                        reserved = reserved_word(ctx);
4097                        debug_printf_parse("checking for reserved-ness: %d\n", !!reserved);
4098                        if (reserved) {
4099# if ENABLE_HUSH_LINENO_VAR
4100/* Case:
4101 * "while ...; do
4102 *      cmd ..."
4103 * If we don't close the pipe _now_, immediately after "do", lineno logic
4104 * sees "cmd" as starting at "do" - i.e., at the previous line.
4105 */
4106                                if (0
4107                                 IF_HUSH_IF(|| reserved->res == RES_THEN)
4108                                 IF_HUSH_IF(|| reserved->res == RES_ELIF)
4109                                 IF_HUSH_IF(|| reserved->res == RES_ELSE)
4110                                 IF_HUSH_LOOPS(|| reserved->res == RES_DO)
4111                                ) {
4112                                        done_pipe(ctx, PIPE_SEQ);
4113                                }
4114# endif
4115                                o_reset_to_empty_unquoted(&ctx->word);
4116                                debug_printf_parse("done_word return %d\n",
4117                                                (ctx->ctx_res_w == RES_SNTX));
4118                                return (ctx->ctx_res_w == RES_SNTX);
4119                        }
4120# if defined(CMD_SINGLEWORD_NOGLOB)
4121                        if (0
4122#  if BASH_TEST2
4123                         || strcmp(ctx->word.data, "[[") == 0
4124#  endif
4125                        /* In bash, local/export/readonly are special, args
4126                         * are assignments and therefore expansion of them
4127                         * should be "one-word" expansion:
4128                         *  $ export i=`echo 'a  b'` # one arg: "i=a  b"
4129                         * compare with:
4130                         *  $ ls i=`echo 'a  b'`     # two args: "i=a" and "b"
4131                         *  ls: cannot access i=a: No such file or directory
4132                         *  ls: cannot access b: No such file or directory
4133                         * Note: bash 3.2.33(1) does this only if export word
4134                         * itself is not quoted:
4135                         *  $ export i=`echo 'aaa  bbb'`; echo "$i"
4136                         *  aaa  bbb
4137                         *  $ "export" i=`echo 'aaa  bbb'`; echo "$i"
4138                         *  aaa
4139                         */
4140                         IF_HUSH_LOCAL(   || strcmp(ctx->word.data, "local") == 0)
4141                         IF_HUSH_EXPORT(  || strcmp(ctx->word.data, "export") == 0)
4142                         IF_HUSH_READONLY(|| strcmp(ctx->word.data, "readonly") == 0)
4143                        ) {
4144                                command->cmd_type = CMD_SINGLEWORD_NOGLOB;
4145                        }
4146                        /* fall through */
4147# endif
4148                }
4149#endif /* HAS_KEYWORDS */
4150
4151                if (command->group) {
4152                        /* "{ echo foo; } echo bar" - bad */
4153                        syntax_error_at(ctx->word.data);
4154                        debug_printf_parse("done_word return 1: syntax error, "
4155                                        "groups and arglists don't mix\n");
4156                        return 1;
4157                }
4158
4159                /* If this word wasn't an assignment, next ones definitely
4160                 * can't be assignments. Even if they look like ones. */
4161                if (ctx->is_assignment != DEFINITELY_ASSIGNMENT
4162                 && ctx->is_assignment != WORD_IS_KEYWORD
4163                ) {
4164                        ctx->is_assignment = NOT_ASSIGNMENT;
4165                } else {
4166                        if (ctx->is_assignment == DEFINITELY_ASSIGNMENT) {
4167                                command->assignment_cnt++;
4168                                debug_printf_parse("++assignment_cnt=%d\n", command->assignment_cnt);
4169                        }
4170                        debug_printf_parse("ctx->is_assignment was:'%s'\n", assignment_flag[ctx->is_assignment]);
4171                        ctx->is_assignment = MAYBE_ASSIGNMENT;
4172                }
4173                debug_printf_parse("ctx->is_assignment='%s'\n", assignment_flag[ctx->is_assignment]);
4174                command->argv = add_string_to_strings(command->argv, xstrdup(ctx->word.data));
4175                debug_print_strings("word appended to argv", command->argv);
4176        }
4177
4178#if ENABLE_HUSH_LOOPS
4179        if (ctx->ctx_res_w == RES_FOR) {
4180                if (ctx->word.has_quoted_part
4181                 || endofname(command->argv[0])[0] != '\0'
4182                ) {
4183                        /* bash says just "not a valid identifier" */
4184                        syntax_error("not a valid identifier in for");
4185                        return 1;
4186                }
4187                /* Force FOR to have just one word (variable name) */
4188                /* NB: basically, this makes hush see "for v in ..."
4189                 * syntax as if it is "for v; in ...". FOR and IN become
4190                 * two pipe structs in parse tree. */
4191                done_pipe(ctx, PIPE_SEQ);
4192        }
4193#endif
4194#if ENABLE_HUSH_CASE
4195        /* Force CASE to have just one word */
4196        if (ctx->ctx_res_w == RES_CASE) {
4197                done_pipe(ctx, PIPE_SEQ);
4198        }
4199#endif
4200
4201        o_reset_to_empty_unquoted(&ctx->word);
4202
4203        debug_printf_parse("done_word return 0\n");
4204        return 0;
4205}
4206
4207
4208/* Peek ahead in the input to find out if we have a "&n" construct,
4209 * as in "2>&1", that represents duplicating a file descriptor.
4210 * Return:
4211 * REDIRFD_CLOSE if >&- "close fd" construct is seen,
4212 * REDIRFD_SYNTAX_ERR if syntax error,
4213 * REDIRFD_TO_FILE if no & was seen,
4214 * or the number found.
4215 */
4216#if BB_MMU
4217#define parse_redir_right_fd(as_string, input) \
4218        parse_redir_right_fd(input)
4219#endif
4220static int parse_redir_right_fd(o_string *as_string, struct in_str *input)
4221{
4222        int ch, d, ok;
4223
4224        ch = i_peek(input);
4225        if (ch != '&')
4226                return REDIRFD_TO_FILE;
4227
4228        ch = i_getch(input);  /* get the & */
4229        nommu_addchr(as_string, ch);
4230        ch = i_peek(input);
4231        if (ch == '-') {
4232                ch = i_getch(input);
4233                nommu_addchr(as_string, ch);
4234                return REDIRFD_CLOSE;
4235        }
4236        d = 0;
4237        ok = 0;
4238        while (ch != EOF && isdigit(ch)) {
4239                d = d*10 + (ch-'0');
4240                ok = 1;
4241                ch = i_getch(input);
4242                nommu_addchr(as_string, ch);
4243                ch = i_peek(input);
4244        }
4245        if (ok) return d;
4246
4247//TODO: this is the place to catch ">&file" bashism (redirect both fd 1 and 2)
4248
4249        bb_error_msg("ambiguous redirect");
4250        return REDIRFD_SYNTAX_ERR;
4251}
4252
4253/* Return code is 0 normal, 1 if a syntax error is detected
4254 */
4255static int parse_redirect(struct parse_context *ctx,
4256                int fd,
4257                redir_type style,
4258                struct in_str *input)
4259{
4260        struct command *command = ctx->command;
4261        struct redir_struct *redir;
4262        struct redir_struct **redirp;
4263        int dup_num;
4264
4265        dup_num = REDIRFD_TO_FILE;
4266        if (style != REDIRECT_HEREDOC) {
4267                /* Check for a '>&1' type redirect */
4268                dup_num = parse_redir_right_fd(&ctx->as_string, input);
4269                if (dup_num == REDIRFD_SYNTAX_ERR)
4270                        return 1;
4271        } else {
4272                int ch = i_peek_and_eat_bkslash_nl(input);
4273                dup_num = (ch == '-'); /* HEREDOC_SKIPTABS bit is 1 */
4274                if (dup_num) { /* <<-... */
4275                        ch = i_getch(input);
4276                        nommu_addchr(&ctx->as_string, ch);
4277                        ch = i_peek(input);
4278                }
4279        }
4280
4281        if (style == REDIRECT_OVERWRITE && dup_num == REDIRFD_TO_FILE) {
4282                int ch = i_peek_and_eat_bkslash_nl(input);
4283                if (ch == '|') {
4284                        /* >|FILE redirect ("clobbering" >).
4285                         * Since we do not support "set -o noclobber" yet,
4286                         * >| and > are the same for now. Just eat |.
4287                         */
4288                        ch = i_getch(input);
4289                        nommu_addchr(&ctx->as_string, ch);
4290                }
4291        }
4292
4293        /* Create a new redir_struct and append it to the linked list */
4294        redirp = &command->redirects;
4295        while ((redir = *redirp) != NULL) {
4296                redirp = &(redir->next);
4297        }
4298        *redirp = redir = xzalloc(sizeof(*redir));
4299        /* redir->next = NULL; */
4300        /* redir->rd_filename = NULL; */
4301        redir->rd_type = style;
4302        redir->rd_fd = (fd == -1) ? redir_table[style].default_fd : fd;
4303
4304        debug_printf_parse("redirect type %d %s\n", redir->rd_fd,
4305                                redir_table[style].descrip);
4306
4307        redir->rd_dup = dup_num;
4308        if (style != REDIRECT_HEREDOC && dup_num != REDIRFD_TO_FILE) {
4309                /* Erik had a check here that the file descriptor in question
4310                 * is legit; I postpone that to "run time"
4311                 * A "-" representation of "close me" shows up as a -3 here */
4312                debug_printf_parse("duplicating redirect '%d>&%d'\n",
4313                                redir->rd_fd, redir->rd_dup);
4314        } else {
4315#if 0           /* Instead we emit error message at run time */
4316                if (ctx->pending_redirect) {
4317                        /* For example, "cmd > <file" */
4318                        syntax_error("invalid redirect");
4319                }
4320#endif
4321                /* Set ctx->pending_redirect, so we know what to do at the
4322                 * end of the next parsed word. */
4323                ctx->pending_redirect = redir;
4324        }
4325        return 0;
4326}
4327
4328/* If a redirect is immediately preceded by a number, that number is
4329 * supposed to tell which file descriptor to redirect.  This routine
4330 * looks for such preceding numbers.  In an ideal world this routine
4331 * needs to handle all the following classes of redirects...
4332 *     echo 2>foo     # redirects fd  2 to file "foo", nothing passed to echo
4333 *     echo 49>foo    # redirects fd 49 to file "foo", nothing passed to echo
4334 *     echo -2>foo    # redirects fd  1 to file "foo",    "-2" passed to echo
4335 *     echo 49x>foo   # redirects fd  1 to file "foo",   "49x" passed to echo
4336 *
4337 * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
4338 * "2.7 Redirection
4339 * ... If n is quoted, the number shall not be recognized as part of
4340 * the redirection expression. For example:
4341 * echo \2>a
4342 * writes the character 2 into file a"
4343 * We are getting it right by setting ->has_quoted_part on any \<char>
4344 *
4345 * A -1 return means no valid number was found,
4346 * the caller should use the appropriate default for this redirection.
4347 */
4348static int redirect_opt_num(o_string *o)
4349{
4350        int num;
4351
4352        if (o->data == NULL)
4353                return -1;
4354        num = bb_strtou(o->data, NULL, 10);
4355        if (errno || num < 0)
4356                return -1;
4357        o_reset_to_empty_unquoted(o);
4358        return num;
4359}
4360
4361#if BB_MMU
4362#define fetch_till_str(as_string, input, word, skip_tabs) \
4363        fetch_till_str(input, word, skip_tabs)
4364#endif
4365static char *fetch_till_str(o_string *as_string,
4366                struct in_str *input,
4367                const char *word,
4368                int heredoc_flags)
4369{
4370        o_string heredoc = NULL_O_STRING;
4371        unsigned past_EOL;
4372        int prev = 0; /* not \ */
4373        int ch;
4374
4375        /* Starting with "" is necessary for this case:
4376         * cat <<EOF
4377         *
4378         * xxx
4379         * EOF
4380         */
4381        heredoc.data = xzalloc(1); /* start as "", not as NULL */
4382
4383        goto jump_in;
4384
4385        while (1) {
4386                ch = i_getch(input);
4387                if (ch != EOF)
4388                        nommu_addchr(as_string, ch);
4389                if (ch == '\n' || ch == EOF) {
4390 check_heredoc_end:
4391                        if ((heredoc_flags & HEREDOC_QUOTED) || prev != '\\') {
4392                                /* End-of-line, and not a line continuation */
4393                                if (strcmp(heredoc.data + past_EOL, word) == 0) {
4394                                        heredoc.data[past_EOL] = '\0';
4395                                        debug_printf_heredoc("parsed '%s' heredoc '%s'\n", word, heredoc.data);
4396                                        return heredoc.data;
4397                                }
4398                                if (ch == '\n') {
4399                                        /* This is a new line.
4400                                         * Remember position and backslash-escaping status.
4401                                         */
4402                                        o_addchr(&heredoc, ch);
4403                                        prev = ch;
4404 jump_in:
4405                                        past_EOL = heredoc.length;
4406                                        /* Get 1st char of next line, possibly skipping leading tabs */
4407                                        do {
4408                                                ch = i_getch(input);
4409                                                if (ch != EOF)
4410                                                        nommu_addchr(as_string, ch);
4411                                        } while ((heredoc_flags & HEREDOC_SKIPTABS) && ch == '\t');
4412                                        /* If this immediately ended the line,
4413                                         * go back to end-of-line checks.
4414                                         */
4415                                        if (ch == '\n')
4416                                                goto check_heredoc_end;
4417                                }
4418                        } else {
4419                                /* Backslash-line continuation in an unquoted
4420                                 * heredoc. This does not need special handling
4421                                 * for heredoc body (unquoted heredocs are
4422                                 * expanded on "execution" and that would take
4423                                 * care of this case too), but not the case
4424                                 * of line continuation *in terminator*:
4425                                 *  cat <<EOF
4426                                 *  Ok1
4427                                 *  EO\
4428                                 *  F
4429                                 */
4430                                heredoc.data[--heredoc.length] = '\0';
4431                                prev = 0; /* not '\' */
4432                                continue;
4433                        }
4434                }
4435                if (ch == EOF) {
4436                        o_free(&heredoc);
4437                        return NULL; /* error */
4438                }
4439                o_addchr(&heredoc, ch);
4440                nommu_addchr(as_string, ch);
4441                if (prev == '\\' && ch == '\\')
4442                        /* Correctly handle foo\\<eol> (not a line cont.) */
4443                        prev = 0; /* not '\' */
4444                else
4445                        prev = ch;
4446        }
4447}
4448
4449/* Look at entire parse tree for not-yet-loaded REDIRECT_HEREDOCs
4450 * and load them all. There should be exactly heredoc_cnt of them.
4451 */
4452#if BB_MMU
4453#define fetch_heredocs(as_string, pi, heredoc_cnt, input) \
4454        fetch_heredocs(pi, heredoc_cnt, input)
4455#endif
4456static int fetch_heredocs(o_string *as_string, struct pipe *pi, int heredoc_cnt, struct in_str *input)
4457{
4458        while (pi && heredoc_cnt) {
4459                int i;
4460                struct command *cmd = pi->cmds;
4461
4462                debug_printf_heredoc("fetch_heredocs: num_cmds:%d cmd argv0:'%s'\n",
4463                                pi->num_cmds,
4464                                cmd->argv ? cmd->argv[0] : "NONE"
4465                );
4466                for (i = 0; i < pi->num_cmds; i++) {
4467                        struct redir_struct *redir = cmd->redirects;
4468
4469                        debug_printf_heredoc("fetch_heredocs: %d cmd argv0:'%s'\n",
4470                                        i, cmd->argv ? cmd->argv[0] : "NONE");
4471                        while (redir) {
4472                                if (redir->rd_type == REDIRECT_HEREDOC) {
4473                                        char *p;
4474
4475                                        redir->rd_type = REDIRECT_HEREDOC2;
4476                                        /* redir->rd_dup is (ab)used to indicate <<- */
4477                                        p = fetch_till_str(as_string, input,
4478                                                        redir->rd_filename, redir->rd_dup);
4479                                        if (!p) {
4480                                                syntax_error("unexpected EOF in here document");
4481                                                return -1;
4482                                        }
4483                                        free(redir->rd_filename);
4484                                        redir->rd_filename = p;
4485                                        heredoc_cnt--;
4486                                }
4487                                redir = redir->next;
4488                        }
4489                        if (cmd->group) {
4490                                //bb_error_msg("%s:%u heredoc_cnt:%d", __func__, __LINE__, heredoc_cnt);
4491                                heredoc_cnt = fetch_heredocs(as_string, cmd->group, heredoc_cnt, input);
4492                                //bb_error_msg("%s:%u heredoc_cnt:%d", __func__, __LINE__, heredoc_cnt);
4493                                if (heredoc_cnt < 0)
4494                                        return heredoc_cnt; /* error */
4495                        }
4496                        cmd++;
4497                }
4498                pi = pi->next;
4499        }
4500        return heredoc_cnt;
4501}
4502
4503
4504static int run_list(struct pipe *pi);
4505#if BB_MMU
4506#define parse_stream(pstring, heredoc_cnt_ptr, input, end_trigger) \
4507        parse_stream(heredoc_cnt_ptr, input, end_trigger)
4508#endif
4509static struct pipe *parse_stream(char **pstring,
4510                int *heredoc_cnt_ptr,
4511                struct in_str *input,
4512                int end_trigger);
4513
4514/* Returns number of heredocs not yet consumed,
4515 * or -1 on error.
4516 */
4517static int parse_group(struct parse_context *ctx,
4518                struct in_str *input, int ch)
4519{
4520        /* ctx->word contains characters seen prior to ( or {.
4521         * Typically it's empty, but for function defs,
4522         * it contains function name (without '()'). */
4523#if BB_MMU
4524# define as_string NULL
4525#else
4526        char *as_string = NULL;
4527#endif
4528        struct pipe *pipe_list;
4529        int heredoc_cnt = 0;
4530        int endch;
4531        struct command *command = ctx->command;
4532
4533        debug_printf_parse("parse_group entered\n");
4534#if ENABLE_HUSH_FUNCTIONS
4535        if (ch == '(' && !ctx->word.has_quoted_part) {
4536                if (ctx->word.length)
4537                        if (done_word(ctx))
4538                                return -1;
4539                if (!command->argv)
4540                        goto skip; /* (... */
4541                if (command->argv[1]) { /* word word ... (... */
4542                        syntax_error_unexpected_ch('(');
4543                        return -1;
4544                }
4545                /* it is "word(..." or "word (..." */
4546                do
4547                        ch = i_getch(input);
4548                while (ch == ' ' || ch == '\t');
4549                if (ch != ')') {
4550                        syntax_error_unexpected_ch(ch);
4551                        return -1;
4552                }
4553                nommu_addchr(&ctx->as_string, ch);
4554                do
4555                        ch = i_getch(input);
4556                while (ch == ' ' || ch == '\t' || ch == '\n');
4557                if (ch != '{' && ch != '(') {
4558                        syntax_error_unexpected_ch(ch);
4559                        return -1;
4560                }
4561                nommu_addchr(&ctx->as_string, ch);
4562                command->cmd_type = CMD_FUNCDEF;
4563                goto skip;
4564        }
4565#endif
4566
4567#if 0 /* Prevented by caller */
4568        if (command->argv /* word [word]{... */
4569         || ctx->word.length /* word{... */
4570         || ctx->word.has_quoted_part /* ""{... */
4571        ) {
4572                syntax_error(NULL);
4573                debug_printf_parse("parse_group return -1: "
4574                        "syntax error, groups and arglists don't mix\n");
4575                return -1;
4576        }
4577#endif
4578
4579 IF_HUSH_FUNCTIONS(skip:)
4580
4581        endch = '}';
4582        if (ch == '(') {
4583                endch = ')';
4584                IF_HUSH_FUNCTIONS(if (command->cmd_type != CMD_FUNCDEF))
4585                        command->cmd_type = CMD_SUBSHELL;
4586        } else {
4587                /* bash does not allow "{echo...", requires whitespace */
4588                ch = i_peek(input);
4589                if (ch != ' ' && ch != '\t' && ch != '\n'
4590                 && ch != '('   /* but "{(..." is allowed (without whitespace) */
4591                ) {
4592                        syntax_error_unexpected_ch(ch);
4593                        return -1;
4594                }
4595                if (ch != '(') {
4596                        ch = i_getch(input);
4597                        nommu_addchr(&ctx->as_string, ch);
4598                }
4599        }
4600
4601        debug_printf_heredoc("calling parse_stream, heredoc_cnt:%d\n", heredoc_cnt);
4602        pipe_list = parse_stream(&as_string, &heredoc_cnt, input, endch);
4603        debug_printf_heredoc("parse_stream returned: heredoc_cnt:%d\n", heredoc_cnt);
4604#if !BB_MMU
4605        if (as_string)
4606                o_addstr(&ctx->as_string, as_string);
4607#endif
4608
4609        /* empty ()/{} or parse error? */
4610        if (!pipe_list || pipe_list == ERR_PTR) {
4611                /* parse_stream already emitted error msg */
4612                if (!BB_MMU)
4613                        free(as_string);
4614                debug_printf_parse("parse_group return -1: "
4615                        "parse_stream returned %p\n", pipe_list);
4616                return -1;
4617        }
4618#if !BB_MMU
4619        as_string[strlen(as_string) - 1] = '\0'; /* plink ')' or '}' */
4620        command->group_as_string = as_string;
4621        debug_printf_parse("end of group, remembering as:'%s'\n",
4622                        command->group_as_string);
4623#endif
4624
4625#if ENABLE_HUSH_FUNCTIONS
4626        /* Convert "f() (cmds)" to "f() {(cmds)}" */
4627        if (command->cmd_type == CMD_FUNCDEF && endch == ')') {
4628                struct command *cmd2;
4629
4630                cmd2 = xzalloc(sizeof(*cmd2));
4631                cmd2->cmd_type = CMD_SUBSHELL;
4632                cmd2->group = pipe_list;
4633# if !BB_MMU
4634//UNTESTED!
4635                cmd2->group_as_string = command->group_as_string;
4636                command->group_as_string = xasprintf("(%s)", command->group_as_string);
4637# endif
4638
4639                pipe_list = new_pipe();
4640                pipe_list->cmds = cmd2;
4641                pipe_list->num_cmds = 1;
4642        }
4643#endif
4644
4645        command->group = pipe_list;
4646
4647        debug_printf_parse("parse_group return %d\n", heredoc_cnt);
4648        return heredoc_cnt;
4649        /* command remains "open", available for possible redirects */
4650#undef as_string
4651}
4652
4653#if ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS
4654/* Subroutines for copying $(...) and `...` things */
4655/* '...' */
4656static int add_till_single_quote(o_string *dest, struct in_str *input)
4657{
4658        while (1) {
4659                int ch = i_getch(input);
4660                if (ch == EOF) {
4661                        syntax_error_unterm_ch('\'');
4662                        return 0;
4663                }
4664                if (ch == '\'')
4665                        return 1;
4666                o_addchr(dest, ch);
4667        }
4668}
4669static int add_till_single_quote_dquoted(o_string *dest, struct in_str *input)
4670{
4671        while (1) {
4672                int ch = i_getch(input);
4673                if (ch == EOF) {
4674                        syntax_error_unterm_ch('\'');
4675                        return 0;
4676                }
4677                if (ch == '\'')
4678                        return 1;
4679                o_addqchr(dest, ch);
4680        }
4681}
4682/* "...\"...`..`...." - do we need to handle "...$(..)..." too? */
4683static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote);
4684static int add_till_double_quote(o_string *dest, struct in_str *input)
4685{
4686        while (1) {
4687                int ch = i_getch(input);
4688                if (ch == EOF) {
4689                        syntax_error_unterm_ch('"');
4690                        return 0;
4691                }
4692                if (ch == '"')
4693                        return 1;
4694                if (ch == '\\') {  /* \x. Copy both chars. */
4695                        o_addchr(dest, ch);
4696                        ch = i_getch(input);
4697                }
4698                o_addchr(dest, ch);
4699                if (ch == '`') {
4700                        if (!add_till_backquote(dest, input, /*in_dquote:*/ 1))
4701                                return 0;
4702                        o_addchr(dest, ch);
4703                        continue;
4704                }
4705                //if (ch == '$') ...
4706        }
4707}
4708/* Process `cmd` - copy contents until "`" is seen. Complicated by
4709 * \` quoting.
4710 * "Within the backquoted style of command substitution, backslash
4711 * shall retain its literal meaning, except when followed by: '$', '`', or '\'.
4712 * The search for the matching backquote shall be satisfied by the first
4713 * backquote found without a preceding backslash; during this search,
4714 * if a non-escaped backquote is encountered within a shell comment,
4715 * a here-document, an embedded command substitution of the $(command)
4716 * form, or a quoted string, undefined results occur. A single-quoted
4717 * or double-quoted string that begins, but does not end, within the
4718 * "`...`" sequence produces undefined results."
4719 * Example                               Output
4720 * echo `echo '\'TEST\`echo ZZ\`BEST`    \TESTZZBEST
4721 */
4722static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote)
4723{
4724        while (1) {
4725                int ch = i_getch(input);
4726                if (ch == '`')
4727                        return 1;
4728                if (ch == '\\') {
4729                        /* \x. Copy both unless it is \`, \$, \\ and maybe \" */
4730                        ch = i_getch(input);
4731                        if (ch != '`'
4732                         && ch != '$'
4733                         && ch != '\\'
4734                         && (!in_dquote || ch != '"')
4735                        ) {
4736                                o_addchr(dest, '\\');
4737                        }
4738                }
4739                if (ch == EOF) {
4740                        syntax_error_unterm_ch('`');
4741                        return 0;
4742                }
4743                o_addchr(dest, ch);
4744        }
4745}
4746/* Process $(cmd) - copy contents until ")" is seen. Complicated by
4747 * quoting and nested ()s.
4748 * "With the $(command) style of command substitution, all characters
4749 * following the open parenthesis to the matching closing parenthesis
4750 * constitute the command. Any valid shell script can be used for command,
4751 * except a script consisting solely of redirections which produces
4752 * unspecified results."
4753 * Example                              Output
4754 * echo $(echo '(TEST)' BEST)           (TEST) BEST
4755 * echo $(echo 'TEST)' BEST)            TEST) BEST
4756 * echo $(echo \(\(TEST\) BEST)         ((TEST) BEST
4757 *
4758 * Also adapted to eat ${var%...} and $((...)) constructs, since ... part
4759 * can contain arbitrary constructs, just like $(cmd).
4760 * In bash compat mode, it needs to also be able to stop on ':' or '/'
4761 * for ${var:N[:M]} and ${var/P[/R]} parsing.
4762 */
4763#define DOUBLE_CLOSE_CHAR_FLAG 0x80
4764static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsigned end_ch)
4765{
4766        int ch;
4767        char dbl = end_ch & DOUBLE_CLOSE_CHAR_FLAG;
4768# if BASH_SUBSTR || BASH_PATTERN_SUBST
4769        char end_char2 = end_ch >> 8;
4770# endif
4771        end_ch &= (DOUBLE_CLOSE_CHAR_FLAG - 1);
4772
4773#if ENABLE_HUSH_INTERACTIVE
4774        G.promptmode = 1; /* PS2 */
4775#endif
4776        debug_printf_prompt("%s promptmode=%d\n", __func__, G.promptmode);
4777
4778        while (1) {
4779                ch = i_getch(input);
4780                if (ch == EOF) {
4781                        syntax_error_unterm_ch(end_ch);
4782                        return 0;
4783                }
4784                if (ch == end_ch
4785# if BASH_SUBSTR || BASH_PATTERN_SUBST
4786                 || ch == end_char2
4787# endif
4788                ) {
4789                        if (!dbl)
4790                                break;
4791                        /* we look for closing )) of $((EXPR)) */
4792                        if (i_peek_and_eat_bkslash_nl(input) == end_ch) {
4793                                i_getch(input); /* eat second ')' */
4794                                break;
4795                        }
4796                }
4797                o_addchr(dest, ch);
4798                //bb_error_msg("%s:o_addchr('%c')", __func__, ch);
4799                if (ch == '(' || ch == '{') {
4800                        ch = (ch == '(' ? ')' : '}');
4801                        if (!add_till_closing_bracket(dest, input, ch))
4802                                return 0;
4803                        o_addchr(dest, ch);
4804                        continue;
4805                }
4806                if (ch == '\'') {
4807                        if (!add_till_single_quote(dest, input))
4808                                return 0;
4809                        o_addchr(dest, ch);
4810                        continue;
4811                }
4812                if (ch == '"') {
4813                        if (!add_till_double_quote(dest, input))
4814                                return 0;
4815                        o_addchr(dest, ch);
4816                        continue;
4817                }
4818                if (ch == '`') {
4819                        if (!add_till_backquote(dest, input, /*in_dquote:*/ 0))
4820                                return 0;
4821                        o_addchr(dest, ch);
4822                        continue;
4823                }
4824                if (ch == '\\') {
4825                        /* \x. Copy verbatim. Important for  \(, \) */
4826                        ch = i_getch(input);
4827                        if (ch == EOF) {
4828                                syntax_error_unterm_ch(end_ch);
4829                                return 0;
4830                        }
4831#if 0
4832                        if (ch == '\n') {
4833                                /* "backslash+newline", ignore both */
4834                                o_delchr(dest); /* undo insertion of '\' */
4835                                continue;
4836                        }
4837#endif
4838                        o_addchr(dest, ch);
4839                        //bb_error_msg("%s:o_addchr('%c') after '\\'", __func__, ch);
4840                        continue;
4841                }
4842        }
4843        debug_printf_parse("%s return '%s' ch:'%c'\n", __func__, dest->data, ch);
4844        return ch;
4845}
4846#endif /* ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS */
4847
4848/* Return code: 0 for OK, 1 for syntax error */
4849#if BB_MMU
4850#define parse_dollar(as_string, dest, input, quote_mask) \
4851        parse_dollar(dest, input, quote_mask)
4852#define as_string NULL
4853#endif
4854static int parse_dollar(o_string *as_string,
4855                o_string *dest,
4856                struct in_str *input, unsigned char quote_mask)
4857{
4858        int ch = i_peek_and_eat_bkslash_nl(input);  /* first character after the $ */
4859
4860        debug_printf_parse("parse_dollar entered: ch='%c'\n", ch);
4861        if (isalpha(ch)) {
4862 make_var:
4863                ch = i_getch(input);
4864                nommu_addchr(as_string, ch);
4865 /*make_var1:*/
4866                o_addchr(dest, SPECIAL_VAR_SYMBOL);
4867                while (1) {
4868                        debug_printf_parse(": '%c'\n", ch);
4869                        o_addchr(dest, ch | quote_mask);
4870                        quote_mask = 0;
4871                        ch = i_peek_and_eat_bkslash_nl(input);
4872                        if (!isalnum(ch) && ch != '_') {
4873                                /* End of variable name reached */
4874                                break;
4875                        }
4876                        ch = i_getch(input);
4877                        nommu_addchr(as_string, ch);
4878                }
4879                o_addchr(dest, SPECIAL_VAR_SYMBOL);
4880        } else if (isdigit(ch)) {
4881 make_one_char_var:
4882                ch = i_getch(input);
4883                nommu_addchr(as_string, ch);
4884                o_addchr(dest, SPECIAL_VAR_SYMBOL);
4885                debug_printf_parse(": '%c'\n", ch);
4886                o_addchr(dest, ch | quote_mask);
4887                o_addchr(dest, SPECIAL_VAR_SYMBOL);
4888        } else switch (ch) {
4889        case '$': /* pid */
4890        case '!': /* last bg pid */
4891        case '?': /* last exit code */
4892        case '#': /* number of args */
4893        case '*': /* args */
4894        case '@': /* args */
4895        case '-': /* $- option flags set by set builtin or shell options (-i etc) */
4896                goto make_one_char_var;
4897        case '{': {
4898                char len_single_ch;
4899
4900                o_addchr(dest, SPECIAL_VAR_SYMBOL);
4901
4902                ch = i_getch(input); /* eat '{' */
4903                nommu_addchr(as_string, ch);
4904
4905                ch = i_getch_and_eat_bkslash_nl(input); /* first char after '{' */
4906                /* It should be ${?}, or ${#var},
4907                 * or even ${?+subst} - operator acting on a special variable,
4908                 * or the beginning of variable name.
4909                 */
4910                if (ch == EOF
4911                 || (!strchr(_SPECIAL_VARS_STR, ch) && !isalnum(ch)) /* not one of those */
4912                ) {
4913 bad_dollar_syntax:
4914                        syntax_error_unterm_str("${name}");
4915                        debug_printf_parse("parse_dollar return 0: unterminated ${name}\n");
4916                        return 0;
4917                }
4918                nommu_addchr(as_string, ch);
4919                len_single_ch = ch;
4920                ch |= quote_mask;
4921
4922                /* It's possible to just call add_till_closing_bracket() at this point.
4923                 * However, this regresses some of our testsuite cases
4924                 * which check invalid constructs like ${%}.
4925                 * Oh well... let's check that the var name part is fine... */
4926
4927                while (1) {
4928                        unsigned pos;
4929
4930                        o_addchr(dest, ch);
4931                        debug_printf_parse(": '%c'\n", ch);
4932
4933                        ch = i_getch(input);
4934                        nommu_addchr(as_string, ch);
4935                        if (ch == '}')
4936                                break;
4937
4938                        if (!isalnum(ch) && ch != '_') {
4939                                unsigned end_ch;
4940                                unsigned char last_ch;
4941                                /* handle parameter expansions
4942                                 * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02
4943                                 */
4944                                if (!strchr(VAR_SUBST_OPS, ch)) { /* ${var<bad_char>... */
4945                                        if (len_single_ch != '#'
4946                                        /*|| !strchr(SPECIAL_VARS_STR, ch) - disallow errors like ${#+} ? */
4947                                         || i_peek(input) != '}'
4948                                        ) {
4949                                                goto bad_dollar_syntax;
4950                                        }
4951                                        /* else: it's "length of C" ${#C} op,
4952                                         * where C is a single char
4953                                         * special var name, e.g. ${#!}.
4954                                         */
4955                                }
4956                                /* Eat everything until closing '}' (or ':') */
4957                                end_ch = '}';
4958                                if (BASH_SUBSTR
4959                                 && ch == ':'
4960                                 && !strchr(MINUS_PLUS_EQUAL_QUESTION, i_peek(input))
4961                                ) {
4962                                        /* It's ${var:N[:M]} thing */
4963                                        end_ch = '}' * 0x100 + ':';
4964                                }
4965                                if (BASH_PATTERN_SUBST
4966                                 && ch == '/'
4967                                ) {
4968                                        /* It's ${var/[/]pattern[/repl]} thing */
4969                                        if (i_peek(input) == '/') { /* ${var//pattern[/repl]}? */
4970                                                i_getch(input);
4971                                                nommu_addchr(as_string, '/');
4972                                                ch = '\\';
4973                                        }
4974                                        end_ch = '}' * 0x100 + '/';
4975                                }
4976                                o_addchr(dest, ch);
4977                                /* The pattern can't be empty.
4978                                 * IOW: if the first char after "${v//" is a slash,
4979                                 * it does not terminate the pattern - it's the first char of the pattern:
4980                                 *  v=/dev/ram; echo ${v////-}  prints -dev-ram (pattern is "/")
4981                                 *  v=/dev/ram; echo ${v///r/-} prints /dev-am  (pattern is "/r")
4982                                 */
4983                                if (i_peek(input) == '/') {
4984                                        o_addchr(dest, i_getch(input));
4985                                }
4986 again:
4987                                if (!BB_MMU)
4988                                        pos = dest->length;
4989#if ENABLE_HUSH_DOLLAR_OPS
4990                                last_ch = add_till_closing_bracket(dest, input, end_ch);
4991                                if (last_ch == 0) /* error? */
4992                                        return 0;
4993#else
4994#error Simple code to only allow ${var} is not implemented
4995#endif
4996                                if (as_string) {
4997                                        o_addstr(as_string, dest->data + pos);
4998                                        o_addchr(as_string, last_ch);
4999                                }
5000
5001                                if ((BASH_SUBSTR || BASH_PATTERN_SUBST)
5002                                         && (end_ch & 0xff00)
5003                                ) {
5004                                        /* close the first block: */
5005                                        o_addchr(dest, SPECIAL_VAR_SYMBOL);
5006                                        /* while parsing N from ${var:N[:M]}
5007                                         * or pattern from ${var/[/]pattern[/repl]} */
5008                                        if ((end_ch & 0xff) == last_ch) {
5009                                                /* got ':' or '/'- parse the rest */
5010                                                end_ch = '}';
5011                                                goto again;
5012                                        }
5013                                        /* got '}' */
5014                                        if (BASH_SUBSTR && end_ch == '}' * 0x100 + ':') {
5015                                                /* it's ${var:N} - emulate :999999999 */
5016                                                o_addstr(dest, "999999999");
5017                                        } /* else: it's ${var/[/]pattern} */
5018                                }
5019                                break;
5020                        }
5021                        len_single_ch = 0; /* it can't be ${#C} op */
5022                }
5023                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5024                break;
5025        }
5026#if ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_TICK
5027        case '(': {
5028                unsigned pos;
5029
5030                ch = i_getch(input);
5031                nommu_addchr(as_string, ch);
5032# if ENABLE_FEATURE_SH_MATH
5033                if (i_peek_and_eat_bkslash_nl(input) == '(') {
5034                        ch = i_getch(input);
5035                        nommu_addchr(as_string, ch);
5036                        o_addchr(dest, SPECIAL_VAR_SYMBOL);
5037                        o_addchr(dest, /*quote_mask |*/ '+');
5038                        if (!BB_MMU)
5039                                pos = dest->length;
5040                        if (!add_till_closing_bracket(dest, input, ')' | DOUBLE_CLOSE_CHAR_FLAG))
5041                                return 0; /* error */
5042                        if (as_string) {
5043                                o_addstr(as_string, dest->data + pos);
5044                                o_addchr(as_string, ')');
5045                                o_addchr(as_string, ')');
5046                        }
5047                        o_addchr(dest, SPECIAL_VAR_SYMBOL);
5048                        break;
5049                }
5050# endif
5051# if ENABLE_HUSH_TICK
5052                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5053                o_addchr(dest, quote_mask | '`');
5054                if (!BB_MMU)
5055                        pos = dest->length;
5056                if (!add_till_closing_bracket(dest, input, ')'))
5057                        return 0; /* error */
5058                if (as_string) {
5059                        o_addstr(as_string, dest->data + pos);
5060                        o_addchr(as_string, ')');
5061                }
5062                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5063# endif
5064                break;
5065        }
5066#endif
5067        case '_':
5068                goto make_var;
5069#if 0
5070        /* TODO: $_: */
5071        /* $_ Shell or shell script name; or last argument of last command
5072         * (if last command wasn't a pipe; if it was, bash sets $_ to "");
5073         * but in command's env, set to full pathname used to invoke it */
5074                ch = i_getch(input);
5075                nommu_addchr(as_string, ch);
5076                ch = i_peek_and_eat_bkslash_nl(input);
5077                if (isalnum(ch)) { /* it's $_name or $_123 */
5078                        ch = '_';
5079                        goto make_var1;
5080                }
5081                /* else: it's $_ */
5082#endif
5083        default:
5084                o_addQchr(dest, '$');
5085        }
5086        debug_printf_parse("parse_dollar return 1 (ok)\n");
5087        return 1;
5088#undef as_string
5089}
5090
5091#if BB_MMU
5092#define encode_string(as_string, dest, input, dquote_end) \
5093        encode_string(dest, input, dquote_end)
5094#define as_string NULL
5095#endif
5096static int encode_string(o_string *as_string,
5097                o_string *dest,
5098                struct in_str *input,
5099                int dquote_end)
5100{
5101        int ch;
5102        int next;
5103
5104 again:
5105        ch = i_getch(input);
5106        if (ch != EOF)
5107                nommu_addchr(as_string, ch);
5108        if (ch == dquote_end) { /* may be only '"' or EOF */
5109                debug_printf_parse("encode_string return 1 (ok)\n");
5110                return 1;
5111        }
5112        /* note: can't move it above ch == dquote_end check! */
5113        if (ch == EOF) {
5114                syntax_error_unterm_ch('"');
5115                return 0; /* error */
5116        }
5117        next = '\0';
5118        if (ch != '\n') {
5119                next = i_peek(input);
5120        }
5121        debug_printf_parse("\" ch=%c (%d) escape=%d\n",
5122                        ch, ch, !!(dest->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
5123        if (ch == '\\') {
5124                if (next == EOF) {
5125                        /* Testcase: in interactive shell a file with
5126                         *  echo "unterminated string\<eof>
5127                         * is sourced.
5128                         */
5129                        syntax_error_unterm_ch('"');
5130                        return 0; /* error */
5131                }
5132                /* bash:
5133                 * "The backslash retains its special meaning [in "..."]
5134                 * only when followed by one of the following characters:
5135                 * $, `, ", \, or <newline>.  A double quote may be quoted
5136                 * within double quotes by preceding it with a backslash."
5137                 * NB: in (unquoted) heredoc, above does not apply to ",
5138                 * therefore we check for it by "next == dquote_end" cond.
5139                 */
5140                if (next == dquote_end || strchr("$`\\\n", next)) {
5141                        ch = i_getch(input); /* eat next */
5142                        if (ch == '\n')
5143                                goto again; /* skip \<newline> */
5144                } /* else: ch remains == '\\', and we double it below: */
5145                o_addqchr(dest, ch); /* \c if c is a glob char, else just c */
5146                nommu_addchr(as_string, ch);
5147                goto again;
5148        }
5149        if (ch == '$') {
5150                if (!parse_dollar(as_string, dest, input, /*quote_mask:*/ 0x80)) {
5151                        debug_printf_parse("encode_string return 0: "
5152                                        "parse_dollar returned 0 (error)\n");
5153                        return 0;
5154                }
5155                goto again;
5156        }
5157#if ENABLE_HUSH_TICK
5158        if (ch == '`') {
5159                //unsigned pos = dest->length;
5160                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5161                o_addchr(dest, 0x80 | '`');
5162                if (!add_till_backquote(dest, input, /*in_dquote:*/ dquote_end == '"'))
5163                        return 0; /* error */
5164                o_addchr(dest, SPECIAL_VAR_SYMBOL);
5165                //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos);
5166                goto again;
5167        }
5168#endif
5169        o_addQchr(dest, ch);
5170        goto again;
5171#undef as_string
5172}
5173
5174/*
5175 * Scan input until EOF or end_trigger char.
5176 * Return a list of pipes to execute, or NULL on EOF
5177 * or if end_trigger character is met.
5178 * On syntax error, exit if shell is not interactive,
5179 * reset parsing machinery and start parsing anew,
5180 * or return ERR_PTR.
5181 */
5182static struct pipe *parse_stream(char **pstring,
5183                int *heredoc_cnt_ptr,
5184                struct in_str *input,
5185                int end_trigger)
5186{
5187        struct parse_context ctx;
5188        int heredoc_cnt;
5189
5190        /* Single-quote triggers a bypass of the main loop until its mate is
5191         * found.  When recursing, quote state is passed in via ctx.word.o_expflags.
5192         */
5193        debug_printf_parse("parse_stream entered, end_trigger='%c'\n",
5194                        end_trigger ? end_trigger : 'X');
5195        debug_enter();
5196
5197        initialize_context(&ctx);
5198
5199        /* If very first arg is "" or '', ctx.word.data may end up NULL.
5200         * Preventing this:
5201         */
5202        ctx.word.data = xzalloc(1); /* start as "", not as NULL */
5203
5204        /* We used to separate words on $IFS here. This was wrong.
5205         * $IFS is used only for word splitting when $var is expanded,
5206         * here we should use blank chars as separators, not $IFS
5207         */
5208
5209        heredoc_cnt = 0;
5210        while (1) {
5211                const char *is_blank;
5212                const char *is_special;
5213                int ch;
5214                int next;
5215                int redir_fd;
5216                redir_type redir_style;
5217
5218                ch = i_getch(input);
5219                debug_printf_parse(": ch=%c (%d) escape=%d\n",
5220                                ch, ch, !!(ctx.word.o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
5221                if (ch == EOF) {
5222                        struct pipe *pi;
5223
5224                        if (heredoc_cnt) {
5225                                syntax_error_unterm_str("here document");
5226                                goto parse_error;
5227                        }
5228                        if (end_trigger == ')') {
5229                                syntax_error_unterm_ch('(');
5230                                goto parse_error;
5231                        }
5232                        if (end_trigger == '}') {
5233                                syntax_error_unterm_ch('{');
5234                                goto parse_error;
5235                        }
5236
5237                        if (done_word(&ctx)) {
5238                                goto parse_error;
5239                        }
5240                        o_free_and_set_NULL(&ctx.word);
5241                        done_pipe(&ctx, PIPE_SEQ);
5242                        pi = ctx.list_head;
5243                        /* If we got nothing... */
5244                        /* (this makes bare "&" cmd a no-op.
5245                         * bash says: "syntax error near unexpected token '&'") */
5246                        if (pi->num_cmds == 0
5247                        IF_HAS_KEYWORDS(&& pi->res_word == RES_NONE)
5248                        ) {
5249                                free_pipe_list(pi);
5250                                pi = NULL;
5251                        }
5252#if !BB_MMU
5253                        debug_printf_parse("as_string1 '%s'\n", ctx.as_string.data);
5254                        if (pstring)
5255                                *pstring = ctx.as_string.data;
5256                        else
5257                                o_free(&ctx.as_string);
5258#endif
5259                        // heredoc_cnt must be 0 here anyway
5260                        //if (heredoc_cnt_ptr)
5261                        //      *heredoc_cnt_ptr = heredoc_cnt;
5262                        debug_leave();
5263                        debug_printf_heredoc("parse_stream return heredoc_cnt:%d\n", heredoc_cnt);
5264                        debug_printf_parse("parse_stream return %p\n", pi);
5265                        return pi;
5266                }
5267
5268                /* Handle "'" and "\" first, as they won't play nice with
5269                 * i_peek_and_eat_bkslash_nl() anyway:
5270                 *   echo z\\
5271                 * and
5272                 *   echo '\
5273                 *   '
5274                 * would break.
5275                 */
5276                if (ch == '\\') {
5277                        ch = i_getch(input);
5278                        if (ch == '\n')
5279                                continue; /* drop \<newline>, get next char */
5280                        nommu_addchr(&ctx.as_string, '\\');
5281                        o_addchr(&ctx.word, '\\');
5282                        if (ch == EOF) {
5283                                /* Testcase: eval 'echo Ok\' */
5284                                /* bash-4.3.43 was removing backslash,
5285                                 * but 4.4.19 retains it, most other shells too
5286                                 */
5287                                continue; /* get next char */
5288                        }
5289                        /* Example: echo Hello \2>file
5290                         * we need to know that word 2 is quoted
5291                         */
5292                        ctx.word.has_quoted_part = 1;
5293                        nommu_addchr(&ctx.as_string, ch);
5294                        o_addchr(&ctx.word, ch);
5295                        continue; /* get next char */
5296                }
5297                nommu_addchr(&ctx.as_string, ch);
5298                if (ch == '\'') {
5299                        ctx.word.has_quoted_part = 1;
5300                        next = i_getch(input);
5301                        if (next == '\'' && !ctx.pending_redirect)
5302                                goto insert_empty_quoted_str_marker;
5303
5304                        ch = next;
5305                        while (1) {
5306                                if (ch == EOF) {
5307                                        syntax_error_unterm_ch('\'');
5308                                        goto parse_error;
5309                                }
5310                                nommu_addchr(&ctx.as_string, ch);
5311                                if (ch == '\'')
5312                                        break;
5313                                if (ch == SPECIAL_VAR_SYMBOL) {
5314                                        /* Convert raw ^C to corresponding special variable reference */
5315                                        o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5316                                        o_addchr(&ctx.word, SPECIAL_VAR_QUOTED_SVS);
5317                                }
5318                                o_addqchr(&ctx.word, ch);
5319                                ch = i_getch(input);
5320                        }
5321                        continue; /* get next char */
5322                }
5323
5324                next = '\0';
5325                if (ch != '\n')
5326                        next = i_peek_and_eat_bkslash_nl(input);
5327
5328                is_special = "{}<>;&|()#" /* special outside of "str" */
5329                                "$\"" IF_HUSH_TICK("`") /* always special */
5330                                SPECIAL_VAR_SYMBOL_STR;
5331                /* Are { and } special here? */
5332                if (ctx.command->argv /* word [word]{... - non-special */
5333                 || ctx.word.length       /* word{... - non-special */
5334                 || ctx.word.has_quoted_part     /* ""{... - non-special */
5335                 || (next != ';'             /* }; - special */
5336                    && next != ')'           /* }) - special */
5337                    && next != '('           /* {( - special */
5338                    && next != '&'           /* }& and }&& ... - special */
5339                    && next != '|'           /* }|| ... - special */
5340                    && !strchr(defifs, next) /* {word - non-special */
5341                    )
5342                ) {
5343                        /* They are not special, skip "{}" */
5344                        is_special += 2;
5345                }
5346                is_special = strchr(is_special, ch);
5347                is_blank = strchr(defifs, ch);
5348
5349                if (!is_special && !is_blank) { /* ordinary char */
5350 ordinary_char:
5351                        o_addQchr(&ctx.word, ch);
5352                        if ((ctx.is_assignment == MAYBE_ASSIGNMENT
5353                            || ctx.is_assignment == WORD_IS_KEYWORD)
5354                         && ch == '='
5355                         && endofname(ctx.word.data)[0] == '='
5356                        ) {
5357                                ctx.is_assignment = DEFINITELY_ASSIGNMENT;
5358                                debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
5359                        }
5360                        continue;
5361                }
5362
5363                if (is_blank) {
5364#if ENABLE_HUSH_LINENO_VAR
5365/* Case:
5366 * "while ...; do<whitespace><newline>
5367 *      cmd ..."
5368 * would think that "cmd" starts in <whitespace> -
5369 * i.e., at the previous line.
5370 * We need to skip all whitespace before newlines.
5371 */
5372                        while (ch != '\n') {
5373                                next = i_peek(input);
5374                                if (next != ' ' && next != '\t' && next != '\n')
5375                                        break; /* next char is not ws */
5376                                ch = i_getch(input);
5377                        }
5378                        /* ch == last eaten whitespace char */
5379#endif
5380                        if (done_word(&ctx)) {
5381                                goto parse_error;
5382                        }
5383                        if (ch == '\n') {
5384                                /* Is this a case when newline is simply ignored?
5385                                 * Some examples:
5386                                 * "cmd | <newline> cmd ..."
5387                                 * "case ... in <newline> word) ..."
5388                                 */
5389                                if (IS_NULL_CMD(ctx.command)
5390                                 && ctx.word.length == 0
5391                                 && !ctx.word.has_quoted_part
5392                                 && heredoc_cnt == 0
5393                                ) {
5394                                        /* This newline can be ignored. But...
5395                                         * Without check #1, interactive shell
5396                                         * ignores even bare <newline>,
5397                                         * and shows the continuation prompt:
5398                                         * ps1_prompt$ <enter>
5399                                         * ps2> _   <=== wrong, should be ps1
5400                                         * Without check #2, "cmd & <newline>"
5401                                         * is similarly mistreated.
5402                                         * (BTW, this makes "cmd & cmd"
5403                                         * and "cmd && cmd" non-orthogonal.
5404                                         * Really, ask yourself, why
5405                                         * "cmd && <newline>" doesn't start
5406                                         * cmd but waits for more input?
5407                                         * The only reason is that it might be
5408                                         * a "cmd1 && <nl> cmd2 &" construct,
5409                                         * cmd1 may need to run in BG).
5410                                         */
5411                                        struct pipe *pi = ctx.list_head;
5412                                        if (pi->num_cmds != 0       /* check #1 */
5413                                         && pi->followup != PIPE_BG /* check #2 */
5414                                        ) {
5415                                                continue;
5416                                        }
5417                                }
5418                                /* Treat newline as a command separator. */
5419                                done_pipe(&ctx, PIPE_SEQ);
5420                                debug_printf_heredoc("heredoc_cnt:%d\n", heredoc_cnt);
5421                                if (heredoc_cnt) {
5422                                        heredoc_cnt = fetch_heredocs(&ctx.as_string, ctx.list_head, heredoc_cnt, input);
5423                                        if (heredoc_cnt != 0)
5424                                                goto parse_error;
5425                                }
5426                                ctx.is_assignment = MAYBE_ASSIGNMENT;
5427                                debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
5428                                ch = ';';
5429                                /* note: if (is_blank) continue;
5430                                 * will still trigger for us */
5431                        }
5432                }
5433
5434                /* "cmd}" or "cmd }..." without semicolon or &:
5435                 * } is an ordinary char in this case, even inside { cmd; }
5436                 * Pathological example: { ""}; } should exec "}" cmd
5437                 */
5438                if (ch == '}') {
5439                        if (ctx.word.length != 0 /* word} */
5440                         || ctx.word.has_quoted_part    /* ""} */
5441                        ) {
5442                                goto ordinary_char;
5443                        }
5444                        if (!IS_NULL_CMD(ctx.command)) { /* cmd } */
5445                                /* Generally, there should be semicolon: "cmd; }"
5446                                 * However, bash allows to omit it if "cmd" is
5447                                 * a group. Examples:
5448                                 * { { echo 1; } }
5449                                 * {(echo 1)}
5450                                 * { echo 0 >&2 | { echo 1; } }
5451                                 * { while false; do :; done }
5452                                 * { case a in b) ;; esac }
5453                                 */
5454                                if (ctx.command->group)
5455                                        goto term_group;
5456                                goto ordinary_char;
5457                        }
5458                        if (!IS_NULL_PIPE(ctx.pipe)) /* cmd | } */
5459                                /* Can't be an end of {cmd}, skip the check */
5460                                goto skip_end_trigger;
5461                        /* else: } does terminate a group */
5462                }
5463 term_group:
5464                if (end_trigger && end_trigger == ch
5465                 && (ch != ';' || heredoc_cnt == 0)
5466#if ENABLE_HUSH_CASE
5467                 && (ch != ')'
5468                    || ctx.ctx_res_w != RES_MATCH
5469                    || (!ctx.word.has_quoted_part && strcmp(ctx.word.data, "esac") == 0)
5470                    )
5471#endif
5472                ) {
5473                        if (done_word(&ctx)) {
5474                                goto parse_error;
5475                        }
5476                        done_pipe(&ctx, PIPE_SEQ);
5477                        ctx.is_assignment = MAYBE_ASSIGNMENT;
5478                        debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
5479                        /* Do we sit outside of any if's, loops or case's? */
5480                        if (!HAS_KEYWORDS
5481                        IF_HAS_KEYWORDS(|| (ctx.ctx_res_w == RES_NONE && ctx.old_flag == 0))
5482                        ) {
5483                                o_free_and_set_NULL(&ctx.word);
5484#if !BB_MMU
5485                                debug_printf_parse("as_string2 '%s'\n", ctx.as_string.data);
5486                                if (pstring)
5487                                        *pstring = ctx.as_string.data;
5488                                else
5489                                        o_free(&ctx.as_string);
5490#endif
5491                                if (ch != ';' && IS_NULL_PIPE(ctx.list_head)) {
5492                                        /* Example: bare "{ }", "()" */
5493                                        G.last_exitcode = 2; /* bash compat */
5494                                        syntax_error_unexpected_ch(ch);
5495                                        goto parse_error2;
5496                                }
5497                                if (heredoc_cnt_ptr)
5498                                        *heredoc_cnt_ptr = heredoc_cnt;
5499                                debug_printf_heredoc("parse_stream return heredoc_cnt:%d\n", heredoc_cnt);
5500                                debug_printf_parse("parse_stream return %p: "
5501                                                "end_trigger char found\n",
5502                                                ctx.list_head);
5503                                debug_leave();
5504                                return ctx.list_head;
5505                        }
5506                }
5507
5508                if (is_blank)
5509                        continue;
5510
5511                /* Catch <, > before deciding whether this word is
5512                 * an assignment. a=1 2>z b=2: b=2 is still assignment */
5513                switch (ch) {
5514                case '>':
5515                        redir_fd = redirect_opt_num(&ctx.word);
5516                        if (done_word(&ctx)) {
5517                                goto parse_error;
5518                        }
5519                        redir_style = REDIRECT_OVERWRITE;
5520                        if (next == '>') {
5521                                redir_style = REDIRECT_APPEND;
5522                                ch = i_getch(input);
5523                                nommu_addchr(&ctx.as_string, ch);
5524                        }
5525#if 0
5526                        else if (next == '(') {
5527                                syntax_error(">(process) not supported");
5528                                goto parse_error;
5529                        }
5530#endif
5531                        if (parse_redirect(&ctx, redir_fd, redir_style, input))
5532                                goto parse_error;
5533                        continue; /* get next char */
5534                case '<':
5535                        redir_fd = redirect_opt_num(&ctx.word);
5536                        if (done_word(&ctx)) {
5537                                goto parse_error;
5538                        }
5539                        redir_style = REDIRECT_INPUT;
5540                        if (next == '<') {
5541                                redir_style = REDIRECT_HEREDOC;
5542                                heredoc_cnt++;
5543                                debug_printf_heredoc("++heredoc_cnt=%d\n", heredoc_cnt);
5544                                ch = i_getch(input);
5545                                nommu_addchr(&ctx.as_string, ch);
5546                        } else if (next == '>') {
5547                                redir_style = REDIRECT_IO;
5548                                ch = i_getch(input);
5549                                nommu_addchr(&ctx.as_string, ch);
5550                        }
5551#if 0
5552                        else if (next == '(') {
5553                                syntax_error("<(process) not supported");
5554                                goto parse_error;
5555                        }
5556#endif
5557                        if (parse_redirect(&ctx, redir_fd, redir_style, input))
5558                                goto parse_error;
5559                        continue; /* get next char */
5560                case '#':
5561                        if (ctx.word.length == 0 && !ctx.word.has_quoted_part) {
5562                                /* skip "#comment" */
5563                                /* note: we do not add it to &ctx.as_string */
5564/* TODO: in bash:
5565 * comment inside $() goes to the next \n, even inside quoted string (!):
5566 * cmd "$(cmd2 #comment)" - syntax error
5567 * cmd "`cmd2 #comment`" - ok
5568 * We accept both (comment ends where command subst ends, in both cases).
5569 */
5570                                while (1) {
5571                                        ch = i_peek(input);
5572                                        if (ch == '\n') {
5573                                                nommu_addchr(&ctx.as_string, '\n');
5574                                                break;
5575                                        }
5576                                        ch = i_getch(input);
5577                                        if (ch == EOF)
5578                                                break;
5579                                }
5580                                continue; /* get next char */
5581                        }
5582                        break;
5583                }
5584 skip_end_trigger:
5585
5586                if (ctx.is_assignment == MAYBE_ASSIGNMENT
5587                 /* check that we are not in word in "a=1 2>word b=1": */
5588                 && !ctx.pending_redirect
5589                ) {
5590                        /* ch is a special char and thus this word
5591                         * cannot be an assignment */
5592                        ctx.is_assignment = NOT_ASSIGNMENT;
5593                        debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
5594                }
5595
5596                /* Note: nommu_addchr(&ctx.as_string, ch) is already done */
5597
5598                switch (ch) {
5599                case SPECIAL_VAR_SYMBOL:
5600                        /* Convert raw ^C to corresponding special variable reference */
5601                        o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5602                        o_addchr(&ctx.word, SPECIAL_VAR_QUOTED_SVS);
5603                        /* fall through */
5604                case '#':
5605                        /* non-comment #: "echo a#b" etc */
5606                        o_addchr(&ctx.word, ch);
5607                        continue; /* get next char */
5608                case '$':
5609                        if (!parse_dollar(&ctx.as_string, &ctx.word, input, /*quote_mask:*/ 0)) {
5610                                debug_printf_parse("parse_stream parse error: "
5611                                        "parse_dollar returned 0 (error)\n");
5612                                goto parse_error;
5613                        }
5614                        continue; /* get next char */
5615                case '"':
5616                        ctx.word.has_quoted_part = 1;
5617                        if (next == '"' && !ctx.pending_redirect) {
5618                                i_getch(input); /* eat second " */
5619 insert_empty_quoted_str_marker:
5620                                nommu_addchr(&ctx.as_string, next);
5621                                o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5622                                o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5623                                continue; /* get next char */
5624                        }
5625                        if (ctx.is_assignment == NOT_ASSIGNMENT)
5626                                ctx.word.o_expflags |= EXP_FLAG_ESC_GLOB_CHARS;
5627                        if (!encode_string(&ctx.as_string, &ctx.word, input, '"'))
5628                                goto parse_error;
5629                        ctx.word.o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS;
5630                        continue; /* get next char */
5631#if ENABLE_HUSH_TICK
5632                case '`': {
5633                        USE_FOR_NOMMU(unsigned pos;)
5634
5635                        o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5636                        o_addchr(&ctx.word, '`');
5637                        USE_FOR_NOMMU(pos = ctx.word.length;)
5638                        if (!add_till_backquote(&ctx.word, input, /*in_dquote:*/ 0))
5639                                goto parse_error;
5640# if !BB_MMU
5641                        o_addstr(&ctx.as_string, ctx.word.data + pos);
5642                        o_addchr(&ctx.as_string, '`');
5643# endif
5644                        o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
5645                        //debug_printf_subst("SUBST RES3 '%s'\n", ctx.word.data + pos);
5646                        continue; /* get next char */
5647                }
5648#endif
5649                case ';':
5650#if ENABLE_HUSH_CASE
5651 case_semi:
5652#endif
5653                        if (done_word(&ctx)) {
5654                                goto parse_error;
5655                        }
5656                        done_pipe(&ctx, PIPE_SEQ);
5657#if ENABLE_HUSH_CASE
5658                        /* Eat multiple semicolons, detect
5659                         * whether it means something special */
5660                        while (1) {
5661                                ch = i_peek_and_eat_bkslash_nl(input);
5662                                if (ch != ';')
5663                                        break;
5664                                ch = i_getch(input);
5665                                nommu_addchr(&ctx.as_string, ch);
5666                                if (ctx.ctx_res_w == RES_CASE_BODY) {
5667                                        ctx.ctx_dsemicolon = 1;
5668                                        ctx.ctx_res_w = RES_MATCH;
5669                                        break;
5670                                }
5671                        }
5672#endif
5673 new_cmd:
5674                        /* We just finished a cmd. New one may start
5675                         * with an assignment */
5676                        ctx.is_assignment = MAYBE_ASSIGNMENT;
5677                        debug_printf_parse("ctx.is_assignment='%s'\n", assignment_flag[ctx.is_assignment]);
5678                        continue; /* get next char */
5679                case '&':
5680                        if (done_word(&ctx)) {
5681                                goto parse_error;
5682                        }
5683                        if (next == '&') {
5684                                ch = i_getch(input);
5685                                nommu_addchr(&ctx.as_string, ch);
5686                                done_pipe(&ctx, PIPE_AND);
5687                        } else {
5688                                done_pipe(&ctx, PIPE_BG);
5689                        }
5690                        goto new_cmd;
5691                case '|':
5692                        if (done_word(&ctx)) {
5693                                goto parse_error;
5694                        }
5695#if ENABLE_HUSH_CASE
5696                        if (ctx.ctx_res_w == RES_MATCH)
5697                                break; /* we are in case's "word | word)" */
5698#endif
5699                        if (next == '|') { /* || */
5700                                ch = i_getch(input);
5701                                nommu_addchr(&ctx.as_string, ch);
5702                                done_pipe(&ctx, PIPE_OR);
5703                        } else {
5704                                /* we could pick up a file descriptor choice here
5705                                 * with redirect_opt_num(), but bash doesn't do it.
5706                                 * "echo foo 2| cat" yields "foo 2". */
5707                                done_command(&ctx);
5708                        }
5709                        goto new_cmd;
5710                case '(':
5711#if ENABLE_HUSH_CASE
5712                        /* "case... in [(]word)..." - skip '(' */
5713                        if (ctx.ctx_res_w == RES_MATCH
5714                         && ctx.command->argv == NULL /* not (word|(... */
5715                         && ctx.word.length == 0 /* not word(... */
5716                         && ctx.word.has_quoted_part == 0 /* not ""(... */
5717                        ) {
5718                                continue; /* get next char */
5719                        }
5720#endif
5721                        /* fall through */
5722                case '{': {
5723                        int n = parse_group(&ctx, input, ch);
5724                        if (n < 0) {
5725                                goto parse_error;
5726                        }
5727                        debug_printf_heredoc("parse_group done, needs heredocs:%d\n", n);
5728                        heredoc_cnt += n;
5729                        goto new_cmd;
5730                }
5731                case ')':
5732#if ENABLE_HUSH_CASE
5733                        if (ctx.ctx_res_w == RES_MATCH)
5734                                goto case_semi;
5735#endif
5736
5737                case '}':
5738                        /* proper use of this character is caught by end_trigger:
5739                         * if we see {, we call parse_group(..., end_trigger='}')
5740                         * and it will match } earlier (not here). */
5741                        G.last_exitcode = 2;
5742                        syntax_error_unexpected_ch(ch);
5743                        goto parse_error2;
5744                default:
5745                        if (HUSH_DEBUG)
5746                                bb_error_msg_and_die("BUG: unexpected %c", ch);
5747                }
5748        } /* while (1) */
5749
5750 parse_error:
5751        G.last_exitcode = 1;
5752 parse_error2:
5753        {
5754                struct parse_context *pctx;
5755                IF_HAS_KEYWORDS(struct parse_context *p2;)
5756
5757                /* Clean up allocated tree.
5758                 * Sample for finding leaks on syntax error recovery path.
5759                 * Run it from interactive shell, watch pmap `pidof hush`.
5760                 * while if false; then false; fi; do break; fi
5761                 * Samples to catch leaks at execution:
5762                 * while if (true | { true;}); then echo ok; fi; do break; done
5763                 * while if (true | { true;}); then echo ok; fi; do (if echo ok; break; then :; fi) | cat; break; done
5764                 */
5765                pctx = &ctx;
5766                do {
5767                        /* Update pipe/command counts,
5768                         * otherwise freeing may miss some */
5769                        done_pipe(pctx, PIPE_SEQ);
5770                        debug_printf_clean("freeing list %p from ctx %p\n",
5771                                        pctx->list_head, pctx);
5772                        debug_print_tree(pctx->list_head, 0);
5773                        free_pipe_list(pctx->list_head);
5774                        debug_printf_clean("freed list %p\n", pctx->list_head);
5775#if !BB_MMU
5776                        o_free(&pctx->as_string);
5777#endif
5778                        IF_HAS_KEYWORDS(p2 = pctx->stack;)
5779                        if (pctx != &ctx) {
5780                                free(pctx);
5781                        }
5782                        IF_HAS_KEYWORDS(pctx = p2;)
5783                } while (HAS_KEYWORDS && pctx);
5784
5785                o_free(&ctx.word);
5786#if !BB_MMU
5787                if (pstring)
5788                        *pstring = NULL;
5789#endif
5790                debug_leave();
5791                return ERR_PTR;
5792        }
5793}
5794
5795
5796/*** Execution routines ***/
5797
5798/* Expansion can recurse, need forward decls: */
5799#if !BASH_PATTERN_SUBST && !ENABLE_HUSH_CASE
5800#define expand_string_to_string(str, EXP_flags, do_unbackslash) \
5801        expand_string_to_string(str)
5802#endif
5803static char *expand_string_to_string(const char *str, int EXP_flags, int do_unbackslash);
5804#if ENABLE_HUSH_TICK
5805static int process_command_subs(o_string *dest, const char *s);
5806#endif
5807static int expand_vars_to_list(o_string *output, int n, char *arg);
5808
5809/* expand_strvec_to_strvec() takes a list of strings, expands
5810 * all variable references within and returns a pointer to
5811 * a list of expanded strings, possibly with larger number
5812 * of strings. (Think VAR="a b"; echo $VAR).
5813 * This new list is allocated as a single malloc block.
5814 * NULL-terminated list of char* pointers is at the beginning of it,
5815 * followed by strings themselves.
5816 * Caller can deallocate entire list by single free(list). */
5817
5818/* A horde of its helpers come first: */
5819
5820static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len)
5821{
5822        while (--len >= 0) {
5823                char c = *str++;
5824
5825#if ENABLE_HUSH_BRACE_EXPANSION
5826                if (c == '{' || c == '}') {
5827                        /* { -> \{, } -> \} */
5828                        o_addchr(o, '\\');
5829                        /* And now we want to add { or } and continue:
5830                         *  o_addchr(o, c);
5831                         *  continue;
5832                         * luckily, just falling through achieves this.
5833                         */
5834                }
5835#endif
5836                o_addchr(o, c);
5837                if (c == '\\') {
5838                        /* \z -> \\\z; \<eol> -> \\<eol> */
5839                        o_addchr(o, '\\');
5840                        if (len) {
5841                                len--;
5842                                o_addchr(o, '\\');
5843                                o_addchr(o, *str++);
5844                        }
5845                }
5846        }
5847}
5848
5849/* Store given string, finalizing the word and starting new one whenever
5850 * we encounter IFS char(s). This is used for expanding variable values.
5851 * End-of-string does NOT finalize word: think about 'echo -$VAR-'.
5852 * Return in output->ended_in_ifs:
5853 * 1 - ended with IFS char, else 0 (this includes case of empty str).
5854 */
5855static int expand_on_ifs(o_string *output, int n, const char *str)
5856{
5857        int last_is_ifs = 0;
5858
5859        while (1) {
5860                int word_len;
5861
5862                if (!*str)  /* EOL - do not finalize word */
5863                        break;
5864                word_len = strcspn(str, G.ifs);
5865                if (word_len) {
5866                        /* We have WORD_LEN leading non-IFS chars */
5867                        if (!(output->o_expflags & EXP_FLAG_GLOB)) {
5868                                o_addblock(output, str, word_len);
5869                        } else {
5870                                /* Protect backslashes against globbing up :)
5871                                 * Example: "v='\*'; echo b$v" prints "b\*"
5872                                 * (and does not try to glob on "*")
5873                                 */
5874                                o_addblock_duplicate_backslash(output, str, word_len);
5875                                /*/ Why can't we do it easier? */
5876                                /*o_addblock(output, str, word_len); - WRONG: "v='\*'; echo Z$v" prints "Z*" instead of "Z\*" */
5877                                /*o_addqblock(output, str, word_len); - WRONG: "v='*'; echo Z$v" prints "Z*" instead of Z* files */
5878                        }
5879                        last_is_ifs = 0;
5880                        str += word_len;
5881                        if (!*str)  /* EOL - do not finalize word */
5882                                break;
5883                }
5884
5885                /* We know str here points to at least one IFS char */
5886                last_is_ifs = 1;
5887                str += strspn(str, G.ifs_whitespace); /* skip IFS whitespace chars */
5888                if (!*str)  /* EOL - do not finalize word */
5889                        break;
5890
5891                if (G.ifs_whitespace != G.ifs /* usually false ($IFS is usually all whitespace), */
5892                 && strchr(G.ifs, *str)       /* the second check would fail */
5893                ) {
5894                        /* This is a non-whitespace $IFS char */
5895                        /* Skip it and IFS whitespace chars, start new word */
5896                        str++;
5897                        str += strspn(str, G.ifs_whitespace);
5898                        goto new_word;
5899                }
5900
5901                /* Start new word... but not always! */
5902                /* Case "v=' a'; echo ''$v": we do need to finalize empty word: */
5903                if (output->has_quoted_part
5904                /*
5905                 * Case "v=' a'; echo $v":
5906                 * here nothing precedes the space in $v expansion,
5907                 * therefore we should not finish the word
5908                 * (IOW: if there *is* word to finalize, only then do it):
5909                 * It's okay if this accesses the byte before first argv[]:
5910                 * past call to o_save_ptr() cleared it to zero byte
5911                 * (grep for -prev-ifs-check-).
5912                 */
5913                 || output->data[output->length - 1]
5914                ) {
5915 new_word:
5916                        o_addchr(output, '\0');
5917                        debug_print_list("expand_on_ifs", output, n);
5918                        n = o_save_ptr(output, n);
5919                }
5920        }
5921
5922        output->ended_in_ifs = last_is_ifs;
5923        debug_print_list("expand_on_ifs[1]", output, n);
5924        return n;
5925}
5926
5927/* Helper to expand $((...)) and heredoc body. These act as if
5928 * they are in double quotes, with the exception that they are not :).
5929 * Just the rules are similar: "expand only $var and `cmd`"
5930 *
5931 * Returns malloced string.
5932 * As an optimization, we return NULL if expansion is not needed.
5933 */
5934static char *encode_then_expand_string(const char *str)
5935{
5936        char *exp_str;
5937        struct in_str input;
5938        o_string dest = NULL_O_STRING;
5939        const char *cp;
5940
5941        cp = str;
5942        for (;;) {
5943                if (!*cp) return NULL; /* string has no special chars */
5944                if (*cp == '$') break;
5945                if (*cp == '\\') break;
5946#if ENABLE_HUSH_TICK
5947                if (*cp == '`') break;
5948#endif
5949                cp++;
5950        }
5951
5952        /* We need to expand. Example:
5953         * echo $(($a + `echo 1`)) $((1 + $((2)) ))
5954         */
5955        setup_string_in_str(&input, str);
5956        encode_string(NULL, &dest, &input, EOF);
5957//TODO: error check (encode_string returns 0 on error)?
5958        //bb_error_msg("'%s' -> '%s'", str, dest.data);
5959        exp_str = expand_string_to_string(dest.data,
5960                        EXP_FLAG_ESC_GLOB_CHARS,
5961                        /*unbackslash:*/ 1
5962        );
5963        //bb_error_msg("'%s' -> '%s'", dest.data, exp_str);
5964        o_free(&dest);
5965        return exp_str;
5966}
5967
5968static const char *first_special_char_in_vararg(const char *cp)
5969{
5970        for (;;) {
5971                if (!*cp) return NULL; /* string has no special chars */
5972                if (*cp == '$') return cp;
5973                if (*cp == '\\') return cp;
5974                if (*cp == '\'') return cp;
5975                if (*cp == '"') return cp;
5976#if ENABLE_HUSH_TICK
5977                if (*cp == '`') return cp;
5978#endif
5979                /* dquoted "${x:+ARG}" should not glob, therefore
5980                 * '*' et al require some non-literal processing: */
5981                if (*cp == '*') return cp;
5982                if (*cp == '?') return cp;
5983                if (*cp == '[') return cp;
5984                cp++;
5985        }
5986}
5987
5988/* Expanding ARG in ${var#ARG}, ${var%ARG}, or ${var/ARG/ARG}.
5989 * These can contain single- and double-quoted strings,
5990 * and treated as if the ARG string is initially unquoted. IOW:
5991 * ${var#ARG} and "${var#ARG}" treat ARG the same (ARG can even be
5992 * a dquoted string: "${var#"zz"}"), the difference only comes later
5993 * (word splitting and globbing of the ${var...} result).
5994 */
5995#if !BASH_PATTERN_SUBST
5996#define encode_then_expand_vararg(str, handle_squotes, do_unbackslash) \
5997        encode_then_expand_vararg(str, handle_squotes)
5998#endif
5999static char *encode_then_expand_vararg(const char *str, int handle_squotes, int do_unbackslash)
6000{
6001#if !BASH_PATTERN_SUBST && ENABLE_HUSH_CASE
6002        const int do_unbackslash = 0;
6003#endif
6004        char *exp_str;
6005        struct in_str input;
6006        o_string dest = NULL_O_STRING;
6007
6008        if (!first_special_char_in_vararg(str)) {
6009                /* string has no special chars */
6010                return NULL;
6011        }
6012
6013        setup_string_in_str(&input, str);
6014        dest.data = xzalloc(1); /* start as "", not as NULL */
6015        exp_str = NULL;
6016
6017        for (;;) {
6018                int ch;
6019
6020                ch = i_getch(&input);
6021                debug_printf_parse("%s: ch=%c (%d) escape=%d\n",
6022                                __func__, ch, ch, !!dest.o_expflags);
6023
6024                if (!dest.o_expflags) {
6025                        if (ch == EOF)
6026                                break;
6027                        if (handle_squotes && ch == '\'') {
6028                                if (!add_till_single_quote_dquoted(&dest, &input))
6029                                        goto ret; /* error */
6030                                continue;
6031                        }
6032                }
6033                if (ch == EOF) {
6034                        syntax_error_unterm_ch('"');
6035                        goto ret; /* error */
6036                }
6037                if (ch == '"') {
6038                        dest.o_expflags ^= EXP_FLAG_ESC_GLOB_CHARS;
6039                        continue;
6040                }
6041                if (ch == '\\') {
6042                        ch = i_getch(&input);
6043                        if (ch == EOF) {
6044//example? error message?       syntax_error_unterm_ch('"');
6045                                debug_printf_parse("%s: error: \\<eof>\n", __func__);
6046                                goto ret;
6047                        }
6048                        o_addqchr(&dest, ch);
6049                        continue;
6050                }
6051                if (ch == '$') {
6052                        if (!parse_dollar(NULL, &dest, &input, /*quote_mask:*/ 0x80)) {
6053                                debug_printf_parse("%s: error: parse_dollar returned 0 (error)\n", __func__);
6054                                goto ret;
6055                        }
6056                        continue;
6057                }
6058#if ENABLE_HUSH_TICK
6059                if (ch == '`') {
6060                        //unsigned pos = dest->length;
6061                        o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6062                        o_addchr(&dest, 0x80 | '`');
6063                        if (!add_till_backquote(&dest, &input,
6064                                        /*in_dquote:*/ dest.o_expflags /* nonzero if EXP_FLAG_ESC_GLOB_CHARS set */
6065                                )
6066                        ) {
6067                                goto ret; /* error */
6068                        }
6069                        o_addchr(&dest, SPECIAL_VAR_SYMBOL);
6070                        //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos);
6071                        continue;
6072                }
6073#endif