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