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