busybox/shell/ash.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * ash shell port for busybox
   4 *
   5 * This code is derived from software contributed to Berkeley by
   6 * Kenneth Almquist.
   7 *
   8 * Original BSD copyright notice is retained at the end of this file.
   9 *
  10 * Copyright (c) 1989, 1991, 1993, 1994
  11 *      The Regents of the University of California.  All rights reserved.
  12 *
  13 * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
  14 * was re-ported from NetBSD and debianized.
  15 *
  16 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  17 */
  18//config:config SHELL_ASH
  19//config:       bool #hidden option
  20//config:       depends on !NOMMU
  21//config:
  22//config:config ASH
  23//config:       bool "ash (78 kb)"
  24//config:       default y
  25//config:       depends on !NOMMU
  26//config:       select SHELL_ASH
  27//config:       help
  28//config:       The most complete and most pedantically correct shell included with
  29//config:       busybox. This shell is actually a derivative of the Debian 'dash'
  30//config:       shell (by Herbert Xu), which was created by porting the 'ash' shell
  31//config:       (written by Kenneth Almquist) from NetBSD.
  32//config:
  33//config:# ash options
  34//config:# note: Don't remove !NOMMU part in the next line; it would break
  35//config:# menuconfig's indenting.
  36//config:if !NOMMU && (SHELL_ASH || ASH || SH_IS_ASH || BASH_IS_ASH)
  37//config:
  38//config:config ASH_OPTIMIZE_FOR_SIZE
  39//config:       bool "Optimize for size instead of speed"
  40//config:       default y
  41//config:       depends on SHELL_ASH
  42//config:
  43//config:config ASH_INTERNAL_GLOB
  44//config:       bool "Use internal glob() implementation"
  45//config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
  46//config:       depends on SHELL_ASH
  47//config:       help
  48//config:       Do not use glob() function from libc, use internal implementation.
  49//config:       Use this if you are getting "glob.h: No such file or directory"
  50//config:       or similar build errors.
  51//config:       Note that as of now (2017-01), uclibc and musl glob() both have bugs
  52//config:       which would break ash if you select N here.
  53//config:
  54//config:config ASH_BASH_COMPAT
  55//config:       bool "bash-compatible extensions"
  56//config:       default y
  57//config:       depends on SHELL_ASH
  58//config:
  59//config:config ASH_BASH_SOURCE_CURDIR
  60//config:       bool "'source' and '.' builtins search current directory after $PATH"
  61//config:       default n   # do not encourage non-standard behavior
  62//config:       depends on ASH_BASH_COMPAT
  63//config:       help
  64//config:       This is not compliant with standards. Avoid if possible.
  65//config:
  66//config:config ASH_BASH_NOT_FOUND_HOOK
  67//config:       bool "command_not_found_handle hook support"
  68//config:       default y
  69//config:       depends on ASH_BASH_COMPAT
  70//config:       help
  71//config:       Enable support for the 'command_not_found_handle' hook function,
  72//config:       from GNU bash, which allows for alternative command not found
  73//config:       handling.
  74//config:
  75//config:config ASH_JOB_CONTROL
  76//config:       bool "Job control"
  77//config:       default y
  78//config:       depends on SHELL_ASH
  79//config:
  80//config:config ASH_ALIAS
  81//config:       bool "Alias support"
  82//config:       default y
  83//config:       depends on SHELL_ASH
  84//config:
  85//config:config ASH_RANDOM_SUPPORT
  86//config:       bool "Pseudorandom generator and $RANDOM variable"
  87//config:       default y
  88//config:       depends on SHELL_ASH
  89//config:       help
  90//config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
  91//config:       Each read of "$RANDOM" will generate a new pseudorandom value.
  92//config:       You can reset the generator by using a specified start value.
  93//config:       After "unset RANDOM" the generator will switch off and this
  94//config:       variable will no longer have special treatment.
  95//config:
  96//config:config ASH_EXPAND_PRMT
  97//config:       bool "Expand prompt string"
  98//config:       default y
  99//config:       depends on SHELL_ASH
 100//config:       help
 101//config:       $PS# may contain volatile content, such as backquote commands.
 102//config:       This option recreates the prompt string from the environment
 103//config:       variable each time it is displayed.
 104//config:
 105//config:config ASH_IDLE_TIMEOUT
 106//config:       bool "Idle timeout variable $TMOUT"
 107//config:       default y
 108//config:       depends on SHELL_ASH
 109//config:       help
 110//config:       Enable bash-like auto-logout after $TMOUT seconds of idle time.
 111//config:
 112//config:config ASH_MAIL
 113//config:       bool "Check for new mail in interactive shell"
 114//config:       default y
 115//config:       depends on SHELL_ASH
 116//config:       help
 117//config:       Enable "check for new mail" function:
 118//config:       if set, $MAIL file and $MAILPATH list of files
 119//config:       are checked for mtime changes, and "you have mail"
 120//config:       message is printed if change is detected.
 121//config:
 122//config:config ASH_ECHO
 123//config:       bool "echo builtin"
 124//config:       default y
 125//config:       depends on SHELL_ASH
 126//config:
 127//config:config ASH_PRINTF
 128//config:       bool "printf builtin"
 129//config:       default y
 130//config:       depends on SHELL_ASH
 131//config:
 132//config:config ASH_TEST
 133//config:       bool "test builtin"
 134//config:       default y
 135//config:       depends on SHELL_ASH
 136//config:
 137//config:config ASH_HELP
 138//config:       bool "help builtin"
 139//config:       default y
 140//config:       depends on SHELL_ASH
 141//config:
 142//config:config ASH_GETOPTS
 143//config:       bool "getopts builtin"
 144//config:       default y
 145//config:       depends on SHELL_ASH
 146//config:
 147//config:config ASH_CMDCMD
 148//config:       bool "command builtin"
 149//config:       default y
 150//config:       depends on SHELL_ASH
 151//config:       help
 152//config:       Enable support for the 'command' builtin, which allows
 153//config:       you to run the specified command or builtin,
 154//config:       even when there is a function with the same name.
 155//config:
 156//config:endif # ash options
 157
 158//applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
 159//                      APPLET_ODDNAME:name  main location    suid_type     help
 160//applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
 161//applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
 162
 163//kbuild:lib-$(CONFIG_SHELL_ASH) += ash.o ash_ptr_hack.o shell_common.o
 164//kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
 165
 166/*
 167 * DEBUG=1 to compile in debugging ('set -o debug' turns on)
 168 * DEBUG=2 to compile in and turn on debugging.
 169 * When debugging is on ("set -o debug" was executed, or DEBUG=2),
 170 * debugging info is written to ./trace, quit signal generates core dump.
 171 */
 172#define DEBUG 0
 173/* Tweak debug output verbosity here */
 174#define DEBUG_TIME 0
 175#define DEBUG_PID 1
 176#define DEBUG_SIG 1
 177#define DEBUG_INTONOFF 0
 178
 179#define PROFILE 0
 180
 181#define JOBS ENABLE_ASH_JOB_CONTROL
 182
 183#include <fnmatch.h>
 184#include <sys/times.h>
 185#include <sys/utsname.h> /* for setting $HOSTNAME */
 186#include "busybox.h" /* for applet_names */
 187#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS
 188# include "embedded_scripts.h"
 189#else
 190# define NUM_SCRIPTS 0
 191#endif
 192
 193/* So far, all bash compat is controlled by one config option */
 194/* Separate defines document which part of code implements what */
 195/* function keyword */
 196#define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
 197#define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
 198/* &>file */
 199#define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
 200#define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
 201/* $'...' */
 202#define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
 203#define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
 204#define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
 205#define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
 206#define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
 207#define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
 208/* BASH_TEST2: [[ EXPR ]]
 209 * Status of [[ support:
 210 *   && and || work as they should
 211 *   = is glob match operator, not equality operator: STR = GLOB
 212 *   == same as =
 213 *   =~ is regex match operator: STR =~ REGEX
 214 * TODO:
 215 * singleword+noglob expansion:
 216 *   v='a b'; [[ $v = 'a b' ]]; echo 0:$?
 217 *   [[ /bin/n* ]]; echo 0:$?
 218 * quoting needs to be considered (-f is an operator, "-f" and ""-f are not; etc)
 219 * ( ) < > should not have special meaning (IOW: should not require quoting)
 220 * in word = GLOB, quoting should be significant on char-by-char basis: a*cd"*"
 221 */
 222#define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
 223#define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
 224#define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
 225#define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
 226#define    BASH_EPOCH_VARS      ENABLE_ASH_BASH_COMPAT
 227#define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
 228#define    BASH_XTRACEFD        ENABLE_ASH_BASH_COMPAT
 229#define    BASH_READ_D          ENABLE_ASH_BASH_COMPAT
 230#define IF_BASH_READ_D              IF_ASH_BASH_COMPAT
 231#define    BASH_WAIT_N          ENABLE_ASH_BASH_COMPAT
 232/* <(...) and >(...) */
 233#if HAVE_DEV_FD
 234# define    BASH_PROCESS_SUBST   ENABLE_ASH_BASH_COMPAT
 235# define IF_BASH_PROCESS_SUBST       IF_ASH_BASH_COMPAT
 236#else
 237# define    BASH_PROCESS_SUBST 0
 238# define IF_BASH_PROCESS_SUBST(...)
 239#endif
 240
 241#if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
 242/* Bionic at least up to version 24 has no glob() */
 243# undef  ENABLE_ASH_INTERNAL_GLOB
 244# define ENABLE_ASH_INTERNAL_GLOB 1
 245#endif
 246
 247#if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
 248# error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
 249# error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
 250# error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
 251# error glob() should unbackslash them and match. uClibc does not unbackslash,
 252# error fails to match dirname, subsequently not expanding <pattern> in it.
 253// Testcase:
 254// if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
 255// if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
 256#endif
 257
 258#if !ENABLE_ASH_INTERNAL_GLOB
 259# include <glob.h>
 260#endif
 261
 262#include "unicode.h"
 263#include "shell_common.h"
 264#if ENABLE_FEATURE_SH_MATH
 265# include "math.h"
 266#else
 267typedef long arith_t;
 268# define ARITH_FMT "%ld"
 269#endif
 270#if ENABLE_ASH_RANDOM_SUPPORT
 271# include "random.h"
 272#else
 273# define CLEAR_RANDOM_T(rnd) ((void)0)
 274#endif
 275
 276#include "NUM_APPLETS.h"
 277#if NUM_APPLETS == 1
 278/* STANDALONE does not make sense, and won't compile */
 279# undef CONFIG_FEATURE_SH_STANDALONE
 280# undef ENABLE_FEATURE_SH_STANDALONE
 281# undef IF_FEATURE_SH_STANDALONE
 282# undef IF_NOT_FEATURE_SH_STANDALONE
 283# define ENABLE_FEATURE_SH_STANDALONE 0
 284# define IF_FEATURE_SH_STANDALONE(...)
 285# define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
 286#endif
 287
 288#ifndef F_DUPFD_CLOEXEC
 289# define F_DUPFD_CLOEXEC F_DUPFD
 290#endif
 291#ifndef O_CLOEXEC
 292# define O_CLOEXEC 0
 293#endif
 294#ifndef PIPE_BUF
 295# define PIPE_BUF 4096           /* amount of buffering in a pipe */
 296#endif
 297
 298#if !BB_MMU
 299# error "Do not even bother, ash will not run on NOMMU machine"
 300#endif
 301
 302/* We use a trick to have more optimized code (fewer pointer reloads):
 303 *  ash.c:   extern struct globals *const ash_ptr_to_globals;
 304 *  ash_ptr_hack.c: struct globals *ash_ptr_to_globals;
 305 * This way, compiler in ash.c knows the pointer can not change.
 306 *
 307 * However, this may break on weird arches or toolchains. In this case,
 308 * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable
 309 * this optimization.
 310 */
 311#ifndef BB_GLOBAL_CONST
 312# define BB_GLOBAL_CONST const
 313#endif
 314
 315
 316/* ============ Hash table sizes. Configurable. */
 317
 318#define VTABSIZE 39
 319#define ATABSIZE 39
 320#define CMDTABLESIZE 31         /* should be prime */
 321
 322
 323/* ============ Shell options */
 324
 325/* If you add/change options hare, update --help text too */
 326static const char *const optletters_optnames[] = {
 327        "e"   "errexit",
 328        "f"   "noglob",
 329/* bash has '-o ignoreeof', but no short synonym -I for it */
 330/* (in bash, set -I disables invisible variables (what's that?)) */
 331        "I"   "ignoreeof",
 332/* The below allowed this invocation:
 333 * ash -c 'set -i; echo $-; sleep 5; echo $-'
 334 * to be ^C-ed and get to interactive ash prompt.
 335 * bash does not support such "set -i".
 336 * In our code, this is denoted by empty long name:
 337 */
 338        "i"   "",
 339/* (removing "i" altogether would remove it from "$-", not good) */
 340        "m"   "monitor",
 341        "n"   "noexec",
 342/* Ditto: bash has no "set -s", "set -c" */
 343        "s"   "",
 344        "c"   "",
 345        "x"   "xtrace",
 346        "v"   "verbose",
 347        "C"   "noclobber",
 348        "a"   "allexport",
 349        "b"   "notify",
 350        "u"   "nounset",
 351        "\0"  "vi"
 352#if BASH_PIPEFAIL
 353        ,"\0"  "pipefail"
 354#endif
 355#if DEBUG
 356        ,"\0"  "nolog"
 357        ,"\0"  "debug"
 358#endif
 359};
 360//bash 4.4.23 also has these opts (with these defaults):
 361//braceexpand           on
 362//emacs                 on
 363//errtrace              off
 364//functrace             off
 365//hashall               on
 366//histexpand            off
 367//history               on
 368//interactive-comments  on
 369//keyword               off
 370//onecmd                off
 371//physical              off
 372//posix                 off
 373//privileged            off
 374
 375#define optletters(n)  optletters_optnames[n][0]
 376#define optnames(n)   (optletters_optnames[n] + 1)
 377
 378enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
 379
 380
 381/* ============ Misc data */
 382
 383#define msg_illnum "Illegal number: %s"
 384
 385/*
 386 * We enclose jmp_buf in a structure so that we can declare pointers to
 387 * jump locations.  The global variable handler contains the location to
 388 * jump to when an exception occurs, and the global variable exception_type
 389 * contains a code identifying the exception.  To implement nested
 390 * exception handlers, the user should save the value of handler on entry
 391 * to an inner scope, set handler to point to a jmploc structure for the
 392 * inner scope, and restore handler on exit from the scope.
 393 */
 394struct jmploc {
 395        jmp_buf loc;
 396};
 397
 398struct globals_misc {
 399        uint8_t exitstatus;     /* exit status of last command */
 400        uint8_t back_exitstatus;/* exit status of backquoted command */
 401        smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
 402        int savestatus;         /* exit status of last command outside traps */
 403        int rootpid;            /* pid of main shell */
 404        /* shell level: 0 for the main shell, 1 for its children, and so on */
 405        int shlvl;
 406#define rootshell (!shlvl)
 407        int errlinno;
 408
 409        char *minusc;  /* argument to -c option */
 410
 411        char *curdir; // = nullstr;     /* current working directory */
 412        char *physdir; // = nullstr;    /* physical working directory */
 413
 414        char *arg0; /* value of $0 */
 415
 416        struct jmploc *exception_handler;
 417
 418        volatile int suppress_int; /* counter */
 419        volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
 420        volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
 421        volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
 422        smallint exception_type; /* kind of exception: */
 423#define EXINT 0         /* SIGINT received */
 424#define EXERROR 1       /* a generic error */
 425#define EXEND 3         /* exit the shell */
 426#define EXEXIT 4        /* exit the shell via exitcmd */
 427
 428        char nullstr[1];        /* zero length string */
 429
 430        char optlist[NOPTS];
 431#define eflag optlist[0]
 432#define fflag optlist[1]
 433#define Iflag optlist[2]
 434#define iflag optlist[3]
 435#define mflag optlist[4]
 436#define nflag optlist[5]
 437#define sflag optlist[6]
 438#define cflag optlist[7]
 439#define xflag optlist[8]
 440#define vflag optlist[9]
 441#define Cflag optlist[10]
 442#define aflag optlist[11]
 443#define bflag optlist[12]
 444#define uflag optlist[13]
 445#define viflag optlist[14]
 446#if BASH_PIPEFAIL
 447# define pipefail optlist[15]
 448#else
 449# define pipefail 0
 450#endif
 451#if DEBUG
 452# define nolog optlist[15 + BASH_PIPEFAIL]
 453# define debug optlist[16 + BASH_PIPEFAIL]
 454#endif
 455
 456        /* trap handler commands */
 457        /*
 458         * Sigmode records the current value of the signal handlers for the various
 459         * modes.  A value of zero means that the current handler is not known.
 460         * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
 461         */
 462        char sigmode[NSIG - 1];
 463#define S_DFL      1            /* default signal handling (SIG_DFL) */
 464#define S_CATCH    2            /* signal is caught */
 465#define S_IGN      3            /* signal is ignored (SIG_IGN) */
 466#define S_HARD_IGN 4            /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
 467
 468        /* indicates specified signal received */
 469        uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
 470        uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
 471        char *trap[NSIG];
 472        char **trap_ptr;        /* used only by "trap hack" */
 473
 474        /* Rarely referenced stuff */
 475#if ENABLE_ASH_RANDOM_SUPPORT
 476        random_t random_gen;
 477#endif
 478        pid_t backgndpid;        /* pid of last background process */
 479};
 480extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc;
 481#define G_misc (*ash_ptr_to_globals_misc)
 482#define exitstatus        (G_misc.exitstatus )
 483#define back_exitstatus   (G_misc.back_exitstatus )
 484#define job_warning       (G_misc.job_warning)
 485#define savestatus  (G_misc.savestatus )
 486#define rootpid     (G_misc.rootpid    )
 487#define shlvl       (G_misc.shlvl      )
 488#define errlinno    (G_misc.errlinno   )
 489#define minusc      (G_misc.minusc     )
 490#define curdir      (G_misc.curdir     )
 491#define physdir     (G_misc.physdir    )
 492#define arg0        (G_misc.arg0       )
 493#define exception_handler (G_misc.exception_handler)
 494#define exception_type    (G_misc.exception_type   )
 495#define suppress_int      (G_misc.suppress_int     )
 496#define pending_int       (G_misc.pending_int      )
 497#define got_sigchld       (G_misc.got_sigchld      )
 498#define pending_sig       (G_misc.pending_sig      )
 499#define nullstr     (G_misc.nullstr    )
 500#define optlist     (G_misc.optlist    )
 501#define sigmode     (G_misc.sigmode    )
 502#define gotsig      (G_misc.gotsig     )
 503#define may_have_traps    (G_misc.may_have_traps   )
 504#define trap        (G_misc.trap       )
 505#define trap_ptr    (G_misc.trap_ptr   )
 506#define random_gen  (G_misc.random_gen )
 507#define backgndpid  (G_misc.backgndpid )
 508#define INIT_G_misc() do { \
 509        (*(struct globals_misc**)not_const_pp(&ash_ptr_to_globals_misc)) = xzalloc(sizeof(G_misc)); \
 510        barrier(); \
 511        savestatus = -1; \
 512        curdir = nullstr; \
 513        physdir = nullstr; \
 514        trap_ptr = trap; \
 515} while (0)
 516
 517
 518/* ============ DEBUG */
 519#if DEBUG
 520static void trace_printf(const char *fmt, ...);
 521static void trace_vprintf(const char *fmt, va_list va);
 522# define TRACE(param)    trace_printf param
 523# define TRACEV(param)   trace_vprintf param
 524# define close(fd) do { \
 525        int dfd = (fd); \
 526        if (close(dfd) < 0) \
 527                bb_error_msg("bug on %d: closing %d(0x%x)", \
 528                        __LINE__, dfd, dfd); \
 529} while (0)
 530#else
 531# define TRACE(param)
 532# define TRACEV(param)
 533#endif
 534
 535
 536/* ============ Utility functions */
 537#define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
 538#define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
 539
 540static int
 541isdigit_str9(const char *str)
 542{
 543        int maxlen = 9 + 1; /* max 9 digits: 999999999 */
 544        while (--maxlen && isdigit(*str))
 545                str++;
 546        return (*str == '\0');
 547}
 548
 549static const char *
 550var_end(const char *var)
 551{
 552        while (*var)
 553                if (*var++ == '=')
 554                        break;
 555        return var;
 556}
 557
 558
 559/* ============ Parser data */
 560
 561/*
 562 * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
 563 */
 564struct strlist {
 565        struct strlist *next;
 566        char *text;
 567};
 568
 569struct alias;
 570
 571struct strpush {
 572        struct strpush *prev;   /* preceding string on stack */
 573        char *prev_string;
 574        int prev_left_in_line;
 575#if ENABLE_ASH_ALIAS
 576        struct alias *ap;       /* if push was associated with an alias */
 577#endif
 578        char *string;           /* remember the string since it may change */
 579
 580        /* Remember last two characters for pungetc. */
 581        int lastc[2];
 582
 583        /* Number of outstanding calls to pungetc. */
 584        int unget;
 585};
 586
 587/*
 588 * The parsefile structure pointed to by the global variable parsefile
 589 * contains information about the current file being read.
 590 */
 591struct parsefile {
 592        struct parsefile *prev; /* preceding file on stack */
 593        int linno;              /* current line */
 594        int pf_fd;              /* file descriptor (or -1 if string) */
 595        int left_in_line;       /* number of chars left in this line */
 596        int left_in_buffer;     /* number of chars left in this buffer past the line */
 597        char *next_to_pgetc;    /* next char in buffer */
 598        char *buf;              /* input buffer */
 599        struct strpush *strpush; /* for pushing strings at this level */
 600        struct strpush basestrpush; /* so pushing one is fast */
 601
 602        /* Remember last two characters for pungetc. */
 603        int lastc[2];
 604
 605        /* Number of outstanding calls to pungetc. */
 606        int unget;
 607};
 608
 609static struct parsefile basepf;        /* top level input file */
 610static struct parsefile *g_parsefile = &basepf;  /* current input file */
 611static char *commandname;              /* currently executing command */
 612
 613
 614/* ============ Interrupts / exceptions */
 615
 616static void exitshell(void) NORETURN;
 617
 618/*
 619 * These macros allow the user to suspend the handling of interrupt signals
 620 * over a period of time.  This is similar to SIGHOLD or to sigblock, but
 621 * much more efficient and portable.  (But hacking the kernel is so much
 622 * more fun than worrying about efficiency and portability. :-))
 623 */
 624#if DEBUG_INTONOFF
 625# define INT_OFF do { \
 626        TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
 627        suppress_int++; \
 628        barrier(); \
 629} while (0)
 630#else
 631# define INT_OFF do { \
 632        suppress_int++; \
 633        barrier(); \
 634} while (0)
 635#endif
 636
 637/*
 638 * Called to raise an exception.  Since C doesn't include exceptions, we
 639 * just do a longjmp to the exception handler.  The type of exception is
 640 * stored in the global variable "exception_type".
 641 */
 642static void raise_exception(int) NORETURN;
 643static void
 644raise_exception(int e)
 645{
 646#if DEBUG
 647        if (exception_handler == NULL)
 648                abort();
 649#endif
 650        INT_OFF;
 651        exception_type = e;
 652        longjmp(exception_handler->loc, 1);
 653}
 654#if DEBUG
 655#define raise_exception(e) do { \
 656        TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
 657        raise_exception(e); \
 658} while (0)
 659#endif
 660
 661/*
 662 * Called when a SIGINT is received.  (If the user specifies
 663 * that SIGINT is to be trapped or ignored using the trap builtin, then
 664 * this routine is not called.)  Suppressint is nonzero when interrupts
 665 * are held using the INT_OFF macro.  (The test for iflag is just
 666 * defensive programming.)
 667 */
 668static void raise_interrupt(void) NORETURN;
 669static void
 670raise_interrupt(void)
 671{
 672        pending_int = 0;
 673        /* Signal is not automatically unmasked after it is raised,
 674         * do it ourself - unmask all signals */
 675        sigprocmask_allsigs(SIG_UNBLOCK);
 676        /* pending_sig = 0; - now done in signal_handler() */
 677
 678        if (!(rootshell && iflag)) {
 679                /* Kill ourself with SIGINT */
 680                signal(SIGINT, SIG_DFL);
 681                raise(SIGINT);
 682        }
 683        /* bash: ^C even on empty command line sets $? */
 684        exitstatus = SIGINT + 128;
 685        raise_exception(EXINT);
 686        /* NOTREACHED */
 687}
 688#if DEBUG
 689#define raise_interrupt() do { \
 690        TRACE(("raising interrupt on line %d\n", __LINE__)); \
 691        raise_interrupt(); \
 692} while (0)
 693#endif
 694
 695static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
 696int_on(void)
 697{
 698        barrier();
 699        if (--suppress_int == 0 && pending_int) {
 700                raise_interrupt();
 701        }
 702}
 703#if DEBUG_INTONOFF
 704# define INT_ON do { \
 705        TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
 706        int_on(); \
 707} while (0)
 708#else
 709# define INT_ON int_on()
 710#endif
 711static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
 712force_int_on(void)
 713{
 714        barrier();
 715        suppress_int = 0;
 716        if (pending_int)
 717                raise_interrupt();
 718}
 719#define FORCE_INT_ON force_int_on()
 720
 721#define SAVE_INT(v) ((v) = suppress_int)
 722
 723#define RESTORE_INT(v) do { \
 724        barrier(); \
 725        suppress_int = (v); \
 726        if (suppress_int == 0 && pending_int) \
 727                raise_interrupt(); \
 728} while (0)
 729
 730
 731/* ============ Stdout/stderr output */
 732
 733static void
 734outstr(const char *p, FILE *file)
 735{
 736        INT_OFF;
 737        fputs(p, file);
 738        INT_ON;
 739}
 740
 741static void
 742flush_stdout_stderr(void)
 743{
 744        INT_OFF;
 745        fflush_all();
 746        INT_ON;
 747}
 748
 749/* Was called outcslow(c,FILE*), but c was always '\n' */
 750static void
 751newline_and_flush(FILE *dest)
 752{
 753        INT_OFF;
 754        putc('\n', dest);
 755        fflush(dest);
 756        INT_ON;
 757}
 758
 759static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
 760static int
 761out1fmt(const char *fmt, ...)
 762{
 763        va_list ap;
 764        int r;
 765
 766        INT_OFF;
 767        va_start(ap, fmt);
 768        r = vprintf(fmt, ap);
 769        va_end(ap);
 770        INT_ON;
 771        return r;
 772}
 773
 774static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
 775static int
 776fmtstr(char *outbuf, size_t length, const char *fmt, ...)
 777{
 778        va_list ap;
 779        int ret;
 780
 781        INT_OFF;
 782        va_start(ap, fmt);
 783        ret = vsnprintf(outbuf, length, fmt, ap);
 784        va_end(ap);
 785        INT_ON;
 786        return ret > (int)length ? length : ret;
 787}
 788
 789static void
 790out1str(const char *p)
 791{
 792        outstr(p, stdout);
 793}
 794
 795static void
 796out2str(const char *p)
 797{
 798        outstr(p, stderr);
 799        flush_stdout_stderr();
 800}
 801
 802
 803/* ============ Parser structures */
 804
 805/* control characters in argument strings */
 806#define CTL_FIRST CTLESC
 807#define CTLESC       ((unsigned char)'\201')    /* escape next character */
 808#define CTLVAR       ((unsigned char)'\202')    /* variable defn */
 809#define CTLENDVAR    ((unsigned char)'\203')
 810#define CTLBACKQ     ((unsigned char)'\204')
 811#define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
 812#define CTLENDARI    ((unsigned char)'\207')
 813#define CTLQUOTEMARK ((unsigned char)'\210')
 814#define CTL_LAST CTLQUOTEMARK
 815#if BASH_PROCESS_SUBST
 816# define CTLTOPROC    ((unsigned char)'\211')
 817# define CTLFROMPROC  ((unsigned char)'\212')
 818# undef CTL_LAST
 819# define CTL_LAST CTLFROMPROC
 820#endif
 821
 822/* variable substitution byte (follows CTLVAR) */
 823#define VSTYPE  0x0f            /* type of variable substitution */
 824#define VSNUL   0x10            /* colon--treat the empty string as unset */
 825
 826/* values of VSTYPE field */
 827#define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
 828#define VSMINUS         0x2     /* ${var-text} */
 829#define VSPLUS          0x3     /* ${var+text} */
 830#define VSQUESTION      0x4     /* ${var?message} */
 831#define VSASSIGN        0x5     /* ${var=text} */
 832#define VSTRIMRIGHT     0x6     /* ${var%pattern} */
 833#define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
 834#define VSTRIMLEFT      0x8     /* ${var#pattern} */
 835#define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
 836#define VSLENGTH        0xa     /* ${#var} */
 837#if BASH_SUBSTR
 838#define VSSUBSTR        0xc     /* ${var:position:length} */
 839#endif
 840#if BASH_PATTERN_SUBST
 841#define VSREPLACE       0xd     /* ${var/pattern/replacement} */
 842#define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
 843#endif
 844
 845static const char dolatstr[] ALIGN1 = {
 846        CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
 847};
 848#define DOLATSTRLEN 6
 849
 850#define NCMD      0
 851#define NPIPE     1
 852#define NREDIR    2
 853#define NBACKGND  3
 854#define NSUBSHELL 4
 855#define NAND      5
 856#define NOR       6
 857#define NSEMI     7
 858#define NIF       8
 859#define NWHILE    9
 860#define NUNTIL   10
 861#define NFOR     11
 862#define NCASE    12
 863#define NCLIST   13
 864#define NDEFUN   14
 865#define NARG     15
 866#define NTO      16
 867#if BASH_REDIR_OUTPUT
 868#define NTO2     17
 869#endif
 870#define NCLOBBER 18
 871#define NFROM    19
 872#define NFROMTO  20
 873#define NAPPEND  21
 874#define NTOFD    22
 875#define NFROMFD  23
 876#define NHERE    24
 877#define NXHERE   25
 878#define NNOT     26
 879#define N_NUMBER 27
 880
 881union node;
 882
 883struct ncmd {
 884        smallint type; /* Nxxxx */
 885        int linno;
 886        union node *assign;
 887        union node *args;
 888        union node *redirect;
 889};
 890
 891struct npipe {
 892        smallint type;
 893        smallint pipe_backgnd;
 894        struct nodelist *cmdlist;
 895};
 896
 897struct nredir {
 898        smallint type;
 899        int linno;
 900        union node *n;
 901        union node *redirect;
 902};
 903
 904struct nbinary {
 905        smallint type;
 906        union node *ch1;
 907        union node *ch2;
 908};
 909
 910struct nif {
 911        smallint type;
 912        union node *test;
 913        union node *ifpart;
 914        union node *elsepart;
 915};
 916
 917struct nfor {
 918        smallint type;
 919        int linno;
 920        union node *args;
 921        union node *body;
 922        char *var;
 923};
 924
 925struct ncase {
 926        smallint type;
 927        int linno;
 928        union node *expr;
 929        union node *cases;
 930};
 931
 932struct nclist {
 933        smallint type;
 934        union node *next;
 935        union node *pattern;
 936        union node *body;
 937};
 938
 939struct ndefun {
 940        smallint type;
 941        int linno;
 942        char *text;
 943        union node *body;
 944};
 945
 946struct narg {
 947        smallint type;
 948        union node *next;
 949        char *text;
 950        struct nodelist *backquote;
 951};
 952
 953/* nfile and ndup layout must match!
 954 * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
 955 * that it is actually NTO2 (>&file), and change its type.
 956 */
 957struct nfile {
 958        smallint type;
 959        union node *next;
 960        int fd;
 961        int _unused_dupfd;
 962        union node *fname;
 963        char *expfname;
 964};
 965
 966struct ndup {
 967        smallint type;
 968        union node *next;
 969        int fd;
 970        int dupfd;
 971        union node *vname;
 972        char *_unused_expfname;
 973};
 974
 975struct nhere {
 976        smallint type;
 977        union node *next;
 978        int fd;
 979        union node *doc;
 980};
 981
 982struct nnot {
 983        smallint type;
 984        union node *com;
 985};
 986
 987union node {
 988        smallint type;
 989        struct ncmd ncmd;
 990        struct npipe npipe;
 991        struct nredir nredir;
 992        struct nbinary nbinary;
 993        struct nif nif;
 994        struct nfor nfor;
 995        struct ncase ncase;
 996        struct nclist nclist;
 997        struct ndefun ndefun;
 998        struct narg narg;
 999        struct nfile nfile;
1000        struct ndup ndup;
1001        struct nhere nhere;
1002        struct nnot nnot;
1003};
1004
1005/*
1006 * NODE_EOF is returned by parsecmd when it encounters an end of file.
1007 * It must be distinct from NULL.
1008 */
1009#define NODE_EOF ((union node *) -1L)
1010
1011struct nodelist {
1012        struct nodelist *next;
1013        union node *n;
1014};
1015
1016struct funcnode {
1017        int count;
1018        union node n;
1019};
1020
1021/*
1022 * Free a parse tree.
1023 */
1024static void
1025freefunc(struct funcnode *f)
1026{
1027        if (f && --f->count < 0)
1028                free(f);
1029}
1030
1031
1032/* ============ Debugging output */
1033
1034#if DEBUG
1035
1036static FILE *tracefile;
1037
1038static void
1039trace_printf(const char *fmt, ...)
1040{
1041        va_list va;
1042
1043        if (debug != 1)
1044                return;
1045        if (DEBUG_TIME)
1046                fprintf(tracefile, "%u ", (int) time(NULL));
1047        if (DEBUG_PID)
1048                fprintf(tracefile, "[%u] ", (int) getpid());
1049        if (DEBUG_SIG)
1050                fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
1051        va_start(va, fmt);
1052        vfprintf(tracefile, fmt, va);
1053        va_end(va);
1054}
1055
1056static void
1057trace_vprintf(const char *fmt, va_list va)
1058{
1059        if (debug != 1)
1060                return;
1061        vfprintf(tracefile, fmt, va);
1062        fprintf(tracefile, "\n");
1063}
1064
1065static void
1066trace_puts(const char *s)
1067{
1068        if (debug != 1)
1069                return;
1070        fputs(s, tracefile);
1071}
1072
1073static void
1074trace_puts_quoted(char *s)
1075{
1076        char *p;
1077        char c;
1078
1079        if (debug != 1)
1080                return;
1081        putc('"', tracefile);
1082        for (p = s; *p; p++) {
1083                switch ((unsigned char)*p) {
1084                case '\n': c = 'n'; goto backslash;
1085                case '\t': c = 't'; goto backslash;
1086                case '\r': c = 'r'; goto backslash;
1087                case '\"': c = '\"'; goto backslash;
1088                case '\\': c = '\\'; goto backslash;
1089                case CTLESC: c = 'e'; goto backslash;
1090                case CTLVAR: c = 'v'; goto backslash;
1091                case CTLBACKQ: c = 'q'; goto backslash;
1092#if BASH_PROCESS_SUBST
1093                case CTLTOPROC: c = 'p'; goto backslash;
1094                case CTLFROMPROC: c = 'P'; goto backslash;
1095#endif
1096 backslash:
1097                        putc('\\', tracefile);
1098                        putc(c, tracefile);
1099                        break;
1100                default:
1101                        if (*p >= ' ' && *p <= '~')
1102                                putc(*p, tracefile);
1103                        else {
1104                                putc('\\', tracefile);
1105                                putc((*p >> 6) & 03, tracefile);
1106                                putc((*p >> 3) & 07, tracefile);
1107                                putc(*p & 07, tracefile);
1108                        }
1109                        break;
1110                }
1111        }
1112        putc('"', tracefile);
1113}
1114
1115static void
1116trace_puts_args(char **ap)
1117{
1118        if (debug != 1)
1119                return;
1120        if (!*ap)
1121                return;
1122        while (1) {
1123                trace_puts_quoted(*ap);
1124                if (!*++ap) {
1125                        putc('\n', tracefile);
1126                        break;
1127                }
1128                putc(' ', tracefile);
1129        }
1130}
1131
1132static void
1133opentrace(void)
1134{
1135        char s[100];
1136#ifdef O_APPEND
1137        int flags;
1138#endif
1139
1140        if (debug != 1) {
1141                if (tracefile)
1142                        fflush(tracefile);
1143                /* leave open because libedit might be using it */
1144                return;
1145        }
1146        strcpy(s, "./trace");
1147        if (tracefile) {
1148                if (!freopen(s, "a", tracefile)) {
1149                        fprintf(stderr, "Can't re-open %s\n", s);
1150                        debug = 0;
1151                        return;
1152                }
1153        } else {
1154                tracefile = fopen(s, "a");
1155                if (tracefile == NULL) {
1156                        fprintf(stderr, "Can't open %s\n", s);
1157                        debug = 0;
1158                        return;
1159                }
1160        }
1161#ifdef O_APPEND
1162        flags = fcntl(fileno(tracefile), F_GETFL);
1163        if (flags >= 0)
1164                fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
1165#endif
1166        setlinebuf(tracefile);
1167        fputs("\nTracing started.\n", tracefile);
1168}
1169
1170static void
1171indent(int amount, char *pfx, FILE *fp)
1172{
1173        int i;
1174
1175        for (i = 0; i < amount; i++) {
1176                if (pfx && i == amount - 1)
1177                        fputs(pfx, fp);
1178                putc('\t', fp);
1179        }
1180}
1181
1182/* little circular references here... */
1183static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1184
1185static void
1186sharg(union node *arg, FILE *fp)
1187{
1188        char *p;
1189        struct nodelist *bqlist;
1190        unsigned char subtype;
1191
1192        if (arg->type != NARG) {
1193                out1fmt("<node type %d>\n", arg->type);
1194                abort();
1195        }
1196        bqlist = arg->narg.backquote;
1197        for (p = arg->narg.text; *p; p++) {
1198                switch ((unsigned char)*p) {
1199                case CTLESC:
1200                        p++;
1201                        putc(*p, fp);
1202                        break;
1203                case CTLVAR:
1204                        putc('$', fp);
1205                        putc('{', fp);
1206                        subtype = *++p;
1207                        if (subtype == VSLENGTH)
1208                                putc('#', fp);
1209
1210                        while (*p != '=') {
1211                                putc(*p, fp);
1212                                p++;
1213                        }
1214
1215                        if (subtype & VSNUL)
1216                                putc(':', fp);
1217
1218                        switch (subtype & VSTYPE) {
1219                        case VSNORMAL:
1220                                putc('}', fp);
1221                                break;
1222                        case VSMINUS:
1223                                putc('-', fp);
1224                                break;
1225                        case VSPLUS:
1226                                putc('+', fp);
1227                                break;
1228                        case VSQUESTION:
1229                                putc('?', fp);
1230                                break;
1231                        case VSASSIGN:
1232                                putc('=', fp);
1233                                break;
1234                        case VSTRIMLEFT:
1235                                putc('#', fp);
1236                                break;
1237                        case VSTRIMLEFTMAX:
1238                                putc('#', fp);
1239                                putc('#', fp);
1240                                break;
1241                        case VSTRIMRIGHT:
1242                                putc('%', fp);
1243                                break;
1244                        case VSTRIMRIGHTMAX:
1245                                putc('%', fp);
1246                                putc('%', fp);
1247                                break;
1248                        case VSLENGTH:
1249                                break;
1250                        default:
1251                                out1fmt("<subtype %d>", subtype);
1252                        }
1253                        break;
1254                case CTLENDVAR:
1255                        putc('}', fp);
1256                        break;
1257#if BASH_PROCESS_SUBST
1258                case CTLTOPROC:
1259                        putc('>', fp);
1260                        goto backq;
1261                case CTLFROMPROC:
1262                        putc('<', fp);
1263                        goto backq;
1264#endif
1265                case CTLBACKQ:
1266                        putc('$', fp);
1267 IF_BASH_PROCESS_SUBST(backq:)
1268                        putc('(', fp);
1269                        shtree(bqlist->n, -1, NULL, fp);
1270                        putc(')', fp);
1271                        break;
1272                default:
1273                        putc(*p, fp);
1274                        break;
1275                }
1276        }
1277}
1278
1279static void
1280shcmd(union node *cmd, FILE *fp)
1281{
1282        union node *np;
1283        int first;
1284        const char *s;
1285        int dftfd;
1286
1287        first = 1;
1288        for (np = cmd->ncmd.args; np; np = np->narg.next) {
1289                if (!first)
1290                        putc(' ', fp);
1291                sharg(np, fp);
1292                first = 0;
1293        }
1294        for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1295                if (!first)
1296                        putc(' ', fp);
1297                dftfd = 0;
1298                switch (np->nfile.type) {
1299                case NTO:      s = ">>"+1; dftfd = 1; break;
1300                case NCLOBBER: s = ">|"; dftfd = 1; break;
1301                case NAPPEND:  s = ">>"; dftfd = 1; break;
1302#if BASH_REDIR_OUTPUT
1303                case NTO2:
1304#endif
1305                case NTOFD:    s = ">&"; dftfd = 1; break;
1306                case NFROM:    s = "<"; break;
1307                case NFROMFD:  s = "<&"; break;
1308                case NFROMTO:  s = "<>"; break;
1309                default:       s = "*error*"; break;
1310                }
1311                if (np->nfile.fd != dftfd)
1312                        fprintf(fp, "%d", np->nfile.fd);
1313                fputs(s, fp);
1314                if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1315                        fprintf(fp, "%d", np->ndup.dupfd);
1316                } else {
1317                        sharg(np->nfile.fname, fp);
1318                }
1319                first = 0;
1320        }
1321}
1322
1323static void
1324shtree(union node *n, int ind, char *pfx, FILE *fp)
1325{
1326        struct nodelist *lp;
1327        const char *s;
1328
1329        if (n == NULL)
1330                return;
1331
1332        indent(ind, pfx, fp);
1333
1334        if (n == NODE_EOF) {
1335                fputs("<EOF>", fp);
1336                return;
1337        }
1338
1339        switch (n->type) {
1340        case NSEMI:
1341                s = "; ";
1342                goto binop;
1343        case NAND:
1344                s = " && ";
1345                goto binop;
1346        case NOR:
1347                s = " || ";
1348 binop:
1349                shtree(n->nbinary.ch1, ind, NULL, fp);
1350                /* if (ind < 0) */
1351                        fputs(s, fp);
1352                shtree(n->nbinary.ch2, ind, NULL, fp);
1353                break;
1354        case NCMD:
1355                shcmd(n, fp);
1356                if (ind >= 0)
1357                        putc('\n', fp);
1358                break;
1359        case NPIPE:
1360                for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1361                        shtree(lp->n, 0, NULL, fp);
1362                        if (lp->next)
1363                                fputs(" | ", fp);
1364                }
1365                if (n->npipe.pipe_backgnd)
1366                        fputs(" &", fp);
1367                if (ind >= 0)
1368                        putc('\n', fp);
1369                break;
1370        default:
1371                fprintf(fp, "<node type %d>", n->type);
1372                if (ind >= 0)
1373                        putc('\n', fp);
1374                break;
1375        }
1376}
1377
1378static void
1379showtree(union node *n)
1380{
1381        trace_puts("showtree called\n");
1382        shtree(n, 1, NULL, stderr);
1383}
1384
1385#endif /* DEBUG */
1386
1387
1388/* ============ Message printing */
1389
1390static void
1391ash_vmsg(const char *msg, va_list ap)
1392{
1393        fprintf(stderr, "%s: ", arg0);
1394        if (commandname) {
1395                if (strcmp(arg0, commandname))
1396                        fprintf(stderr, "%s: ", commandname);
1397                if (!iflag || g_parsefile->pf_fd > 0)
1398                        fprintf(stderr, "line %d: ", errlinno);
1399        }
1400        vfprintf(stderr, msg, ap);
1401        newline_and_flush(stderr);
1402}
1403
1404/*
1405 * Exverror is called to raise the error exception.  If the second argument
1406 * is not NULL then error prints an error message using printf style
1407 * formatting.  It then raises the error exception.
1408 */
1409static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1410static void
1411ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1412{
1413#if DEBUG
1414        if (msg) {
1415                TRACE(("ash_vmsg_and_raise(%d):", cond));
1416                TRACEV((msg, ap));
1417        } else
1418                TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1419        if (msg)
1420#endif
1421                ash_vmsg(msg, ap);
1422
1423        flush_stdout_stderr();
1424        raise_exception(cond);
1425        /* NOTREACHED */
1426}
1427
1428static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1429static void
1430ash_msg_and_raise_error(const char *msg, ...)
1431{
1432        va_list ap;
1433
1434        exitstatus = 2;
1435
1436        va_start(ap, msg);
1437        ash_vmsg_and_raise(EXERROR, msg, ap);
1438        /* NOTREACHED */
1439        va_end(ap);
1440}
1441
1442/*
1443 * 'fmt' must be a string literal.
1444 */
1445#define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": "STRERROR_FMT, ##__VA_ARGS__ STRERROR_ERRNO)
1446
1447static void raise_error_syntax(const char *) NORETURN;
1448static void
1449raise_error_syntax(const char *msg)
1450{
1451        errlinno = g_parsefile->linno;
1452        ash_msg_and_raise_error("syntax error: %s", msg);
1453        /* NOTREACHED */
1454}
1455
1456static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1457static void
1458ash_msg_and_raise(int cond, const char *msg, ...)
1459{
1460        va_list ap;
1461
1462        va_start(ap, msg);
1463        ash_vmsg_and_raise(cond, msg, ap);
1464        /* NOTREACHED */
1465        va_end(ap);
1466}
1467
1468/*
1469 * error/warning routines for external builtins
1470 */
1471static void
1472ash_msg(const char *fmt, ...)
1473{
1474        va_list ap;
1475
1476        va_start(ap, fmt);
1477        ash_vmsg(fmt, ap);
1478        va_end(ap);
1479}
1480
1481/*
1482 * Return a string describing an error.  The returned string may be a
1483 * pointer to a static buffer that will be overwritten on the next call.
1484 * Action describes the operation that got the error.
1485 */
1486static const char *
1487errmsg(int e, const char *em)
1488{
1489        if (e == ENOENT || e == ENOTDIR) {
1490                return em;
1491        }
1492        return strerror(e);
1493}
1494
1495
1496/* ============ Memory allocation */
1497
1498#if 0
1499/* I consider these wrappers nearly useless:
1500 * ok, they return you to nearest exception handler, but
1501 * how much memory do you leak in the process, making
1502 * memory starvation worse?
1503 */
1504static void *
1505ckrealloc(void * p, size_t nbytes)
1506{
1507        p = realloc(p, nbytes);
1508        if (!p)
1509                ash_msg_and_raise_error(bb_msg_memory_exhausted);
1510        return p;
1511}
1512
1513static void *
1514ckmalloc(size_t nbytes)
1515{
1516        return ckrealloc(NULL, nbytes);
1517}
1518
1519static void *
1520ckzalloc(size_t nbytes)
1521{
1522        return memset(ckmalloc(nbytes), 0, nbytes);
1523}
1524
1525static char *
1526ckstrdup(const char *s)
1527{
1528        char *p = strdup(s);
1529        if (!p)
1530                ash_msg_and_raise_error(bb_msg_memory_exhausted);
1531        return p;
1532}
1533#else
1534/* Using bbox equivalents. They exit if out of memory */
1535# define ckrealloc xrealloc
1536# define ckmalloc  xmalloc
1537# define ckzalloc  xzalloc
1538# define ckstrdup  xstrdup
1539#endif
1540
1541/*
1542 * It appears that grabstackstr() will barf with such alignments
1543 * because stalloc() will return a string allocated in a new stackblock.
1544 */
1545#define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1546enum {
1547        /* Most machines require the value returned from malloc to be aligned
1548         * in some way.  The following macro will get this right
1549         * on many machines.  */
1550        SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1551        /* Minimum size of a block */
1552        MINSIZE = SHELL_ALIGN(504),
1553};
1554
1555struct stack_block {
1556        struct stack_block *prev;
1557        char space[MINSIZE];
1558};
1559
1560struct stackmark {
1561        struct stack_block *stackp;
1562        char *stacknxt;
1563        size_t stacknleft;
1564};
1565
1566
1567struct globals_memstack {
1568        struct stack_block *g_stackp; // = &stackbase;
1569        char *g_stacknxt; // = stackbase.space;
1570        char *sstrend; // = stackbase.space + MINSIZE;
1571        size_t g_stacknleft; // = MINSIZE;
1572        struct stack_block stackbase;
1573};
1574extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack;
1575#define G_memstack (*ash_ptr_to_globals_memstack)
1576#define g_stackp     (G_memstack.g_stackp    )
1577#define g_stacknxt   (G_memstack.g_stacknxt  )
1578#define sstrend      (G_memstack.sstrend     )
1579#define g_stacknleft (G_memstack.g_stacknleft)
1580#define stackbase    (G_memstack.stackbase   )
1581#define INIT_G_memstack() do { \
1582        (*(struct globals_memstack**)not_const_pp(&ash_ptr_to_globals_memstack)) = xzalloc(sizeof(G_memstack)); \
1583        barrier(); \
1584        g_stackp = &stackbase; \
1585        g_stacknxt = stackbase.space; \
1586        g_stacknleft = MINSIZE; \
1587        sstrend = stackbase.space + MINSIZE; \
1588} while (0)
1589
1590
1591#define stackblock()     ((void *)g_stacknxt)
1592#define stackblocksize() g_stacknleft
1593
1594/*
1595 * Parse trees for commands are allocated in lifo order, so we use a stack
1596 * to make this more efficient, and also to avoid all sorts of exception
1597 * handling code to handle interrupts in the middle of a parse.
1598 *
1599 * The size 504 was chosen because the Ultrix malloc handles that size
1600 * well.
1601 */
1602static void *
1603stalloc(size_t nbytes)
1604{
1605        char *p;
1606        size_t aligned;
1607
1608        aligned = SHELL_ALIGN(nbytes);
1609        if (aligned > g_stacknleft) {
1610                size_t len;
1611                size_t blocksize;
1612                struct stack_block *sp;
1613
1614                blocksize = aligned;
1615                if (blocksize < MINSIZE)
1616                        blocksize = MINSIZE;
1617                len = sizeof(struct stack_block) - MINSIZE + blocksize;
1618                if (len < blocksize)
1619                        ash_msg_and_raise_error(bb_msg_memory_exhausted);
1620                INT_OFF;
1621                sp = ckmalloc(len);
1622                sp->prev = g_stackp;
1623                g_stacknxt = sp->space;
1624                g_stacknleft = blocksize;
1625                sstrend = g_stacknxt + blocksize;
1626                g_stackp = sp;
1627                INT_ON;
1628        }
1629        p = g_stacknxt;
1630        g_stacknxt += aligned;
1631        g_stacknleft -= aligned;
1632        return p;
1633}
1634
1635static void *
1636stzalloc(size_t nbytes)
1637{
1638        return memset(stalloc(nbytes), 0, nbytes);
1639}
1640
1641static void
1642stunalloc(void *p)
1643{
1644#if DEBUG
1645        if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1646                write(STDERR_FILENO, "stunalloc\n", 10);
1647                abort();
1648        }
1649#endif
1650        g_stacknleft += g_stacknxt - (char *)p;
1651        g_stacknxt = p;
1652}
1653
1654/*
1655 * Like strdup but works with the ash stack.
1656 */
1657static char *
1658sstrdup(const char *p)
1659{
1660        size_t len = strlen(p) + 1;
1661        return memcpy(stalloc(len), p, len);
1662}
1663
1664static ALWAYS_INLINE void
1665grabstackblock(size_t len)
1666{
1667        stalloc(len);
1668}
1669
1670static void
1671pushstackmark(struct stackmark *mark, size_t len)
1672{
1673        mark->stackp = g_stackp;
1674        mark->stacknxt = g_stacknxt;
1675        mark->stacknleft = g_stacknleft;
1676        grabstackblock(len);
1677}
1678
1679static void
1680setstackmark(struct stackmark *mark)
1681{
1682        pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1683}
1684
1685static void
1686popstackmark(struct stackmark *mark)
1687{
1688        struct stack_block *sp;
1689
1690        if (!mark->stackp)
1691                return;
1692
1693        INT_OFF;
1694        while (g_stackp != mark->stackp) {
1695                sp = g_stackp;
1696                g_stackp = sp->prev;
1697                free(sp);
1698        }
1699        g_stacknxt = mark->stacknxt;
1700        g_stacknleft = mark->stacknleft;
1701        sstrend = mark->stacknxt + mark->stacknleft;
1702        INT_ON;
1703}
1704
1705/*
1706 * When the parser reads in a string, it wants to stick the string on the
1707 * stack and only adjust the stack pointer when it knows how big the
1708 * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1709 * of space on top of the stack and stackblocklen returns the length of
1710 * this block.  Growstackblock will grow this space by at least one byte,
1711 * possibly moving it (like realloc).  Grabstackblock actually allocates the
1712 * part of the block that has been used.
1713 */
1714static void
1715growstackblock(size_t min)
1716{
1717        size_t newlen;
1718
1719        newlen = g_stacknleft * 2;
1720        if (newlen < g_stacknleft)
1721                ash_msg_and_raise_error(bb_msg_memory_exhausted);
1722        min = SHELL_ALIGN(min | 128);
1723        if (newlen < min)
1724                newlen += min;
1725
1726        if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1727                struct stack_block *sp;
1728                struct stack_block *prevstackp;
1729                size_t grosslen;
1730
1731                INT_OFF;
1732                sp = g_stackp;
1733                prevstackp = sp->prev;
1734                grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1735                sp = ckrealloc(sp, grosslen);
1736                sp->prev = prevstackp;
1737                g_stackp = sp;
1738                g_stacknxt = sp->space;
1739                g_stacknleft = newlen;
1740                sstrend = sp->space + newlen;
1741                INT_ON;
1742        } else {
1743                char *oldspace = g_stacknxt;
1744                size_t oldlen = g_stacknleft;
1745                char *p = stalloc(newlen);
1746
1747                /* free the space we just allocated */
1748                g_stacknxt = memcpy(p, oldspace, oldlen);
1749                g_stacknleft += newlen;
1750        }
1751}
1752
1753/*
1754 * The following routines are somewhat easier to use than the above.
1755 * The user declares a variable of type STACKSTR, which may be declared
1756 * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1757 * the user uses the macro STPUTC to add characters to the string.  In
1758 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1759 * grown as necessary.  When the user is done, she can just leave the
1760 * string there and refer to it using stackblock().  Or she can allocate
1761 * the space for it using grabstackstr().  If it is necessary to allow
1762 * someone else to use the stack temporarily and then continue to grow
1763 * the string, the user should use grabstack to allocate the space, and
1764 * then call ungrabstr(p) to return to the previous mode of operation.
1765 *
1766 * USTPUTC is like STPUTC except that it doesn't check for overflow.
1767 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1768 * is space for at least one character.
1769 */
1770static void *
1771growstackstr(void)
1772{
1773        size_t len = stackblocksize();
1774        growstackblock(0);
1775        return (char *)stackblock() + len;
1776}
1777
1778static char *
1779growstackto(size_t len)
1780{
1781        if (stackblocksize() < len)
1782                growstackblock(len);
1783        return stackblock();
1784}
1785
1786/*
1787 * Called from CHECKSTRSPACE.
1788 */
1789static char *
1790makestrspace(size_t newlen, char *p)
1791{
1792        size_t len = p - g_stacknxt;
1793
1794        return growstackto(len + newlen) + len;
1795}
1796
1797static char *
1798stnputs(const char *s, size_t n, char *p)
1799{
1800        p = makestrspace(n, p);
1801        p = (char *)mempcpy(p, s, n);
1802        return p;
1803}
1804
1805static char *
1806stack_putstr(const char *s, char *p)
1807{
1808        return stnputs(s, strlen(s), p);
1809}
1810
1811static char *
1812_STPUTC(int c, char *p)
1813{
1814        if (p == sstrend)
1815                p = growstackstr();
1816        *p++ = c;
1817        return p;
1818}
1819
1820#define STARTSTACKSTR(p)        ((p) = stackblock())
1821#define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1822#define CHECKSTRSPACE(n, p) do { \
1823        char *q = (p); \
1824        size_t l = (n); \
1825        size_t m = sstrend - q; \
1826        if (l > m) \
1827                (p) = makestrspace(l, q); \
1828} while (0)
1829#define USTPUTC(c, p)           (*(p)++ = (c))
1830#define STACKSTRNUL(p) do { \
1831        if ((p) == sstrend) \
1832                (p) = growstackstr(); \
1833        *(p) = '\0'; \
1834} while (0)
1835#define STUNPUTC(p)             (--(p))
1836#define STTOPC(p)               ((p)[-1])
1837#define STADJUST(amount, p)     ((p) += (amount))
1838
1839#define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1840#define ungrabstackstr(s, p)    stunalloc(s)
1841#define stackstrend()           ((void *)sstrend)
1842
1843
1844/* ============ String helpers */
1845
1846/*
1847 * prefix -- see if pfx is a prefix of string.
1848 */
1849static char *
1850prefix(const char *string, const char *pfx)
1851{
1852        while (*pfx) {
1853                if (*pfx++ != *string++)
1854                        return NULL;
1855        }
1856        return (char *) string;
1857}
1858
1859/*
1860 * Check for a valid number.  This should be elsewhere.
1861 */
1862static int
1863is_number(const char *p)
1864{
1865        do {
1866                if (!isdigit(*p))
1867                        return 0;
1868        } while (*++p != '\0');
1869        return 1;
1870}
1871
1872/*
1873 * Convert a string of digits to an integer, printing an error message on
1874 * failure.
1875 */
1876static int
1877number(const char *s)
1878{
1879        if (!is_number(s))
1880                ash_msg_and_raise_error(msg_illnum, s);
1881        return atoi(s);
1882}
1883
1884/*
1885 * Produce a single quoted string suitable as input to the shell.
1886 * The return string is allocated on the stack.
1887 */
1888static char *
1889single_quote(const char *s)
1890{
1891        char *p;
1892
1893        STARTSTACKSTR(p);
1894
1895        do {
1896                char *q;
1897                size_t len;
1898
1899                len = strchrnul(s, '\'') - s;
1900
1901                q = p = makestrspace(len + 3, p);
1902
1903                *q++ = '\'';
1904                q = (char *)mempcpy(q, s, len);
1905                *q++ = '\'';
1906                s += len;
1907
1908                STADJUST(q - p, p);
1909
1910                if (*s != '\'')
1911                        break;
1912                len = 0;
1913                do len++; while (*++s == '\'');
1914
1915                q = p = makestrspace(len + 3, p);
1916
1917                *q++ = '"';
1918                q = (char *)mempcpy(q, s - len, len);
1919                *q++ = '"';
1920
1921                STADJUST(q - p, p);
1922        } while (*s);
1923
1924        USTPUTC('\0', p);
1925
1926        return stackblock();
1927}
1928
1929/*
1930 * Produce a possibly single quoted string suitable as input to the shell.
1931 * If quoting was done, the return string is allocated on the stack,
1932 * otherwise a pointer to the original string is returned.
1933 */
1934static const char *
1935maybe_single_quote(const char *s)
1936{
1937        const char *p = s;
1938
1939        while (*p) {
1940                /* Assuming ACSII */
1941                /* quote ctrl_chars space !"#$%&'()* */
1942                if (*p < '+')
1943                        goto need_quoting;
1944                /* quote ;<=>? */
1945                if (*p >= ';' && *p <= '?')
1946                        goto need_quoting;
1947                /* quote `[\ */
1948                if (*p == '`')
1949                        goto need_quoting;
1950                if (*p == '[')
1951                        goto need_quoting;
1952                if (*p == '\\')
1953                        goto need_quoting;
1954                /* quote {|}~ DEL and high bytes */
1955                if (*p > 'z')
1956                        goto need_quoting;
1957                /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1958                /* TODO: maybe avoid quoting % */
1959                p++;
1960        }
1961        return s;
1962
1963 need_quoting:
1964        return single_quote(s);
1965}
1966
1967
1968/* ============ nextopt */
1969
1970static char **argptr;                  /* argument list for builtin commands */
1971static char *optionarg;                /* set by nextopt (like getopt) */
1972static char *optptr;                   /* used by nextopt */
1973
1974/*
1975 * XXX - should get rid of. Have all builtins use getopt(3).
1976 * The library getopt must have the BSD extension static variable
1977 * "optreset", otherwise it can't be used within the shell safely.
1978 *
1979 * Standard option processing (a la getopt) for builtin routines.
1980 * The only argument that is passed to nextopt is the option string;
1981 * the other arguments are unnecessary. It returns the character,
1982 * or '\0' on end of input.
1983 */
1984static int
1985nextopt(const char *optstring)
1986{
1987        char *p;
1988        const char *q;
1989        char c;
1990
1991        p = optptr;
1992        if (p == NULL || *p == '\0') {
1993                /* We ate entire "-param", take next one */
1994                p = *argptr;
1995                if (p == NULL)
1996                        return '\0';
1997                if (*p != '-')
1998                        return '\0';
1999                if (*++p == '\0') /* just "-" ? */
2000                        return '\0';
2001                argptr++;
2002                if (LONE_DASH(p)) /* "--" ? */
2003                        return '\0';
2004                /* p => next "-param" */
2005        }
2006        /* p => some option char in the middle of a "-param" */
2007        c = *p++;
2008        for (q = optstring; *q != c;) {
2009                if (*q == '\0')
2010                        ash_msg_and_raise_error("illegal option -%c", c);
2011                if (*++q == ':')
2012                        q++;
2013        }
2014        if (*++q == ':') {
2015                if (*p == '\0') {
2016                        p = *argptr++;
2017                        if (p == NULL)
2018                                ash_msg_and_raise_error("no arg for -%c option", c);
2019                }
2020                optionarg = p;
2021                p = NULL;
2022        }
2023        optptr = p;
2024        return c;
2025}
2026
2027
2028/* ============ Shell variables */
2029
2030struct shparam {
2031        int nparam;             /* # of positional parameters (without $0) */
2032#if ENABLE_ASH_GETOPTS
2033        int optind;             /* next parameter to be processed by getopts */
2034        int optoff;             /* used by getopts */
2035#endif
2036        unsigned char malloced; /* if parameter list dynamically allocated */
2037        char **p;               /* parameter list */
2038};
2039
2040/*
2041 * Free the list of positional parameters.
2042 */
2043static void
2044freeparam(volatile struct shparam *param)
2045{
2046        if (param->malloced) {
2047                char **ap, **ap1;
2048                ap = ap1 = param->p;
2049                while (*ap)
2050                        free(*ap++);
2051                free(ap1);
2052        }
2053}
2054
2055#if ENABLE_ASH_GETOPTS
2056static void FAST_FUNC getoptsreset(const char *value);
2057#endif
2058
2059struct var {
2060        struct var *next;               /* next entry in hash list */
2061        int flags;                      /* flags are defined above */
2062        const char *var_text;           /* name=value */
2063        void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
2064                                        /* the variable gets set/unset */
2065};
2066
2067struct localvar {
2068        struct localvar *next;          /* next local variable in list */
2069        struct var *vp;                 /* the variable that was made local */
2070        int flags;                      /* saved flags */
2071        const char *text;               /* saved text */
2072};
2073
2074/* flags */
2075#define VEXPORT         0x01    /* variable is exported */
2076#define VREADONLY       0x02    /* variable cannot be modified */
2077#define VSTRFIXED       0x04    /* variable struct is statically allocated */
2078#define VTEXTFIXED      0x08    /* text is statically allocated */
2079#define VSTACK          0x10    /* text is allocated on the stack */
2080#define VUNSET          0x20    /* the variable is not set */
2081#define VNOFUNC         0x40    /* don't call the callback function */
2082#define VNOSET          0x80    /* do not set variable - just readonly test */
2083#define VNOSAVE         0x100   /* when text is on the heap before setvareq */
2084#if ENABLE_ASH_RANDOM_SUPPORT
2085# define VDYNAMIC       0x200   /* dynamic variable */
2086#else
2087# define VDYNAMIC       0
2088#endif
2089
2090
2091/* Need to be before varinit_data[] */
2092#if ENABLE_LOCALE_SUPPORT
2093static void FAST_FUNC
2094change_lc_all(const char *value)
2095{
2096        if (value && *value != '\0')
2097                setlocale(LC_ALL, value);
2098}
2099static void FAST_FUNC
2100change_lc_ctype(const char *value)
2101{
2102        if (value && *value != '\0')
2103                setlocale(LC_CTYPE, value);
2104}
2105#endif
2106#if ENABLE_ASH_MAIL
2107static void chkmail(void);
2108static void changemail(const char *var_value) FAST_FUNC;
2109#else
2110# define chkmail()  ((void)0)
2111#endif
2112static void changepath(const char *) FAST_FUNC;
2113#if ENABLE_ASH_RANDOM_SUPPORT
2114static void change_random(const char *) FAST_FUNC;
2115#endif
2116#if BASH_EPOCH_VARS
2117static void change_seconds(const char *) FAST_FUNC;
2118static void change_realtime(const char *) FAST_FUNC;
2119#endif
2120
2121static const struct {
2122        int flags;
2123        const char *var_text;
2124        void (*var_func)(const char *) FAST_FUNC;
2125} varinit_data[] ALIGN_PTR = {
2126        /*
2127         * Note: VEXPORT would not work correctly here for NOFORK applets:
2128         * some environment strings may be constant.
2129         */
2130        { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2131#if ENABLE_ASH_MAIL
2132        { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2133        { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2134#endif
2135        { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2136        { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2137        { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2138        { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2139#if ENABLE_ASH_GETOPTS
2140        { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2141#endif
2142        { VSTRFIXED|VTEXTFIXED       , NULL /* inited to linenovar */, NULL },
2143#if ENABLE_ASH_RANDOM_SUPPORT
2144        { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2145#endif
2146#if BASH_EPOCH_VARS
2147        { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "EPOCHSECONDS", change_seconds },
2148        { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "EPOCHREALTIME", change_realtime },
2149#endif
2150#if ENABLE_LOCALE_SUPPORT
2151        { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2152        { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2153#endif
2154#if ENABLE_FEATURE_EDITING_SAVEHISTORY
2155        { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2156#endif
2157};
2158
2159struct redirtab;
2160
2161struct globals_var {
2162        struct shparam shellparam;      /* $@ current positional parameters */
2163        struct redirtab *redirlist;
2164        int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2165        struct var *vartab[VTABSIZE];
2166        struct var varinit[ARRAY_SIZE(varinit_data)];
2167        int lineno;
2168        char linenovar[sizeof("LINENO=") + sizeof(int)*3];
2169};
2170extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var;
2171#define G_var (*ash_ptr_to_globals_var)
2172#define shellparam    (G_var.shellparam   )
2173//#define redirlist     (G_var.redirlist    )
2174#define preverrout_fd (G_var.preverrout_fd)
2175#define vartab        (G_var.vartab       )
2176#define varinit       (G_var.varinit      )
2177#define lineno        (G_var.lineno       )
2178#define linenovar     (G_var.linenovar    )
2179#define vifs      varinit[0]
2180#if ENABLE_ASH_MAIL
2181# define vmail    varinit[1]
2182# define vmpath   varinit[2]
2183#endif
2184#define VAR_OFFSET1 (ENABLE_ASH_MAIL*2)
2185#define vpath     varinit[VAR_OFFSET1 + 1]
2186#define vps1      varinit[VAR_OFFSET1 + 2]
2187#define vps2      varinit[VAR_OFFSET1 + 3]
2188#define vps4      varinit[VAR_OFFSET1 + 4]
2189#if ENABLE_ASH_GETOPTS
2190# define voptind  varinit[VAR_OFFSET1 + 5]
2191#endif
2192#define VAR_OFFSET2 (VAR_OFFSET1 + ENABLE_ASH_GETOPTS)
2193#define vlineno   varinit[VAR_OFFSET2 + 5]
2194#if ENABLE_ASH_RANDOM_SUPPORT
2195# define vrandom  varinit[VAR_OFFSET2 + 6]
2196#endif
2197#define VAR_OFFSET3 (VAR_OFFSET2 + ENABLE_ASH_RANDOM_SUPPORT)
2198#if BASH_EPOCH_VARS
2199# define vepochs  varinit[VAR_OFFSET3 + 6]
2200# define vepochr  varinit[VAR_OFFSET3 + 7]
2201#endif
2202#define INIT_G_var() do { \
2203        unsigned i; \
2204        (*(struct globals_var**)not_const_pp(&ash_ptr_to_globals_var)) = xzalloc(sizeof(G_var)); \
2205        barrier(); \
2206        for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2207                varinit[i].flags    = varinit_data[i].flags; \
2208                varinit[i].var_text = varinit_data[i].var_text; \
2209                varinit[i].var_func = varinit_data[i].var_func; \
2210        } \
2211        strcpy(linenovar, "LINENO="); \
2212        vlineno.var_text = linenovar; \
2213} while (0)
2214
2215/*
2216 * The following macros access the values of the above variables.
2217 * They have to skip over the name.  They return the null string
2218 * for unset variables.
2219 */
2220#define ifsval()        (vifs.var_text + 4)
2221#define ifsset()        ((vifs.flags & VUNSET) == 0)
2222#if ENABLE_ASH_MAIL
2223# define mailval()      (vmail.var_text + 5)
2224# define mpathval()     (vmpath.var_text + 9)
2225# define mpathset()     ((vmpath.flags & VUNSET) == 0)
2226#endif
2227#define pathval()       (vpath.var_text + 5)
2228#define ps1val()        (vps1.var_text + 4)
2229#define ps2val()        (vps2.var_text + 4)
2230#define ps4val()        (vps4.var_text + 4)
2231#if ENABLE_ASH_GETOPTS
2232# define optindval()    (voptind.var_text + 7)
2233#endif
2234
2235#if ENABLE_ASH_GETOPTS
2236static void FAST_FUNC
2237getoptsreset(const char *value)
2238{
2239        shellparam.optind = 1;
2240        if (is_number(value))
2241                shellparam.optind = number(value) ?: 1;
2242        shellparam.optoff = -1;
2243}
2244#endif
2245
2246/*
2247 * Compares two strings up to the first = or '\0'.  The first
2248 * string must be terminated by '='; the second may be terminated by
2249 * either '=' or '\0'.
2250 */
2251static int
2252varcmp(const char *p, const char *q)
2253{
2254        int c, d;
2255
2256        while ((c = *p) == (d = *q)) {
2257                if (c == '\0' || c == '=')
2258                        goto out;
2259                p++;
2260                q++;
2261        }
2262        if (c == '=')
2263                c = '\0';
2264        if (d == '=')
2265                d = '\0';
2266 out:
2267        return c - d;
2268}
2269
2270/*
2271 * Find the appropriate entry in the hash table from the name.
2272 */
2273static struct var **
2274hashvar(const char *p)
2275{
2276        unsigned hashval;
2277
2278        hashval = ((unsigned char) *p) << 4;
2279        while (*p && *p != '=')
2280                hashval += (unsigned char) *p++;
2281        return &vartab[hashval % VTABSIZE];
2282}
2283
2284static int
2285vpcmp(const void *a, const void *b)
2286{
2287        return varcmp(*(const char **)a, *(const char **)b);
2288}
2289
2290/*
2291 * This routine initializes the builtin variables.
2292 */
2293static void
2294initvar(void)
2295{
2296        struct var *vp;
2297        struct var *end;
2298        struct var **vpp;
2299
2300        /*
2301         * PS1 depends on uid
2302         */
2303#if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2304        vps1.var_text = "PS1=\\w \\$ ";
2305#else
2306        if (!geteuid())
2307                vps1.var_text = "PS1=# ";
2308#endif
2309        vp = varinit;
2310        end = vp + ARRAY_SIZE(varinit);
2311        do {
2312                vpp = hashvar(vp->var_text);
2313                vp->next = *vpp;
2314                *vpp = vp;
2315        } while (++vp < end);
2316}
2317
2318static struct var **
2319findvar(struct var **vpp, const char *name)
2320{
2321        for (; *vpp; vpp = &(*vpp)->next) {
2322                if (varcmp((*vpp)->var_text, name) == 0) {
2323                        break;
2324                }
2325        }
2326        return vpp;
2327}
2328
2329/*
2330 * Find the value of a variable.  Returns NULL if not set.
2331 */
2332static const char* FAST_FUNC
2333lookupvar(const char *name)
2334{
2335        struct var *v;
2336
2337        v = *findvar(hashvar(name), name);
2338        if (v) {
2339#if ENABLE_ASH_RANDOM_SUPPORT || BASH_EPOCH_VARS
2340        /*
2341         * Dynamic variables are implemented roughly the same way they are
2342         * in bash. Namely, they're "special" so long as they aren't unset.
2343         * As soon as they're unset, they're no longer dynamic, and dynamic
2344         * lookup will no longer happen at that point. -- PFM.
2345         */
2346                if (v->flags & VDYNAMIC)
2347                        v->var_func(NULL);
2348#endif
2349                if (!(v->flags & VUNSET)) {
2350                        if (v == &vlineno && v->var_text == linenovar) {
2351                                fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno);
2352                        }
2353                        return var_end(v->var_text);
2354                }
2355        }
2356        return NULL;
2357}
2358
2359#if ENABLE_UNICODE_SUPPORT
2360static void
2361reinit_unicode_for_ash(void)
2362{
2363        /* Unicode support should be activated even if LANG is set
2364         * _during_ shell execution, not only if it was set when
2365         * shell was started. Therefore, re-check LANG every time:
2366         */
2367        if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2368         || ENABLE_UNICODE_USING_LOCALE
2369        ) {
2370                const char *s = lookupvar("LC_ALL");
2371                if (!s) s = lookupvar("LC_CTYPE");
2372                if (!s) s = lookupvar("LANG");
2373                reinit_unicode(s);
2374        }
2375}
2376#else
2377# define reinit_unicode_for_ash() ((void)0)
2378#endif
2379
2380/*
2381 * Search the environment of a builtin command.
2382 */
2383static ALWAYS_INLINE const char *
2384bltinlookup(const char *name)
2385{
2386        return lookupvar(name);
2387}
2388
2389/*
2390 * Same as setvar except that the variable and value are passed in
2391 * the first argument as name=value.  Since the first argument will
2392 * be actually stored in the table, it should not be a string that
2393 * will go away.
2394 * Called with interrupts off.
2395 */
2396static struct var *
2397setvareq(char *s, int flags)
2398{
2399        struct var *vp, **vpp;
2400
2401        vpp = hashvar(s);
2402        flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2403        vpp = findvar(vpp, s);
2404        vp = *vpp;
2405        if (vp) {
2406                if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2407                        const char *n;
2408
2409                        if (flags & VNOSAVE)
2410                                free(s);
2411                        n = vp->var_text;
2412                        exitstatus = 1;
2413                        ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2414                }
2415
2416                if (flags & VNOSET)
2417                        goto out;
2418
2419                if (vp->var_func && !(flags & VNOFUNC))
2420                        vp->var_func(var_end(s));
2421
2422                if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2423                        free((char*)vp->var_text);
2424
2425                if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2426                        *vpp = vp->next;
2427                        free(vp);
2428 out_free:
2429                        if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2430                                free(s);
2431                        goto out;
2432                }
2433
2434                flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2435#if ENABLE_ASH_RANDOM_SUPPORT || BASH_EPOCH_VARS
2436                if (flags & VUNSET)
2437                        flags &= ~VDYNAMIC;
2438#endif
2439        } else {
2440                /* variable s is not found */
2441                if (flags & VNOSET)
2442                        goto out;
2443                if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2444                        goto out_free;
2445                vp = ckzalloc(sizeof(*vp));
2446                vp->next = *vpp;
2447                /*vp->func = NULL; - ckzalloc did it */
2448                *vpp = vp;
2449        }
2450        if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2451                s = ckstrdup(s);
2452        vp->var_text = s;
2453        vp->flags = flags;
2454
2455 out:
2456        return vp;
2457}
2458
2459/*
2460 * Set the value of a variable.  The flags argument is ored with the
2461 * flags of the variable.  If val is NULL, the variable is unset.
2462 */
2463static struct var *
2464setvar(const char *name, const char *val, int flags)
2465{
2466        const char *q;
2467        char *p;
2468        char *nameeq;
2469        size_t namelen;
2470        size_t vallen;
2471        struct var *vp;
2472
2473        q = endofname(name);
2474        p = strchrnul(q, '=');
2475        namelen = p - name;
2476        if (!namelen || p != q)
2477                ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2478        vallen = 0;
2479        if (val == NULL) {
2480                flags |= VUNSET;
2481        } else {
2482                vallen = strlen(val);
2483        }
2484
2485        INT_OFF;
2486        nameeq = ckzalloc(namelen + vallen + 2);
2487        p = mempcpy(nameeq, name, namelen);
2488        if (val) {
2489                *p++ = '=';
2490                memcpy(p, val, vallen);
2491        }
2492        vp = setvareq(nameeq, flags | VNOSAVE);
2493        INT_ON;
2494
2495        return vp;
2496}
2497
2498static void FAST_FUNC
2499setvar0(const char *name, const char *val)
2500{
2501        setvar(name, val, 0);
2502}
2503
2504/*
2505 * Unset the specified variable.
2506 */
2507static void
2508unsetvar(const char *s)
2509{
2510        setvar(s, NULL, 0);
2511}
2512
2513/*
2514 * Generate a list of variables satisfying the given conditions.
2515 */
2516#if !ENABLE_FEATURE_SH_NOFORK
2517# define listvars(on, off, lp, end) listvars(on, off, end)
2518#endif
2519static char **
2520listvars(int on, int off, struct strlist *lp, char ***end)
2521{
2522        struct var **vpp;
2523        struct var *vp;
2524        char **ep;
2525        int mask;
2526
2527        STARTSTACKSTR(ep);
2528        vpp = vartab;
2529        mask = on | off;
2530        do {
2531                for (vp = *vpp; vp; vp = vp->next) {
2532                        if ((vp->flags & mask) == on) {
2533#if ENABLE_FEATURE_SH_NOFORK
2534                                /* If variable with the same name is both
2535                                 * exported and temporarily set for a command:
2536                                 *  export ZVAR=5
2537                                 *  ZVAR=6 printenv
2538                                 * then "ZVAR=6" will be both in vartab and
2539                                 * lp lists. Do not pass it twice to printenv.
2540                                 */
2541                                struct strlist *lp1 = lp;
2542                                while (lp1) {
2543                                        if (strcmp(lp1->text, vp->var_text) == 0)
2544                                                goto skip;
2545                                        lp1 = lp1->next;
2546                                }
2547#endif
2548                                if (ep == stackstrend())
2549                                        ep = growstackstr();
2550                                *ep++ = (char*)vp->var_text;
2551#if ENABLE_FEATURE_SH_NOFORK
2552 skip: ;
2553#endif
2554                        }
2555                }
2556        } while (++vpp < vartab + VTABSIZE);
2557
2558#if ENABLE_FEATURE_SH_NOFORK
2559        while (lp) {
2560                if (ep == stackstrend())
2561                        ep = growstackstr();
2562                *ep++ = lp->text;
2563                lp = lp->next;
2564        }
2565#endif
2566
2567        if (ep == stackstrend())
2568                ep = growstackstr();
2569        if (end)
2570                *end = ep;
2571        *ep++ = NULL;
2572        return grabstackstr(ep);
2573}
2574
2575
2576/* ============ Path search helper */
2577static const char *
2578legal_pathopt(const char *opt, const char *term, int magic)
2579{
2580        switch (magic) {
2581        case 0:
2582                opt = NULL;
2583                break;
2584
2585        case 1:
2586                opt = prefix(opt, "builtin") ?: prefix(opt, "func");
2587                break;
2588
2589        default:
2590                opt += strcspn(opt, term);
2591                break;
2592        }
2593
2594        if (opt && *opt == '%')
2595                opt++;
2596
2597        return opt;
2598}
2599
2600/*
2601 * The variable path (passed by reference) should be set to the start
2602 * of the path before the first call; padvance will update
2603 * this value as it proceeds.  Successive calls to padvance will return
2604 * the possible path expansions in sequence.  If an option (indicated by
2605 * a percent sign) appears in the path entry then the global variable
2606 * pathopt will be set to point to it; otherwise pathopt will be set to
2607 * NULL.
2608 *
2609 * If magic is 0 then pathopt recognition will be disabled.  If magic is
2610 * 1 we shall recognise %builtin/%func.  Otherwise we shall accept any
2611 * pathopt.
2612 */
2613static const char *pathopt;     /* set by padvance */
2614
2615static int
2616padvance_magic(const char **path, const char *name, int magic)
2617{
2618        const char *term = "%:";
2619        const char *lpathopt;
2620        const char *p;
2621        char *q;
2622        const char *start;
2623        size_t qlen;
2624        size_t len;
2625
2626        if (*path == NULL)
2627                return -1;
2628
2629        lpathopt = NULL;
2630        start = *path;
2631
2632        if (*start == '%' && (p = legal_pathopt(start + 1, term, magic))) {
2633                lpathopt = start + 1;
2634                start = p;
2635                term = ":";
2636        }
2637
2638        len = strcspn(start, term);
2639        p = start + len;
2640
2641        if (*p == '%') {
2642                size_t extra = strchrnul(p, ':') - p;
2643
2644                if (legal_pathopt(p + 1, term, magic))
2645                        lpathopt = p + 1;
2646                else
2647                        len += extra;
2648
2649                p += extra;
2650        }
2651
2652        pathopt = lpathopt;
2653        *path = *p == ':' ? p + 1 : NULL;
2654
2655        /* "2" is for '/' and '\0' */
2656        qlen = len + strlen(name) + 2;
2657        q = growstackto(qlen);
2658
2659        if (len) {
2660                q = mempcpy(q, start, len);
2661                *q++ = '/';
2662        }
2663        strcpy(q, name);
2664
2665        return qlen;
2666}
2667
2668static int
2669padvance(const char **path, const char *name)
2670{
2671        return padvance_magic(path, name, 1);
2672}
2673
2674
2675/* ============ Prompt */
2676
2677static smallint doprompt;                   /* if set, prompt the user */
2678static smallint needprompt;                 /* true if interactive and at start of line */
2679
2680#if ENABLE_FEATURE_EDITING
2681static line_input_t *line_input_state;
2682static const char *cmdedit_prompt;
2683static void
2684putprompt(const char *s)
2685{
2686        if (ENABLE_ASH_EXPAND_PRMT) {
2687                free((char*)cmdedit_prompt);
2688                cmdedit_prompt = ckstrdup(s);
2689                return;
2690        }
2691        cmdedit_prompt = s;
2692}
2693#else
2694static void
2695putprompt(const char *s)
2696{
2697        out2str(s);
2698}
2699#endif
2700
2701/* expandstr() needs parsing machinery, so it is far away ahead... */
2702static const char *expandstr(const char *ps, int syntax_type);
2703/* Values for syntax param */
2704#define BASESYNTAX 0    /* not in quotes */
2705#define DQSYNTAX   1    /* in double quotes */
2706#define SQSYNTAX   2    /* in single quotes */
2707#define ARISYNTAX  3    /* in arithmetic */
2708#if ENABLE_ASH_EXPAND_PRMT
2709# define PSSYNTAX  4    /* prompt. never passed to SIT() */
2710#endif
2711/* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2712
2713/*
2714 * called by editline -- any expansions to the prompt should be added here.
2715 */
2716static void
2717setprompt_if(smallint do_set, int whichprompt)
2718{
2719        const char *prompt;
2720        IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2721
2722        if (!do_set)
2723                return;
2724
2725        needprompt = 0;
2726
2727        switch (whichprompt) {
2728        case 1:
2729                prompt = ps1val();
2730                break;
2731        case 2:
2732                prompt = ps2val();
2733                break;
2734        default:                        /* 0 */
2735                prompt = nullstr;
2736        }
2737#if ENABLE_ASH_EXPAND_PRMT
2738        pushstackmark(&smark, stackblocksize());
2739        putprompt(expandstr(prompt, PSSYNTAX));
2740        popstackmark(&smark);
2741#else
2742        putprompt(prompt);
2743#endif
2744}
2745
2746
2747/* ============ The cd and pwd commands */
2748
2749#define CD_PHYSICAL 1
2750#define CD_PRINT 2
2751
2752static int
2753cdopt(void)
2754{
2755        int flags = 0;
2756        int i, j;
2757
2758        j = 'L';
2759        while ((i = nextopt("LP")) != '\0') {
2760                if (i != j) {
2761                        flags ^= CD_PHYSICAL;
2762                        j = i;
2763                }
2764        }
2765
2766        return flags;
2767}
2768
2769/*
2770 * Update curdir (the name of the current directory) in response to a
2771 * cd command.
2772 */
2773static const char *
2774updatepwd(const char *dir)
2775{
2776        char *new;
2777        char *p;
2778        char *cdcomppath;
2779        const char *lim;
2780
2781        cdcomppath = sstrdup(dir);
2782        STARTSTACKSTR(new);
2783        if (*dir != '/') {
2784                if (curdir == nullstr)
2785                        return 0;
2786                new = stack_putstr(curdir, new);
2787        }
2788        new = makestrspace(strlen(dir) + 2, new);
2789        lim = (char *)stackblock() + 1;
2790        if (*dir != '/') {
2791                if (new[-1] != '/')
2792                        USTPUTC('/', new);
2793                if (new > lim && *lim == '/')
2794                        lim++;
2795        } else {
2796                USTPUTC('/', new);
2797                cdcomppath++;
2798                if (dir[1] == '/' && dir[2] != '/') {
2799                        USTPUTC('/', new);
2800                        cdcomppath++;
2801                        lim++;
2802                }
2803        }
2804        p = strtok_r(cdcomppath, "/", &cdcomppath);
2805        while (p) {
2806                switch (*p) {
2807                case '.':
2808                        if (p[1] == '.' && p[2] == '\0') {
2809                                while (new > lim) {
2810                                        STUNPUTC(new);
2811                                        if (new[-1] == '/')
2812                                                break;
2813                                }
2814                                break;
2815                        }
2816                        if (p[1] == '\0')
2817                                break;
2818                        /* fall through */
2819                default:
2820                        new = stack_putstr(p, new);
2821                        USTPUTC('/', new);
2822                }
2823                p = strtok_r(NULL, "/", &cdcomppath);
2824        }
2825        if (new > lim)
2826                STUNPUTC(new);
2827        *new = 0;
2828        return stackblock();
2829}
2830
2831/*
2832 * Find out what the current directory is. If we already know the current
2833 * directory, this routine returns immediately.
2834 */
2835static char *
2836getpwd(void)
2837{
2838        char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2839        return dir ? dir : nullstr;
2840}
2841
2842static void
2843setpwd(const char *val, int setold)
2844{
2845        char *oldcur, *dir;
2846
2847        oldcur = dir = curdir;
2848
2849        if (setold) {
2850                setvar("OLDPWD", oldcur, VEXPORT);
2851        }
2852        INT_OFF;
2853        if (physdir != nullstr) {
2854                if (physdir != oldcur)
2855                        free(physdir);
2856                physdir = nullstr;
2857        }
2858        if (oldcur == val || !val) {
2859                char *s = getpwd();
2860                physdir = s;
2861                if (!val)
2862                        dir = s;
2863        } else
2864                dir = ckstrdup(val);
2865        if (oldcur != dir && oldcur != nullstr) {
2866                free(oldcur);
2867        }
2868        curdir = dir;
2869        INT_ON;
2870        setvar("PWD", dir, VEXPORT);
2871}
2872
2873static void hashcd(void);
2874
2875/*
2876 * Actually do the chdir.  We also call hashcd to let other routines
2877 * know that the current directory has changed.
2878 */
2879static int
2880docd(const char *dest, int flags)
2881{
2882        const char *dir = NULL;
2883        int err;
2884
2885        TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2886
2887        INT_OFF;
2888        if (!(flags & CD_PHYSICAL)) {
2889                dir = updatepwd(dest);
2890                if (dir)
2891                        dest = dir;
2892        }
2893        err = chdir(dest);
2894        if (err)
2895                goto out;
2896        setpwd(dir, 1);
2897        hashcd();
2898 out:
2899        INT_ON;
2900        return err;
2901}
2902
2903static int FAST_FUNC
2904cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2905{
2906        const char *dest;
2907        const char *path;
2908        const char *p;
2909        char c;
2910        struct stat statb;
2911        int flags;
2912        int len;
2913
2914        flags = cdopt();
2915        dest = *argptr;
2916        if (!dest)
2917                dest = bltinlookup("HOME");
2918        else if (LONE_DASH(dest)) {
2919                dest = bltinlookup("OLDPWD");
2920                flags |= CD_PRINT;
2921        }
2922        if (!dest)
2923                dest = nullstr;
2924        if (*dest == '/')
2925                goto step6;
2926        if (*dest == '.') {
2927                c = dest[1];
2928 dotdot:
2929                switch (c) {
2930                case '\0':
2931                case '/':
2932                        goto step6;
2933                case '.':
2934                        c = dest[2];
2935                        if (c != '.')
2936                                goto dotdot;
2937                }
2938        }
2939        if (!*dest)
2940                dest = ".";
2941        path = bltinlookup("CDPATH");
2942        while (p = path, (len = padvance(&path, dest)) >= 0) {
2943                c = *p;
2944                p = stalloc(len);
2945
2946                if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2947                        if (c && c != ':')
2948                                flags |= CD_PRINT;
2949 docd:
2950                        if (!docd(p, flags))
2951                                goto out;
2952                        goto err;
2953                }
2954        }
2955
2956 step6:
2957        p = dest;
2958        goto docd;
2959
2960 err:
2961        ash_msg_and_raise_perror("can't cd to %s", dest);
2962        /* NOTREACHED */
2963 out:
2964        if (flags & CD_PRINT)
2965                out1fmt("%s\n", curdir);
2966        return 0;
2967}
2968
2969static int FAST_FUNC
2970pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2971{
2972        int flags;
2973        const char *dir = curdir;
2974
2975        flags = cdopt();
2976        if (flags) {
2977                if (physdir == nullstr)
2978                        setpwd(dir, 0);
2979                dir = physdir;
2980        }
2981        out1fmt("%s\n", dir);
2982        return 0;
2983}
2984
2985
2986/* ============ ... */
2987
2988
2989#define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2990
2991/* Syntax classes */
2992#define CWORD     0             /* character is nothing special */
2993#define CNL       1             /* newline character */
2994#define CBACK     2             /* a backslash character */
2995#define CSQUOTE   3             /* single quote */
2996#define CDQUOTE   4             /* double quote */
2997#define CENDQUOTE 5             /* a terminating quote */
2998#define CBQUOTE   6             /* backwards single quote */
2999#define CVAR      7             /* a dollar sign */
3000#define CENDVAR   8             /* a '}' character */
3001#define CLP       9             /* a left paren in arithmetic */
3002#define CRP      10             /* a right paren in arithmetic */
3003#define CENDFILE 11             /* end of file */
3004#define CCTL     12             /* like CWORD, except it must be escaped */
3005#define CSPCL    13             /* these terminate a word */
3006#define CIGN     14             /* character should be ignored */
3007
3008#define PEOF     256
3009#if ENABLE_ASH_ALIAS
3010# define PEOA    257
3011#endif
3012
3013#define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
3014
3015#if ENABLE_FEATURE_SH_MATH
3016# define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
3017#else
3018# define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
3019#endif
3020static const uint16_t S_I_T[] ALIGN2 = {
3021#if ENABLE_ASH_ALIAS
3022        SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
3023#endif
3024        SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
3025        SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
3026        SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
3027        SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
3028        SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
3029        SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
3030        SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
3031        SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
3032        SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
3033        SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
3034        SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
3035#if !USE_SIT_FUNCTION
3036        SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
3037        SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
3038        SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
3039#endif
3040#undef SIT_ITEM
3041};
3042/* Constants below must match table above */
3043enum {
3044#if ENABLE_ASH_ALIAS
3045        CSPCL_CIGN_CIGN_CIGN               , /*  0 */
3046#endif
3047        CSPCL_CWORD_CWORD_CWORD            , /*  1 */
3048        CNL_CNL_CNL_CNL                    , /*  2 */
3049        CWORD_CCTL_CCTL_CWORD              , /*  3 */
3050        CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
3051        CVAR_CVAR_CWORD_CVAR               , /*  5 */
3052        CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
3053        CSPCL_CWORD_CWORD_CLP              , /*  7 */
3054        CSPCL_CWORD_CWORD_CRP              , /*  8 */
3055        CBACK_CBACK_CCTL_CBACK             , /*  9 */
3056        CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
3057        CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
3058        CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
3059        CWORD_CWORD_CWORD_CWORD            , /* 13 */
3060        CCTL_CCTL_CCTL_CCTL                , /* 14 */
3061};
3062
3063/* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
3064 * caller must ensure proper cast on it if c is *char_ptr!
3065 */
3066#if USE_SIT_FUNCTION
3067
3068static int
3069SIT(int c, int syntax)
3070{
3071        /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
3072        static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
3073        /*
3074         * This causes '/' to be prepended with CTLESC in dquoted string,
3075         * making "./file"* treated incorrectly because we feed
3076         * ".\/file*" string to glob(), confusing it (see expandmeta func).
3077         * The "homegrown" glob implementation is okay with that,
3078         * but glibc one isn't. With '/' always treated as CWORD,
3079         * both work fine.
3080         */
3081# if ENABLE_ASH_ALIAS
3082        static const uint8_t syntax_index_table[] ALIGN1 = {
3083                1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
3084                7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
3085                3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
3086                11, 3                           /* "}~" */
3087        };
3088# else
3089        static const uint8_t syntax_index_table[] ALIGN1 = {
3090                0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
3091                6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
3092                2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
3093                10, 2                           /* "}~" */
3094        };
3095# endif
3096        const char *s;
3097        int indx;
3098
3099        if (c == PEOF)
3100                return CENDFILE;
3101# if ENABLE_ASH_ALIAS
3102        if (c == PEOA)
3103                indx = 0;
3104        else
3105# endif
3106        {
3107                /* Cast is purely for paranoia here,
3108                 * just in case someone passed signed char to us */
3109                if ((unsigned char)c >= CTL_FIRST
3110                 && (unsigned char)c <= CTL_LAST
3111                ) {
3112                        return CCTL;
3113                }
3114                s = strchrnul(spec_symbls, c);
3115                if (*s == '\0')
3116                        return CWORD;
3117                indx = syntax_index_table[s - spec_symbls];
3118        }
3119        return (S_I_T[indx] >> (syntax*4)) & 0xf;
3120}
3121
3122#else   /* !USE_SIT_FUNCTION */
3123
3124static const uint8_t syntax_index_table[] ALIGN1 = {
3125        /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
3126        /*   0      */ CWORD_CWORD_CWORD_CWORD,
3127        /*   1      */ CWORD_CWORD_CWORD_CWORD,
3128        /*   2      */ CWORD_CWORD_CWORD_CWORD,
3129        /*   3      */ CWORD_CWORD_CWORD_CWORD,
3130        /*   4      */ CWORD_CWORD_CWORD_CWORD,
3131        /*   5      */ CWORD_CWORD_CWORD_CWORD,
3132        /*   6      */ CWORD_CWORD_CWORD_CWORD,
3133        /*   7      */ CWORD_CWORD_CWORD_CWORD,
3134        /*   8      */ CWORD_CWORD_CWORD_CWORD,
3135        /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
3136        /*  10 "\n" */ CNL_CNL_CNL_CNL,
3137        /*  11      */ CWORD_CWORD_CWORD_CWORD,
3138        /*  12      */ CWORD_CWORD_CWORD_CWORD,
3139        /*  13      */ CWORD_CWORD_CWORD_CWORD,
3140        /*  14      */ CWORD_CWORD_CWORD_CWORD,
3141        /*  15      */ CWORD_CWORD_CWORD_CWORD,
3142        /*  16      */ CWORD_CWORD_CWORD_CWORD,
3143        /*  17      */ CWORD_CWORD_CWORD_CWORD,
3144        /*  18      */ CWORD_CWORD_CWORD_CWORD,
3145        /*  19      */ CWORD_CWORD_CWORD_CWORD,
3146        /*  20      */ CWORD_CWORD_CWORD_CWORD,
3147        /*  21      */ CWORD_CWORD_CWORD_CWORD,
3148        /*  22      */ CWORD_CWORD_CWORD_CWORD,
3149        /*  23      */ CWORD_CWORD_CWORD_CWORD,
3150        /*  24      */ CWORD_CWORD_CWORD_CWORD,
3151        /*  25      */ CWORD_CWORD_CWORD_CWORD,
3152        /*  26      */ CWORD_CWORD_CWORD_CWORD,
3153        /*  27      */ CWORD_CWORD_CWORD_CWORD,
3154        /*  28      */ CWORD_CWORD_CWORD_CWORD,
3155        /*  29      */ CWORD_CWORD_CWORD_CWORD,
3156        /*  30      */ CWORD_CWORD_CWORD_CWORD,
3157        /*  31      */ CWORD_CWORD_CWORD_CWORD,
3158        /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
3159        /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
3160        /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
3161        /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
3162        /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
3163        /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
3164        /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
3165        /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
3166        /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
3167        /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
3168        /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
3169        /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
3170        /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
3171        /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
3172        /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
3173/* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
3174        /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
3175        /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
3176        /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
3177        /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
3178        /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
3179        /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
3180        /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
3181        /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
3182        /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
3183        /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
3184        /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
3185        /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
3186        /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
3187        /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
3188        /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
3189        /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
3190        /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
3191        /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
3192        /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
3193        /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
3194        /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
3195        /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
3196        /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
3197        /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
3198        /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
3199        /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
3200        /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
3201        /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
3202        /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
3203        /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
3204        /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
3205        /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
3206        /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
3207        /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
3208        /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
3209        /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
3210        /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3211        /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3212        /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3213        /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3214        /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3215        /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3216        /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3217        /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3218        /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3219        /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3220        /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3221        /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3222        /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3223        /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3224        /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3225        /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3226        /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3227        /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3228        /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3229        /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3230        /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3231        /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3232        /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3233        /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3234        /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3235        /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3236        /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3237        /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3238        /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3239        /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3240        /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3241        /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3242        /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3243        /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3244        /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3245        /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3246        /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3247        /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3248        /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3249        /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3250        /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3251        /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3252        /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3253        /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3254        /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3255        /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3256        /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3257        /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3258        /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3259        /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3260        /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3261        /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3262        /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3263        /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3264#if BASH_PROCESS_SUBST
3265        /* 137 CTLTOPROC    */ CCTL_CCTL_CCTL_CCTL,
3266        /* 138 CTLFROMPROC  */ CCTL_CCTL_CCTL_CCTL,
3267#else
3268        /* 137      */ CWORD_CWORD_CWORD_CWORD,
3269        /* 138      */ CWORD_CWORD_CWORD_CWORD,
3270#endif
3271        /* 139      */ CWORD_CWORD_CWORD_CWORD,
3272        /* 140      */ CWORD_CWORD_CWORD_CWORD,
3273        /* 141      */ CWORD_CWORD_CWORD_CWORD,
3274        /* 142      */ CWORD_CWORD_CWORD_CWORD,
3275        /* 143      */ CWORD_CWORD_CWORD_CWORD,
3276        /* 144      */ CWORD_CWORD_CWORD_CWORD,
3277        /* 145      */ CWORD_CWORD_CWORD_CWORD,
3278        /* 146      */ CWORD_CWORD_CWORD_CWORD,
3279        /* 147      */ CWORD_CWORD_CWORD_CWORD,
3280        /* 148      */ CWORD_CWORD_CWORD_CWORD,
3281        /* 149      */ CWORD_CWORD_CWORD_CWORD,
3282        /* 150      */ CWORD_CWORD_CWORD_CWORD,
3283        /* 151      */ CWORD_CWORD_CWORD_CWORD,
3284        /* 152      */ CWORD_CWORD_CWORD_CWORD,
3285        /* 153      */ CWORD_CWORD_CWORD_CWORD,
3286        /* 154      */ CWORD_CWORD_CWORD_CWORD,
3287        /* 155      */ CWORD_CWORD_CWORD_CWORD,
3288        /* 156      */ CWORD_CWORD_CWORD_CWORD,
3289        /* 157      */ CWORD_CWORD_CWORD_CWORD,
3290        /* 158      */ CWORD_CWORD_CWORD_CWORD,
3291        /* 159      */ CWORD_CWORD_CWORD_CWORD,
3292        /* 160      */ CWORD_CWORD_CWORD_CWORD,
3293        /* 161      */ CWORD_CWORD_CWORD_CWORD,
3294        /* 162      */ CWORD_CWORD_CWORD_CWORD,
3295        /* 163      */ CWORD_CWORD_CWORD_CWORD,
3296        /* 164      */ CWORD_CWORD_CWORD_CWORD,
3297        /* 165      */ CWORD_CWORD_CWORD_CWORD,
3298        /* 166      */ CWORD_CWORD_CWORD_CWORD,
3299        /* 167      */ CWORD_CWORD_CWORD_CWORD,
3300        /* 168      */ CWORD_CWORD_CWORD_CWORD,
3301        /* 169      */ CWORD_CWORD_CWORD_CWORD,
3302        /* 170      */ CWORD_CWORD_CWORD_CWORD,
3303        /* 171      */ CWORD_CWORD_CWORD_CWORD,
3304        /* 172      */ CWORD_CWORD_CWORD_CWORD,
3305        /* 173      */ CWORD_CWORD_CWORD_CWORD,
3306        /* 174      */ CWORD_CWORD_CWORD_CWORD,
3307        /* 175      */ CWORD_CWORD_CWORD_CWORD,
3308        /* 176      */ CWORD_CWORD_CWORD_CWORD,
3309        /* 177      */ CWORD_CWORD_CWORD_CWORD,
3310        /* 178      */ CWORD_CWORD_CWORD_CWORD,
3311        /* 179      */ CWORD_CWORD_CWORD_CWORD,
3312        /* 180      */ CWORD_CWORD_CWORD_CWORD,
3313        /* 181      */ CWORD_CWORD_CWORD_CWORD,
3314        /* 182      */ CWORD_CWORD_CWORD_CWORD,
3315        /* 183      */ CWORD_CWORD_CWORD_CWORD,
3316        /* 184      */ CWORD_CWORD_CWORD_CWORD,
3317        /* 185      */ CWORD_CWORD_CWORD_CWORD,
3318        /* 186      */ CWORD_CWORD_CWORD_CWORD,
3319        /* 187      */ CWORD_CWORD_CWORD_CWORD,
3320        /* 188      */ CWORD_CWORD_CWORD_CWORD,
3321        /* 189      */ CWORD_CWORD_CWORD_CWORD,
3322        /* 190      */ CWORD_CWORD_CWORD_CWORD,
3323        /* 191      */ CWORD_CWORD_CWORD_CWORD,
3324        /* 192      */ CWORD_CWORD_CWORD_CWORD,
3325        /* 193      */ CWORD_CWORD_CWORD_CWORD,
3326        /* 194      */ CWORD_CWORD_CWORD_CWORD,
3327        /* 195      */ CWORD_CWORD_CWORD_CWORD,
3328        /* 196      */ CWORD_CWORD_CWORD_CWORD,
3329        /* 197      */ CWORD_CWORD_CWORD_CWORD,
3330        /* 198      */ CWORD_CWORD_CWORD_CWORD,
3331        /* 199      */ CWORD_CWORD_CWORD_CWORD,
3332        /* 200      */ CWORD_CWORD_CWORD_CWORD,
3333        /* 201      */ CWORD_CWORD_CWORD_CWORD,
3334        /* 202      */ CWORD_CWORD_CWORD_CWORD,
3335        /* 203      */ CWORD_CWORD_CWORD_CWORD,
3336        /* 204      */ CWORD_CWORD_CWORD_CWORD,
3337        /* 205      */ CWORD_CWORD_CWORD_CWORD,
3338        /* 206      */ CWORD_CWORD_CWORD_CWORD,
3339        /* 207      */ CWORD_CWORD_CWORD_CWORD,
3340        /* 208      */ CWORD_CWORD_CWORD_CWORD,
3341        /* 209      */ CWORD_CWORD_CWORD_CWORD,
3342        /* 210      */ CWORD_CWORD_CWORD_CWORD,
3343        /* 211      */ CWORD_CWORD_CWORD_CWORD,
3344        /* 212      */ CWORD_CWORD_CWORD_CWORD,
3345        /* 213      */ CWORD_CWORD_CWORD_CWORD,
3346        /* 214      */ CWORD_CWORD_CWORD_CWORD,
3347        /* 215      */ CWORD_CWORD_CWORD_CWORD,
3348        /* 216      */ CWORD_CWORD_CWORD_CWORD,
3349        /* 217      */ CWORD_CWORD_CWORD_CWORD,
3350        /* 218      */ CWORD_CWORD_CWORD_CWORD,
3351        /* 219      */ CWORD_CWORD_CWORD_CWORD,
3352        /* 220      */ CWORD_CWORD_CWORD_CWORD,
3353        /* 221      */ CWORD_CWORD_CWORD_CWORD,
3354        /* 222      */ CWORD_CWORD_CWORD_CWORD,
3355        /* 223      */ CWORD_CWORD_CWORD_CWORD,
3356        /* 224      */ CWORD_CWORD_CWORD_CWORD,
3357        /* 225      */ CWORD_CWORD_CWORD_CWORD,
3358        /* 226      */ CWORD_CWORD_CWORD_CWORD,
3359        /* 227      */ CWORD_CWORD_CWORD_CWORD,
3360        /* 228      */ CWORD_CWORD_CWORD_CWORD,
3361        /* 229      */ CWORD_CWORD_CWORD_CWORD,
3362        /* 230      */ CWORD_CWORD_CWORD_CWORD,
3363        /* 231      */ CWORD_CWORD_CWORD_CWORD,
3364        /* 232      */ CWORD_CWORD_CWORD_CWORD,
3365        /* 233      */ CWORD_CWORD_CWORD_CWORD,
3366        /* 234      */ CWORD_CWORD_CWORD_CWORD,
3367        /* 235      */ CWORD_CWORD_CWORD_CWORD,
3368        /* 236      */ CWORD_CWORD_CWORD_CWORD,
3369        /* 237      */ CWORD_CWORD_CWORD_CWORD,
3370        /* 238      */ CWORD_CWORD_CWORD_CWORD,
3371        /* 239      */ CWORD_CWORD_CWORD_CWORD,
3372        /* 230      */ CWORD_CWORD_CWORD_CWORD,
3373        /* 241      */ CWORD_CWORD_CWORD_CWORD,
3374        /* 242      */ CWORD_CWORD_CWORD_CWORD,
3375        /* 243      */ CWORD_CWORD_CWORD_CWORD,
3376        /* 244      */ CWORD_CWORD_CWORD_CWORD,
3377        /* 245      */ CWORD_CWORD_CWORD_CWORD,
3378        /* 246      */ CWORD_CWORD_CWORD_CWORD,
3379        /* 247      */ CWORD_CWORD_CWORD_CWORD,
3380        /* 248      */ CWORD_CWORD_CWORD_CWORD,
3381        /* 249      */ CWORD_CWORD_CWORD_CWORD,
3382        /* 250      */ CWORD_CWORD_CWORD_CWORD,
3383        /* 251      */ CWORD_CWORD_CWORD_CWORD,
3384        /* 252      */ CWORD_CWORD_CWORD_CWORD,
3385        /* 253      */ CWORD_CWORD_CWORD_CWORD,
3386        /* 254      */ CWORD_CWORD_CWORD_CWORD,
3387        /* 255      */ CWORD_CWORD_CWORD_CWORD,
3388        /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3389# if ENABLE_ASH_ALIAS
3390        /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3391# endif
3392};
3393
3394#if 1
3395# define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3396#else /* debug version, caught one signed char bug */
3397# define SIT(c, syntax) \
3398        ({ \
3399                if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3400                        bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3401                if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3402                        bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3403                ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3404        })
3405#endif
3406
3407#endif  /* !USE_SIT_FUNCTION */
3408
3409
3410/* ============ Alias handling */
3411
3412#if ENABLE_ASH_ALIAS
3413
3414#define ALIASINUSE 1
3415#define ALIASDEAD  2
3416
3417struct alias {
3418        struct alias *next;
3419        char *name;
3420        char *val;
3421        int flag;
3422};
3423
3424
3425static struct alias **atab; // [ATABSIZE];
3426#define INIT_G_alias() do { \
3427        atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3428} while (0)
3429
3430
3431static struct alias **
3432__lookupalias(const char *name)
3433{
3434        unsigned int hashval;
3435        struct alias **app;
3436        const char *p;
3437        unsigned int ch;
3438
3439        p = name;
3440
3441        ch = (unsigned char)*p;
3442        hashval = ch << 4;
3443        while (ch) {
3444                hashval += ch;
3445                ch = (unsigned char)*++p;
3446        }
3447        app = &atab[hashval % ATABSIZE];
3448
3449        for (; *app; app = &(*app)->next) {
3450                if (strcmp(name, (*app)->name) == 0) {
3451                        break;
3452                }
3453        }
3454
3455        return app;
3456}
3457
3458static struct alias *
3459lookupalias(const char *name, int check)
3460{
3461        struct alias *ap = *__lookupalias(name);
3462
3463        if (check && ap && (ap->flag & ALIASINUSE))
3464                return NULL;
3465        return ap;
3466}
3467
3468static struct alias *
3469freealias(struct alias *ap)
3470{
3471        struct alias *next;
3472
3473        if (ap->flag & ALIASINUSE) {
3474                ap->flag |= ALIASDEAD;
3475                return ap;
3476        }
3477
3478        next = ap->next;
3479        free(ap->name);
3480        free(ap->val);
3481        free(ap);
3482        return next;
3483}
3484
3485static void
3486setalias(const char *name, const char *val)
3487{
3488        struct alias *ap, **app;
3489
3490        app = __lookupalias(name);
3491        ap = *app;
3492        INT_OFF;
3493        if (ap) {
3494                if (!(ap->flag & ALIASINUSE)) {
3495                        free(ap->val);
3496                }
3497                ap->val = ckstrdup(val);
3498                ap->flag &= ~ALIASDEAD;
3499        } else {
3500                /* not found */
3501                ap = ckzalloc(sizeof(struct alias));
3502                ap->name = ckstrdup(name);
3503                ap->val = ckstrdup(val);
3504                /*ap->flag = 0; - ckzalloc did it */
3505                /*ap->next = NULL;*/
3506                *app = ap;
3507        }
3508        INT_ON;
3509}
3510
3511static int
3512unalias(const char *name)
3513{
3514        struct alias **app;
3515
3516        app = __lookupalias(name);
3517
3518        if (*app) {
3519                INT_OFF;
3520                *app = freealias(*app);
3521                INT_ON;
3522                return 0;
3523        }
3524
3525        return 1;
3526}
3527
3528static void
3529rmaliases(void)
3530{
3531        struct alias *ap, **app;
3532        int i;
3533
3534        INT_OFF;
3535        for (i = 0; i < ATABSIZE; i++) {
3536                app = &atab[i];
3537                for (ap = *app; ap; ap = *app) {
3538                        *app = freealias(*app);
3539                        if (ap == *app) {
3540                                app = &ap->next;
3541                        }
3542                }
3543        }
3544        INT_ON;
3545}
3546
3547static void
3548printalias(const struct alias *ap)
3549{
3550        out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3551}
3552
3553/*
3554 * TODO - sort output
3555 */
3556static int FAST_FUNC
3557aliascmd(int argc UNUSED_PARAM, char **argv)
3558{
3559        char *n, *v;
3560        int ret = 0;
3561        struct alias *ap;
3562
3563        if (!argv[1]) {
3564                int i;
3565
3566                for (i = 0; i < ATABSIZE; i++) {
3567                        for (ap = atab[i]; ap; ap = ap->next) {
3568                                printalias(ap);
3569                        }
3570                }
3571                return 0;
3572        }
3573        while ((n = *++argv) != NULL) {
3574                v = strchr(n+1, '=');
3575                if (v == NULL) { /* n+1: funny ksh stuff */
3576                        ap = *__lookupalias(n);
3577                        if (ap == NULL) {
3578                                fprintf(stderr, "%s: %s not found\n", "alias", n);
3579                                ret = 1;
3580                        } else
3581                                printalias(ap);
3582                } else {
3583                        *v++ = '\0';
3584                        setalias(n, v);
3585                }
3586        }
3587
3588        return ret;
3589}
3590
3591static int FAST_FUNC
3592unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3593{
3594        int i;
3595
3596        while (nextopt("a") != '\0') {
3597                rmaliases();
3598                return 0;
3599        }
3600        for (i = 0; *argptr; argptr++) {
3601                if (unalias(*argptr)) {
3602                        fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3603                        i = 1;
3604                }
3605        }
3606
3607        return i;
3608}
3609
3610#endif /* ASH_ALIAS */
3611
3612
3613/* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3614#define FORK_FG    0
3615#define FORK_BG    1
3616#define FORK_NOJOB 2
3617
3618/* mode flags for showjob(s) */
3619#define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3620#define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3621#define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3622#define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3623
3624/*
3625 * A job structure contains information about a job.  A job is either a
3626 * single process or a set of processes contained in a pipeline.  In the
3627 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3628 * array of pids.
3629 */
3630struct procstat {
3631        pid_t   ps_pid;         /* process id */
3632        int     ps_status;      /* last process status from wait() */
3633        char    *ps_cmd;        /* text of command being run */
3634};
3635
3636struct job {
3637        struct procstat ps0;    /* status of process */
3638        struct procstat *ps;    /* status of processes when more than one */
3639#if JOBS
3640        int stopstatus;         /* status of a stopped job */
3641#endif
3642        unsigned nprocs;        /* number of processes */
3643
3644#define JOBRUNNING      0       /* at least one proc running */
3645#define JOBSTOPPED      1       /* all procs are stopped */
3646#define JOBDONE         2       /* all procs are completed */
3647        unsigned
3648                state: 8,
3649#if JOBS
3650                sigint: 1,      /* job was killed by SIGINT */
3651                jobctl: 1,      /* job running under job control */
3652#endif
3653                waited: 1,      /* true if this entry has been waited for */
3654                used: 1,        /* true if this entry is in used */
3655                changed: 1;     /* true if status has changed */
3656        struct job *prev_job;   /* previous job */
3657};
3658
3659static struct job *makejob(/*union node *,*/ int);
3660static int forkshell(struct job *, union node *, int);
3661static int waitforjob(struct job *);
3662
3663#if !JOBS
3664enum { doing_jobctl = 0 };
3665#define setjobctl(on) do {} while (0)
3666#else
3667static smallint doing_jobctl; //references:8
3668static void setjobctl(int);
3669#endif
3670
3671/*
3672 * Ignore a signal.
3673 */
3674static void
3675ignoresig(int signo)
3676{
3677        /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3678        if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3679                /* No, need to do it */
3680                signal(signo, SIG_IGN);
3681        }
3682        sigmode[signo - 1] = S_HARD_IGN;
3683}
3684
3685/*
3686 * Only one usage site - in setsignal()
3687 */
3688static void
3689signal_handler(int signo)
3690{
3691        if (signo == SIGCHLD) {
3692                got_sigchld = 1;
3693                if (!trap[SIGCHLD])
3694                        return;
3695        }
3696
3697        gotsig[signo - 1] = 1;
3698        pending_sig = signo;
3699
3700        if (signo == SIGINT && !trap[SIGINT]) {
3701                if (!suppress_int) {
3702                        pending_sig = 0;
3703                        raise_interrupt(); /* does not return */
3704                }
3705                pending_int = 1;
3706        }
3707}
3708
3709/*
3710 * Set the signal handler for the specified signal.  The routine figures
3711 * out what it should be set to.
3712 */
3713static void
3714setsignal(int signo)
3715{
3716        char *t;
3717        char cur_act, new_act;
3718        struct sigaction act;
3719
3720        t = trap[signo];
3721        new_act = S_DFL;
3722        if (t != NULL) { /* trap for this sig is set */
3723                new_act = S_CATCH;
3724                if (t[0] == '\0') /* trap is "": ignore this sig */
3725                        new_act = S_IGN;
3726        }
3727
3728        if (rootshell && new_act == S_DFL) {
3729                switch (signo) {
3730                case SIGINT:
3731                        if (iflag || minusc || sflag == 0)
3732                                new_act = S_CATCH;
3733                        break;
3734                case SIGQUIT:
3735#if DEBUG
3736                        if (debug)
3737                                break;
3738#endif
3739                        /* man bash:
3740                         * "In all cases, bash ignores SIGQUIT. Non-builtin
3741                         * commands run by bash have signal handlers
3742                         * set to the values inherited by the shell
3743                         * from its parent". */
3744                        new_act = S_IGN;
3745                        break;
3746                case SIGTERM:
3747                        if (iflag)
3748                                new_act = S_IGN;
3749                        break;
3750#if JOBS
3751                case SIGTSTP:
3752                case SIGTTOU:
3753                        if (mflag)
3754                                new_act = S_IGN;
3755                        break;
3756#endif
3757                }
3758        }
3759        /* if !rootshell, we reset SIGQUIT to DFL,
3760         * whereas we have to restore it to what shell got on entry.
3761         * This is handled by the fact that if signal was IGNored on entry,
3762         * then cur_act is S_HARD_IGN and we never change its sigaction
3763         * (see code below).
3764         */
3765
3766        if (signo == SIGCHLD)
3767                new_act = S_CATCH;
3768
3769        t = &sigmode[signo - 1];
3770        cur_act = *t;
3771        if (cur_act == 0) {
3772                /* current setting is not yet known */
3773                if (sigaction(signo, NULL, &act)) {
3774                        /* pretend it worked; maybe we should give a warning,
3775                         * but other shells don't. We don't alter sigmode,
3776                         * so we retry every time.
3777                         * btw, in Linux it never fails. --vda */
3778                        return;
3779                }
3780                if (act.sa_handler == SIG_IGN) {
3781                        cur_act = S_HARD_IGN;
3782                        if (mflag
3783                         && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3784                        ) {
3785                                cur_act = S_IGN;   /* don't hard ignore these */
3786                        }
3787                }
3788                if (act.sa_handler == SIG_DFL && new_act == S_DFL) {
3789                        /* installing SIG_DFL over SIG_DFL is a no-op */
3790                        /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3791                        *t = S_DFL;
3792                        return;
3793                }
3794        }
3795        if (cur_act == S_HARD_IGN || cur_act == new_act)
3796                return;
3797
3798        *t = new_act;
3799
3800        act.sa_handler = SIG_DFL;
3801        switch (new_act) {
3802        case S_CATCH:
3803                act.sa_handler = signal_handler;
3804                break;
3805        case S_IGN:
3806                act.sa_handler = SIG_IGN;
3807                break;
3808        }
3809        /* flags and mask matter only if !DFL and !IGN, but we do it
3810         * for all cases for more deterministic behavior:
3811         */
3812        act.sa_flags = 0; //TODO: why not SA_RESTART?
3813        sigfillset(&act.sa_mask);
3814
3815        sigaction_set(signo, &act);
3816}
3817
3818/* mode flags for set_curjob */
3819#define CUR_DELETE 2
3820#define CUR_RUNNING 1
3821#define CUR_STOPPED 0
3822
3823#if JOBS
3824/* pgrp of shell on invocation */
3825static int initialpgrp; //references:2
3826static int ttyfd = -1; //5
3827#endif
3828/* array of jobs */
3829static struct job *jobtab; //5
3830/* size of array */
3831static unsigned njobs; //4
3832/* current job */
3833static struct job *curjob; //lots
3834
3835#if 0
3836/* Bash has a feature: it restores termios after a successful wait for
3837 * a foreground job which had at least one stopped or sigkilled member.
3838 * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3839 * properly restoring tty state. Should we do this too?
3840 * A reproducer: ^Z an interactive python:
3841 *
3842 * # python
3843 * Python 2.7.12 (...)
3844 * >>> ^Z
3845 *      { python leaves tty in -icanon -echo state. We do survive that... }
3846 *  [1]+  Stopped                    python
3847 *      { ...however, next program (python #2) does not survive it well: }
3848 * # python
3849 * Python 2.7.12 (...)
3850 * >>> Traceback (most recent call last):
3851 *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3852 *   File "<stdin>", line 1, in <module>
3853 * NameError: name 'qwerty' is not defined
3854 *
3855 * The implementation below is modeled on bash code and seems to work.
3856 * However, I'm not sure we should do this. For one: what if I'd fg
3857 * the stopped python instead? It'll be confused by "restored" tty state.
3858 */
3859static struct termios shell_tty_info;
3860static void
3861get_tty_state(void)
3862{
3863        if (rootshell && ttyfd >= 0)
3864                tcgetattr(ttyfd, &shell_tty_info);
3865}
3866static void
3867set_tty_state(void)
3868{
3869        /* if (rootshell) - caller ensures this */
3870        if (ttyfd >= 0)
3871                tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3872}
3873static int
3874job_signal_status(struct job *jp)
3875{
3876        int status;
3877        unsigned i;
3878        struct procstat *ps = jp->ps;
3879        for (i = 0; i < jp->nprocs; i++) {
3880                status = ps[i].ps_status;
3881                if (WIFSIGNALED(status) || WIFSTOPPED(status))
3882                        return status;
3883        }
3884        return 0;
3885}
3886static void
3887restore_tty_if_stopped_or_signaled(struct job *jp)
3888{
3889//TODO: check what happens if we come from waitforjob() in expbackq()
3890        if (rootshell) {
3891                int s = job_signal_status(jp);
3892                if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3893                        set_tty_state();
3894        }
3895}
3896#else
3897# define get_tty_state() ((void)0)
3898# define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3899#endif
3900
3901static void
3902set_curjob(struct job *jp, unsigned mode)
3903{
3904        struct job *jp1;
3905        struct job **jpp, **curp;
3906
3907        /* first remove from list */
3908        jpp = curp = &curjob;
3909        while (1) {
3910                jp1 = *jpp;
3911                if (jp1 == jp)
3912                        break;
3913                jpp = &jp1->prev_job;
3914        }
3915        *jpp = jp1->prev_job;
3916
3917        /* Then re-insert in correct position */
3918        jpp = curp;
3919        switch (mode) {
3920        default:
3921#if DEBUG
3922                abort();
3923#endif
3924        case CUR_DELETE:
3925                /* job being deleted */
3926                break;
3927        case CUR_RUNNING:
3928                /* newly created job or backgrounded job,
3929                 * put after all stopped jobs.
3930                 */
3931                while (1) {
3932                        jp1 = *jpp;
3933#if JOBS
3934                        if (!jp1 || jp1->state != JOBSTOPPED)
3935#endif
3936                                break;
3937                        jpp = &jp1->prev_job;
3938                }
3939                /* FALLTHROUGH */
3940#if JOBS
3941        case CUR_STOPPED:
3942#endif
3943                /* newly stopped job - becomes curjob */
3944                jp->prev_job = *jpp;
3945                *jpp = jp;
3946                break;
3947        }
3948}
3949
3950#if JOBS || DEBUG
3951static int
3952jobno(const struct job *jp)
3953{
3954        return jp - jobtab + 1;
3955}
3956#endif
3957
3958/*
3959 * Convert a job name to a job structure.
3960 */
3961#if !JOBS
3962#define getjob(name, getctl) getjob(name)
3963#endif
3964static struct job *
3965getjob(const char *name, int getctl)
3966{
3967        struct job *jp;
3968        struct job *found;
3969        const char *err_msg = "%s: no such job";
3970        unsigned num;
3971        int c;
3972        const char *p;
3973        char *(*match)(const char *, const char *);
3974
3975        jp = curjob;
3976        p = name;
3977        if (!p)
3978                goto currentjob;
3979
3980        if (*p != '%')
3981                goto err;
3982
3983        c = *++p;
3984        if (!c)
3985                goto currentjob;
3986
3987        if (!p[1]) {
3988                if (c == '+' || c == '%') {
3989 currentjob:
3990                        err_msg = "No current job";
3991                        goto check;
3992                }
3993                if (c == '-') {
3994                        if (jp)
3995                                jp = jp->prev_job;
3996                        err_msg = "No previous job";
3997 check:
3998                        if (!jp)
3999                                goto err;
4000                        goto gotit;
4001                }
4002        }
4003
4004        if (is_number(p)) {
4005                num = atoi(p);
4006                if (num > 0 && num <= njobs) {
4007                        jp = jobtab + num - 1;
4008                        if (jp->used)
4009                                goto gotit;
4010                        goto err;
4011                }
4012        }
4013
4014        match = prefix;
4015        if (*p == '?') {
4016                match = strstr;
4017                p++;
4018        }
4019
4020        found = NULL;
4021        while (jp) {
4022                if (match(jp->ps[0].ps_cmd, p)) {
4023                        if (found)
4024                                goto err;
4025                        found = jp;
4026                        err_msg = "%s: ambiguous";
4027                }
4028                jp = jp->prev_job;
4029        }
4030        if (!found)
4031                goto err;
4032        jp = found;
4033
4034 gotit:
4035#if JOBS
4036        err_msg = "job %s not created under job control";
4037        if (getctl && jp->jobctl == 0)
4038                goto err;
4039#endif
4040        return jp;
4041 err:
4042        ash_msg_and_raise_error(err_msg, name);
4043}
4044
4045/*
4046 * Mark a job structure as unused.
4047 */
4048static void
4049freejob(struct job *jp)
4050{
4051        struct procstat *ps;
4052        int i;
4053
4054        INT_OFF;
4055        for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
4056                if (ps->ps_cmd != nullstr)
4057                        free(ps->ps_cmd);
4058        }
4059        if (jp->ps != &jp->ps0)
4060                free(jp->ps);
4061        jp->used = 0;
4062        set_curjob(jp, CUR_DELETE);
4063        INT_ON;
4064}
4065
4066#if JOBS
4067static void
4068xtcsetpgrp(int fd, pid_t pgrp)
4069{
4070        if (tcsetpgrp(fd, pgrp))
4071                ash_msg_and_raise_perror("can't set tty process group");
4072}
4073
4074/*
4075 * Turn job control on and off.
4076 *
4077 * Note:  This code assumes that the third arg to ioctl is a character
4078 * pointer, which is true on Berkeley systems but not System V.  Since
4079 * System V doesn't have job control yet, this isn't a problem now.
4080 *
4081 * Called with interrupts off.
4082 */
4083static void
4084setjobctl(int on)
4085{
4086        int fd;
4087        int pgrp;
4088
4089        if (on == doing_jobctl || rootshell == 0)
4090                return;
4091        if (on) {
4092                int ofd;
4093                ofd = fd = open(_PATH_TTY, O_RDWR);
4094                if (fd < 0) {
4095        /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
4096         * That sometimes helps to acquire controlling tty.
4097         * Obviously, a workaround for bugs when someone
4098         * failed to provide a controlling tty to bash! :) */
4099                        fd = 2;
4100                        while (!isatty(fd))
4101                                if (--fd < 0)
4102                                        goto out;
4103                }
4104                /* fd is a tty at this point */
4105                fd = fcntl(fd, F_DUPFD_CLOEXEC, 10);
4106                if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
4107                        close(ofd);
4108                if (fd < 0)
4109                        goto out; /* F_DUPFD failed */
4110                if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
4111                        close_on_exec_on(fd);
4112                while (1) { /* while we are in the background */
4113                        pgrp = tcgetpgrp(fd);
4114                        if (pgrp < 0) {
4115 out:
4116                                ash_msg("can't access tty; job control turned off");
4117                                mflag = on = 0;
4118                                goto close;
4119                        }
4120                        if (pgrp == getpgrp())
4121                                break;
4122                        killpg(0, SIGTTIN);
4123                }
4124                initialpgrp = pgrp;
4125
4126                setsignal(SIGTSTP);
4127                setsignal(SIGTTOU);
4128                setsignal(SIGTTIN);
4129                pgrp = rootpid;
4130                setpgid(0, pgrp);
4131                xtcsetpgrp(fd, pgrp);
4132        } else {
4133                /* turning job control off */
4134                fd = ttyfd;
4135                pgrp = initialpgrp;
4136                /* was xtcsetpgrp, but this can make exiting ash
4137                 * loop forever if pty is already deleted */
4138                tcsetpgrp(fd, pgrp);
4139                setpgid(0, pgrp);
4140                setsignal(SIGTSTP);
4141                setsignal(SIGTTOU);
4142                setsignal(SIGTTIN);
4143 close:
4144                if (fd >= 0)
4145                        close(fd);
4146                fd = -1;
4147        }
4148        ttyfd = fd;
4149        doing_jobctl = on;
4150}
4151
4152static int FAST_FUNC
4153killcmd(int argc, char **argv)
4154{
4155        if (argv[1] && strcmp(argv[1], "-l") != 0) {
4156                int i = 1;
4157                do {
4158                        if (argv[i][0] == '%') {
4159                                /*
4160                                 * "kill %N" - job kill
4161                                 * Converting to pgrp / pid kill
4162                                 */
4163                                struct job *jp;
4164                                char *dst;
4165                                int j, n;
4166
4167                                jp = getjob(argv[i], 0);
4168                                /*
4169                                 * In jobs started under job control, we signal
4170                                 * entire process group by kill -PGRP_ID.
4171                                 * This happens, f.e., in interactive shell.
4172                                 *
4173                                 * Otherwise, we signal each child via
4174                                 * kill PID1 PID2 PID3.
4175                                 * Testcases:
4176                                 * sh -c 'sleep 1|sleep 1 & kill %1'
4177                                 * sh -c 'true|sleep 2 & sleep 1; kill %1'
4178                                 * sh -c 'true|sleep 1 & sleep 2; kill %1'
4179                                 */
4180                                n = jp->nprocs; /* can't be 0 (I hope) */
4181                                if (jp->jobctl)
4182                                        n = 1;
4183                                dst = alloca(n * sizeof(int)*4);
4184                                argv[i] = dst;
4185                                for (j = 0; j < n; j++) {
4186                                        struct procstat *ps = &jp->ps[j];
4187                                        /* Skip non-running and not-stopped members
4188                                         * (i.e. dead members) of the job
4189                                         */
4190                                        if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
4191                                                continue;
4192                                        /*
4193                                         * kill_main has matching code to expect
4194                                         * leading space. Needed to not confuse
4195                                         * negative pids with "kill -SIGNAL_NO" syntax
4196                                         */
4197                                        dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
4198                                }
4199                                *dst = '\0';
4200                        }
4201                } while (argv[++i]);
4202        }
4203        return kill_main(argc, argv);
4204}
4205
4206static void
4207showpipe(struct job *jp /*, FILE *out*/)
4208{
4209        struct procstat *ps;
4210        struct procstat *psend;
4211
4212        psend = jp->ps + jp->nprocs;
4213        for (ps = jp->ps + 1; ps < psend; ps++)
4214                printf(" | %s", ps->ps_cmd);
4215        newline_and_flush(stdout);
4216        flush_stdout_stderr();
4217}
4218
4219
4220static int
4221restartjob(struct job *jp, int mode)
4222{
4223        struct procstat *ps;
4224        int i;
4225        int status;
4226        pid_t pgid;
4227
4228        INT_OFF;
4229        if (jp->state == JOBDONE)
4230                goto out;
4231        jp->state = JOBRUNNING;
4232        pgid = jp->ps[0].ps_pid;
4233        if (mode == FORK_FG) {
4234                get_tty_state();
4235                xtcsetpgrp(ttyfd, pgid);
4236        }
4237        killpg(pgid, SIGCONT);
4238        ps = jp->ps;
4239        i = jp->nprocs;
4240        do {
4241                if (WIFSTOPPED(ps->ps_status)) {
4242                        ps->ps_status = -1;
4243                }
4244                ps++;
4245        } while (--i);
4246 out:
4247        status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4248        INT_ON;
4249        return status;
4250}
4251
4252static int FAST_FUNC
4253fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4254{
4255        struct job *jp;
4256        int mode;
4257        int retval;
4258
4259        mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4260        nextopt(nullstr);
4261        argv = argptr;
4262        do {
4263                jp = getjob(*argv, 1);
4264                if (mode == FORK_BG) {
4265                        set_curjob(jp, CUR_RUNNING);
4266                        printf("[%d] ", jobno(jp));
4267                }
4268                out1str(jp->ps[0].ps_cmd);
4269                showpipe(jp /*, stdout*/);
4270                retval = restartjob(jp, mode);
4271        } while (*argv && *++argv);
4272        return retval;
4273}
4274#endif
4275
4276static int
4277sprint_status48(char *os, int status, int sigonly)
4278{
4279        char *s = os;
4280        int st;
4281
4282        if (!WIFEXITED(status)) {
4283#if JOBS
4284                if (WIFSTOPPED(status))
4285                        st = WSTOPSIG(status);
4286                else
4287#endif
4288                        st = WTERMSIG(status);
4289                if (sigonly) {
4290                        if (st == SIGINT || st == SIGPIPE)
4291                                goto out;
4292#if JOBS
4293                        if (WIFSTOPPED(status))
4294                                goto out;
4295#endif
4296                }
4297                st &= 0x7f;
4298                s = stpncpy(s, strsignal(st), 32);
4299                if (WCOREDUMP(status)) {
4300                        s = stpcpy(s, " (core dumped)");
4301                }
4302        } else if (!sigonly) {
4303                st = WEXITSTATUS(status);
4304                s += fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4305        }
4306 out:
4307        return s - os;
4308}
4309
4310#define DOWAIT_NONBLOCK 0
4311#define DOWAIT_BLOCK    1
4312#define DOWAIT_BLOCK_OR_SIG 2
4313#if BASH_WAIT_N
4314# define DOWAIT_JOBSTATUS 0x10   /* OR this to get job's exitstatus instead of pid */
4315#endif
4316
4317static int
4318waitproc(int block, int *status)
4319{
4320        sigset_t oldmask;
4321        int flags = block == DOWAIT_BLOCK ? 0 : WNOHANG;
4322        int err;
4323
4324#if JOBS
4325        if (doing_jobctl)
4326                flags |= WUNTRACED;
4327#endif
4328
4329        do {
4330                got_sigchld = 0;
4331                do
4332                        err = waitpid(-1, status, flags);
4333                while (err < 0 && errno == EINTR);
4334
4335                if (err || (err = -!block))
4336                        break;
4337
4338                sigfillset(&oldmask);
4339                sigprocmask2(SIG_SETMASK, &oldmask); /* mask is updated */
4340                while (!got_sigchld && !pending_sig)
4341                        sigsuspend(&oldmask);
4342                sigprocmask(SIG_SETMASK, &oldmask, NULL);
4343                //simpler, but unsafe: a signal can set pending_sig after check, but before pause():
4344                //while (!got_sigchld && !pending_sig)
4345                //      pause();
4346
4347        } while (got_sigchld);
4348
4349        return err;
4350}
4351
4352static int
4353waitone(int block, struct job *job)
4354{
4355        int pid;
4356        int status;
4357        struct job *jp;
4358        struct job *thisjob = NULL;
4359#if BASH_WAIT_N
4360        bool want_jobexitstatus = (block & DOWAIT_JOBSTATUS);
4361        block = (block & ~DOWAIT_JOBSTATUS);
4362#endif
4363
4364        TRACE(("dowait(0x%x) called\n", block));
4365
4366        /* It's wrong to call waitpid() outside of INT_OFF region:
4367         * signal can arrive just after syscall return and handler can
4368         * longjmp away, losing stop/exit notification processing.
4369         * Thus, for "jobs" builtin, and for waiting for a fg job,
4370         * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4371         *
4372         * However, for "wait" builtin it is wrong to simply call waitpid()
4373         * in INT_OFF region: "wait" needs to wait for any running job
4374         * to change state, but should exit on any trap too.
4375         * In INT_OFF region, a signal just before syscall entry can set
4376         * pending_sig variables, but we can't check them, and we would
4377         * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4378         *
4379         * Because of this, we run inside INT_OFF, but use a special routine
4380         * which combines waitpid() and sigsuspend().
4381         * This is the reason why we need to have a handler for SIGCHLD:
4382         * SIG_DFL handler does not wake sigsuspend().
4383         */
4384        INT_OFF;
4385        pid = waitproc(block, &status);
4386        TRACE(("wait returns pid %d, status=%d\n", pid, status));
4387        if (pid <= 0)
4388                goto out;
4389
4390        for (jp = curjob; jp; jp = jp->prev_job) {
4391                int jobstate;
4392                struct procstat *ps;
4393                struct procstat *psend;
4394                if (jp->state == JOBDONE)
4395                        continue;
4396                jobstate = JOBDONE;
4397                ps = jp->ps;
4398                psend = ps + jp->nprocs;
4399                do {
4400                        if (ps->ps_pid == pid) {
4401                                TRACE(("Job %d: changing status of proc %d "
4402                                        "from 0x%x to 0x%x\n",
4403                                        jobno(jp), pid, ps->ps_status, status));
4404                                ps->ps_status = status;
4405                                thisjob = jp;
4406                        }
4407                        if (ps->ps_status == -1)
4408                                jobstate = JOBRUNNING;
4409#if JOBS
4410                        if (jobstate == JOBRUNNING)
4411                                continue;
4412                        if (WIFSTOPPED(ps->ps_status)) {
4413                                jp->stopstatus = ps->ps_status;
4414                                jobstate = JOBSTOPPED;
4415                        }
4416#endif
4417                } while (++ps < psend);
4418                if (!thisjob)
4419                        continue;
4420
4421                /* Found the job where one of its processes changed its state.
4422                 * Is there at least one live and running process in this job? */
4423                if (jobstate != JOBRUNNING) {
4424                        /* No. All live processes in the job are stopped
4425                         * (JOBSTOPPED) or there are no live processes (JOBDONE)
4426                         */
4427                        thisjob->changed = 1;
4428                        if (thisjob->state != jobstate) {
4429                                TRACE(("Job %d: changing state from %d to %d\n",
4430                                        jobno(thisjob), thisjob->state, jobstate));
4431                                thisjob->state = jobstate;
4432#if JOBS
4433                                if (jobstate == JOBSTOPPED)
4434                                        set_curjob(thisjob, CUR_STOPPED);
4435#endif
4436                        }
4437                }
4438                goto out;
4439        }
4440        /* The process wasn't found in job list */
4441 out:
4442        INT_ON;
4443
4444#if BASH_WAIT_N
4445        if (want_jobexitstatus) {
4446                pid = -1;
4447                if (thisjob && thisjob->state == JOBDONE)
4448                        pid = thisjob->ps[thisjob->nprocs - 1].ps_status;
4449        }
4450#endif
4451        if (thisjob && thisjob == job) {
4452                char s[48 + 1];
4453                int len;
4454
4455                len = sprint_status48(s, status, 1);
4456                if (len) {
4457                        s[len] = '\n';
4458                        s[len + 1] = '\0';
4459                        out2str(s);
4460                }
4461        }
4462        return pid;
4463}
4464
4465static int
4466dowait(int block, struct job *jp)
4467{
4468        smallint gotchld = *(volatile smallint *)&got_sigchld;
4469        int rpid;
4470        int pid;
4471
4472        if (jp && jp->state != JOBRUNNING)
4473                block = DOWAIT_NONBLOCK;
4474
4475        if (block == DOWAIT_NONBLOCK && !gotchld)
4476                return 1;
4477
4478        rpid = 1;
4479
4480        do {
4481                pid = waitone(block, jp);
4482                rpid &= !!pid;
4483
4484                if (!pid || (jp && jp->state != JOBRUNNING))
4485                        block = DOWAIT_NONBLOCK;
4486        } while (pid >= 0);
4487
4488        return rpid;
4489}
4490
4491#if JOBS
4492static void
4493showjob(struct job *jp, int mode)
4494{
4495        struct procstat *ps;
4496        struct procstat *psend;
4497        int col;
4498        int indent_col;
4499        char s[16 + 16 + 48];
4500        FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4501
4502        ps = jp->ps;
4503
4504        if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4505                /* just output process (group) id of pipeline */
4506                fprintf(out, "%d\n", ps->ps_pid);
4507                return;
4508        }
4509
4510        col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4511        indent_col = col;
4512
4513        if (jp == curjob)
4514                s[col - 3] = '+';
4515        else if (curjob && jp == curjob->prev_job)
4516                s[col - 3] = '-';
4517
4518        if (mode & SHOW_PIDS)
4519                col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4520
4521        psend = ps + jp->nprocs;
4522
4523        if (jp->state == JOBRUNNING) {
4524                strcpy(s + col, "Running");
4525                col += sizeof("Running") - 1;
4526        } else {
4527                int status = psend[-1].ps_status;
4528                if (jp->state == JOBSTOPPED)
4529                        status = jp->stopstatus;
4530                col += sprint_status48(s + col, status, 0);
4531        }
4532        /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4533
4534        /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4535         * or prints several "PID             | <cmdN>" lines,
4536         * depending on SHOW_PIDS bit.
4537         * We do not print status of individual processes
4538         * between PID and <cmdN>. bash does it, but not very well:
4539         * first line shows overall job status, not process status,
4540         * making it impossible to know 1st process status.
4541         */
4542        goto start;
4543        do {
4544                /* for each process */
4545                s[0] = '\0';
4546                col = 33;
4547                if (mode & SHOW_PIDS)
4548                        col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4549 start:
4550                fprintf(out, "%s%*c%s%s",
4551                                s,
4552                                33 - col >= 0 ? 33 - col : 0, ' ',
4553                                ps == jp->ps ? "" : "| ",
4554                                ps->ps_cmd
4555                );
4556        } while (++ps != psend);
4557        newline_and_flush(out);
4558
4559        jp->changed = 0;
4560
4561        if (jp->state == JOBDONE) {
4562                TRACE(("showjob: freeing job %d\n", jobno(jp)));
4563                freejob(jp);
4564        }
4565}
4566
4567/*
4568 * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4569 * statuses have changed since the last call to showjobs.
4570 */
4571static void
4572showjobs(int mode)
4573{
4574        struct job *jp;
4575
4576        TRACE(("showjobs(0x%x) called\n", mode));
4577
4578        /* Handle all finished jobs */
4579        dowait(DOWAIT_NONBLOCK, NULL);
4580
4581        for (jp = curjob; jp; jp = jp->prev_job) {
4582                if (!(mode & SHOW_CHANGED) || jp->changed) {
4583                        showjob(jp, mode);
4584                }
4585        }
4586}
4587
4588static int FAST_FUNC
4589jobscmd(int argc UNUSED_PARAM, char **argv)
4590{
4591        int mode, m;
4592
4593        mode = 0;
4594        while ((m = nextopt("lp")) != '\0') {
4595                if (m == 'l')
4596                        mode |= SHOW_PIDS;
4597                else
4598                        mode |= SHOW_ONLY_PGID;
4599        }
4600
4601        argv = argptr;
4602        if (*argv) {
4603                do
4604                        showjob(getjob(*argv, 0), mode);
4605                while (*++argv);
4606        } else {
4607                showjobs(mode);
4608        }
4609
4610        return 0;
4611}
4612#endif /* JOBS */
4613
4614/* Called only on finished or stopped jobs (no members are running) */
4615static int
4616getstatus(struct job *job)
4617{
4618        int status;
4619        int retval;
4620        struct procstat *ps;
4621
4622        /* Fetch last member's status */
4623        ps = job->ps + job->nprocs - 1;
4624        status = ps->ps_status;
4625        if (pipefail) {
4626                /* "set -o pipefail" mode: use last _nonzero_ status */
4627                while (status == 0 && --ps >= job->ps)
4628                        status = ps->ps_status;
4629        }
4630
4631        retval = WEXITSTATUS(status);
4632        if (!WIFEXITED(status)) {
4633#if JOBS
4634                retval = WSTOPSIG(status);
4635                if (!WIFSTOPPED(status))
4636#endif
4637                {
4638                        /* XXX: limits number of signals */
4639                        retval = WTERMSIG(status);
4640#if JOBS
4641                        if (retval == SIGINT)
4642                                job->sigint = 1;
4643#endif
4644                }
4645                retval |= 128;
4646        }
4647        TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4648                jobno(job), job->nprocs, status, retval));
4649        return retval;
4650}
4651
4652static int FAST_FUNC
4653waitcmd(int argc UNUSED_PARAM, char **argv)
4654{
4655        struct job *job;
4656        int retval;
4657        struct job *jp;
4658#if BASH_WAIT_N
4659        int status;
4660        char one = nextopt("n");
4661#else
4662        nextopt(nullstr);
4663#endif
4664        retval = 0;
4665
4666        argv = argptr;
4667        if (!argv[0]) {
4668                /* wait for all jobs / one job if -n */
4669                for (;;) {
4670                        jp = curjob;
4671#if BASH_WAIT_N
4672                        if (one && !jp)
4673                                /* exitcode of "wait -n" with nothing to wait for is 127, not 0 */
4674                                retval = 127;
4675#endif
4676                        while (1) {
4677                                if (!jp) /* no running procs */
4678                                        goto ret;
4679                                if (jp->state == JOBRUNNING)
4680                                        break;
4681                                jp->waited = 1;
4682                                jp = jp->prev_job;
4683                        }
4684        /* man bash:
4685         * "When bash is waiting for an asynchronous command via
4686         * the wait builtin, the reception of a signal for which a trap
4687         * has been set will cause the wait builtin to return immediately
4688         * with an exit status greater than 128, immediately after which
4689         * the trap is executed."
4690         */
4691#if BASH_WAIT_N
4692                        status = dowait(DOWAIT_BLOCK_OR_SIG | DOWAIT_JOBSTATUS, NULL);
4693#else
4694                        dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4695#endif
4696                        /* if child sends us a signal *and immediately exits*,
4697                         * dowait() returns pid > 0. Check this case,
4698                         * not "if (dowait() < 0)"!
4699                         */
4700                        if (pending_sig)
4701                                goto sigout;
4702#if BASH_WAIT_N
4703                        if (one) {
4704                                /* wait -n waits for one _job_, not one _process_.
4705                                 *  date; sleep 3 & sleep 2 | sleep 1 & wait -n; date
4706                                 * should wait for 2 seconds. Not 1 or 3.
4707                                 */
4708                                if (status != -1 && !WIFSTOPPED(status)) {
4709                                        retval = WEXITSTATUS(status);
4710                                        if (WIFSIGNALED(status))
4711                                                retval = 128 | WTERMSIG(status);
4712                                        goto ret;
4713                                }
4714                        }
4715#endif
4716                }
4717        }
4718
4719        retval = 127;
4720        do {
4721                if (**argv != '%') {
4722                        pid_t pid = number(*argv);
4723                        job = curjob;
4724                        while (1) {
4725                                if (!job)
4726                                        goto repeat;
4727                                if (job->ps[job->nprocs - 1].ps_pid == pid)
4728                                        break;
4729                                job = job->prev_job;
4730                        }
4731                } else {
4732                        job = getjob(*argv, 0);
4733                }
4734                /* loop until process terminated or stopped */
4735                dowait(DOWAIT_BLOCK_OR_SIG, job);
4736                if (pending_sig)
4737                        goto sigout;
4738                job->waited = 1;
4739                retval = getstatus(job);
4740 repeat: ;
4741        } while (*++argv);
4742
4743 ret:
4744        return retval;
4745 sigout:
4746        retval = 128 | pending_sig;
4747        return retval;
4748}
4749
4750static struct job *
4751growjobtab(void)
4752{
4753        size_t len;
4754        ptrdiff_t offset;
4755        struct job *jp, *jq;
4756
4757        len = njobs * sizeof(*jp);
4758        jq = jobtab;
4759        jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4760
4761        offset = (char *)jp - (char *)jq;
4762        if (offset) {
4763                /* Relocate pointers */
4764                size_t l = len;
4765
4766                jq = (struct job *)((char *)jq + l);
4767                while (l) {
4768                        l -= sizeof(*jp);
4769                        jq--;
4770#define joff(p) ((struct job *)((char *)(p) + l))
4771#define jmove(p) (p) = (void *)((char *)(p) + offset)
4772                        if (joff(jp)->ps == &jq->ps0)
4773                                jmove(joff(jp)->ps);
4774                        if (joff(jp)->prev_job)
4775                                jmove(joff(jp)->prev_job);
4776                }
4777                if (curjob)
4778                        jmove(curjob);
4779#undef joff
4780#undef jmove
4781        }
4782
4783        njobs += 4;
4784        jobtab = jp;
4785        jp = (struct job *)((char *)jp + len);
4786        jq = jp + 3;
4787        do {
4788                jq->used = 0;
4789        } while (--jq >= jp);
4790        return jp;
4791}
4792
4793/*
4794 * Return a new job structure.
4795 * Called with interrupts off.
4796 */
4797static struct job *
4798makejob(/*union node *node,*/ int nprocs)
4799{
4800        int i;
4801        struct job *jp;
4802
4803        for (i = njobs, jp = jobtab; ; jp++) {
4804                if (--i < 0) {
4805                        jp = growjobtab();
4806                        break;
4807                }
4808                if (jp->used == 0)
4809                        break;
4810                if (jp->state != JOBDONE || !jp->waited)
4811                        continue;
4812#if JOBS
4813                if (doing_jobctl)
4814                        continue;
4815#endif
4816                freejob(jp);
4817                break;
4818        }
4819        memset(jp, 0, sizeof(*jp));
4820#if JOBS
4821        /* jp->jobctl is a bitfield.
4822         * "jp->jobctl |= doing_jobctl" likely to give awful code */
4823        if (doing_jobctl)
4824                jp->jobctl = 1;
4825#endif
4826        jp->prev_job = curjob;
4827        curjob = jp;
4828        jp->used = 1;
4829        jp->ps = &jp->ps0;
4830        if (nprocs > 1) {
4831                jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4832        }
4833        TRACE(("makejob(%d) returns %%%d\n", nprocs,
4834                                jobno(jp)));
4835        return jp;
4836}
4837
4838#if JOBS
4839/*
4840 * Return a string identifying a command (to be printed by the
4841 * jobs command).
4842 */
4843static char *cmdnextc;
4844
4845static void
4846cmdputs(const char *s)
4847{
4848        static const char vstype[VSTYPE + 1][3] ALIGN1 = {
4849                "", "}", "-", "+", "?", "=",
4850                "%", "%%", "#", "##"
4851                IF_BASH_SUBSTR(, ":")
4852                IF_BASH_PATTERN_SUBST(, "/", "//")
4853        };
4854
4855        const char *p, *str;
4856        char cc[2];
4857        char *nextc;
4858        unsigned char c;
4859        unsigned char subtype = 0;
4860        int quoted = 0;
4861
4862        cc[1] = '\0';
4863        nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4864        p = s;
4865        while ((c = *p++) != '\0') {
4866                str = NULL;
4867                switch (c) {
4868                case CTLESC:
4869                        c = *p++;
4870                        break;
4871                case CTLVAR:
4872                        subtype = *p++;
4873                        if ((subtype & VSTYPE) == VSLENGTH)
4874                                str = "${#";
4875                        else
4876                                str = "${";
4877                        goto dostr;
4878                case CTLENDVAR:
4879                        str = "\"}";
4880                        str += !(quoted & 1);
4881                        quoted >>= 1;
4882                        subtype = 0;
4883                        goto dostr;
4884#if BASH_PROCESS_SUBST
4885                case CTLBACKQ:
4886                        c = '$';
4887                        str = "(...)";
4888                        break;
4889                case CTLTOPROC:
4890                        c = '>';
4891                        str = "(...)";
4892                        break;
4893                case CTLFROMPROC:
4894                        c = '<';
4895                        str = "(...)";
4896                        break;
4897#else
4898                case CTLBACKQ:
4899                        str = "$(...)";
4900                        goto dostr;
4901#endif
4902#if ENABLE_FEATURE_SH_MATH
4903                case CTLARI:
4904                        str = "$((";
4905                        goto dostr;
4906                case CTLENDARI:
4907                        str = "))";
4908                        goto dostr;
4909#endif
4910                case CTLQUOTEMARK:
4911                        quoted ^= 1;
4912                        c = '"';
4913                        break;
4914                case '=':
4915                        if (subtype == 0)
4916                                break;
4917                        if ((subtype & VSTYPE) != VSNORMAL)
4918                                quoted <<= 1;
4919                        str = vstype[subtype & VSTYPE];
4920                        if (subtype & VSNUL)
4921                                c = ':';
4922                        else
4923                                goto checkstr;
4924                        break;
4925                case '\'':
4926                case '\\':
4927                case '"':
4928                case '$':
4929                        /* These can only happen inside quotes */
4930                        cc[0] = c;
4931                        str = cc;
4932//FIXME:
4933// $ true $$ &
4934// $ <cr>
4935// [1]+  Done    true ${\$}   <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4936                        c = '\\';
4937                        break;
4938                default:
4939                        break;
4940                }
4941                USTPUTC(c, nextc);
4942 checkstr:
4943                if (!str)
4944                        continue;
4945 dostr:
4946                while ((c = *str++) != '\0') {
4947                        USTPUTC(c, nextc);
4948                }
4949        } /* while *p++ not NUL */
4950
4951        if (quoted & 1) {
4952                USTPUTC('"', nextc);
4953        }
4954        *nextc = 0;
4955        cmdnextc = nextc;
4956}
4957
4958/* cmdtxt() and cmdlist() call each other */
4959static void cmdtxt(union node *n);
4960
4961static void
4962cmdlist(union node *np, int sep)
4963{
4964        for (; np; np = np->narg.next) {
4965                if (!sep)
4966                        cmdputs(" ");
4967                cmdtxt(np);
4968                if (sep && np->narg.next)
4969                        cmdputs(" ");
4970        }
4971}
4972
4973static void
4974cmdtxt(union node *n)
4975{
4976        union node *np;
4977        struct nodelist *lp;
4978        const char *p;
4979
4980        if (!n)
4981                return;
4982        switch (n->type) {
4983        default:
4984#if DEBUG
4985                abort();
4986#endif
4987        case NPIPE:
4988                lp = n->npipe.cmdlist;
4989                for (;;) {
4990                        cmdtxt(lp->n);
4991                        lp = lp->next;
4992                        if (!lp)
4993                                break;
4994                        cmdputs(" | ");
4995                }
4996                break;
4997        case NSEMI:
4998                p = "; ";
4999                goto binop;
5000        case NAND:
5001                p = " && ";
5002                goto binop;
5003        case NOR:
5004                p = " || ";
5005 binop:
5006                cmdtxt(n->nbinary.ch1);
5007                cmdputs(p);
5008                n = n->nbinary.ch2;
5009                goto donode;
5010        case NREDIR:
5011        case NBACKGND:
5012                n = n->nredir.n;
5013                goto donode;
5014        case NNOT:
5015                cmdputs("!");
5016                n = n->nnot.com;
5017 donode:
5018                cmdtxt(n);
5019                break;
5020        case NIF:
5021                cmdputs("if ");
5022                cmdtxt(n->nif.test);
5023                cmdputs("; then ");
5024                if (n->nif.elsepart) {
5025                        cmdtxt(n->nif.ifpart);
5026                        cmdputs("; else ");
5027                        n = n->nif.elsepart;
5028                } else {
5029                        n = n->nif.ifpart;
5030                }
5031                p = "; fi";
5032                goto dotail;
5033        case NSUBSHELL:
5034                cmdputs("(");
5035                n = n->nredir.n;
5036                p = ")";
5037                goto dotail;
5038        case NWHILE:
5039                p = "while ";
5040                goto until;
5041        case NUNTIL:
5042                p = "until ";
5043 until:
5044                cmdputs(p);
5045                cmdtxt(n->nbinary.ch1);
5046                n = n->nbinary.ch2;
5047                p = "; done";
5048 dodo:
5049                cmdputs("; do ");
5050 dotail:
5051                cmdtxt(n);
5052                goto dotail2;
5053        case NFOR:
5054                cmdputs("for ");
5055                cmdputs(n->nfor.var);
5056                cmdputs(" in ");
5057                cmdlist(n->nfor.args, 1);
5058                n = n->nfor.body;
5059                p = "; done";
5060                goto dodo;
5061        case NDEFUN:
5062                cmdputs(n->ndefun.text);
5063                p = "() { ... }";
5064                goto dotail2;
5065        case NCMD:
5066                cmdlist(n->ncmd.args, 1);
5067                cmdlist(n->ncmd.redirect, 0);
5068                break;
5069        case NARG:
5070                p = n->narg.text;
5071 dotail2:
5072                cmdputs(p);
5073                break;
5074        case NHERE:
5075        case NXHERE:
5076                p = "<<...";
5077                goto dotail2;
5078        case NCASE:
5079                cmdputs("case ");
5080                cmdputs(n->ncase.expr->narg.text);
5081                cmdputs(" in ");
5082                for (np = n->ncase.cases; np; np = np->nclist.next) {
5083                        cmdtxt(np->nclist.pattern);
5084                        cmdputs(") ");
5085                        cmdtxt(np->nclist.body);
5086                        cmdputs(";; ");
5087                }
5088                p = "esac";
5089                goto dotail2;
5090        case NTO:
5091                p = ">";
5092                goto redir;
5093        case NCLOBBER:
5094                p = ">|";
5095                goto redir;
5096        case NAPPEND:
5097                p = ">>";
5098                goto redir;
5099#if BASH_REDIR_OUTPUT
5100        case NTO2:
5101#endif
5102        case NTOFD:
5103                p = ">&";
5104                goto redir;
5105        case NFROM:
5106                p = "<";
5107                goto redir;
5108        case NFROMFD:
5109                p = "<&";
5110                goto redir;
5111        case NFROMTO:
5112                p = "<>";
5113 redir:
5114                cmdputs(utoa(n->nfile.fd));
5115                cmdputs(p);
5116                if (n->type == NTOFD || n->type == NFROMFD) {
5117                        if (n->ndup.dupfd >= 0)
5118                                cmdputs(utoa(n->ndup.dupfd));
5119                        else
5120                                cmdputs("-");
5121                        break;
5122                }
5123                n = n->nfile.fname;
5124                goto donode;
5125        }
5126}
5127
5128static char *
5129commandtext(union node *n)
5130{
5131        char *name;
5132
5133        STARTSTACKSTR(cmdnextc);
5134        cmdtxt(n);
5135        name = stackblock();
5136        TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
5137        return ckstrdup(name);
5138}
5139#endif /* JOBS */
5140
5141/*
5142 * Fork off a subshell.  If we are doing job control, give the subshell its
5143 * own process group.  Jp is a job structure that the job is to be added to.
5144 * N is the command that will be evaluated by the child.  Both jp and n may
5145 * be NULL.  The mode parameter can be one of the following:
5146 *      FORK_FG - Fork off a foreground process.
5147 *      FORK_BG - Fork off a background process.
5148 *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
5149 *                   process group even if job control is on.
5150 *
5151 * When job control is turned off, background processes have their standard
5152 * input redirected to /dev/null (except for the second and later processes
5153 * in a pipeline).
5154 *
5155 * Called with interrupts off.
5156 */
5157/*
5158 * Clear traps on a fork.
5159 */
5160static void
5161clear_traps(void)
5162{
5163        char **tp;
5164
5165        INT_OFF;
5166        for (tp = trap; tp < &trap[NSIG]; tp++) {
5167                if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
5168                        if (trap_ptr == trap)
5169                                free(*tp);
5170                        /* else: it "belongs" to trap_ptr vector, don't free */
5171                        *tp = NULL;
5172                        if ((tp - trap) != 0)
5173                                setsignal(tp - trap);
5174                }
5175        }
5176        may_have_traps = 0;
5177        INT_ON;
5178}
5179
5180/* Lives far away from here, needed for forkchild */
5181static void closescript(void);
5182
5183/* Called after fork(), in child */
5184/* jp and n are NULL when called by openhere() for heredoc support */
5185static NOINLINE void
5186forkchild(struct job *jp, union node *n, int mode)
5187{
5188        int oldlvl;
5189
5190        TRACE(("Child shell %d\n", getpid()));
5191        oldlvl = shlvl;
5192        shlvl++;
5193
5194        /* man bash: "Non-builtin commands run by bash have signal handlers
5195         * set to the values inherited by the shell from its parent".
5196         * Do we do it correctly? */
5197
5198        closescript();
5199
5200        if (mode == FORK_NOJOB          /* is it `xxx` ? */
5201         && n && n->type == NCMD        /* is it single cmd? */
5202        /* && n->ncmd.args->type == NARG - always true? */
5203         && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
5204         && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
5205        /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
5206        ) {
5207                TRACE(("Trap hack\n"));
5208                /* Awful hack for `trap` or $(trap).
5209                 *
5210                 * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
5211                 * contains an example where "trap" is executed in a subshell:
5212                 *
5213                 * save_traps=$(trap)
5214                 * ...
5215                 * eval "$save_traps"
5216                 *
5217                 * Standard does not say that "trap" in subshell shall print
5218                 * parent shell's traps. It only says that its output
5219                 * must have suitable form, but then, in the above example
5220                 * (which is not supposed to be normative), it implies that.
5221                 *
5222                 * bash (and probably other shell) does implement it
5223                 * (traps are reset to defaults, but "trap" still shows them),
5224                 * but as a result, "trap" logic is hopelessly messed up:
5225                 *
5226                 * # trap
5227                 * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
5228                 * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
5229                 * # true | trap   <--- trap is in subshell - no output (ditto)
5230                 * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
5231                 * trap -- 'echo Ho' SIGWINCH
5232                 * # echo `(trap)`         <--- in subshell in subshell - output
5233                 * trap -- 'echo Ho' SIGWINCH
5234                 * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
5235                 * trap -- 'echo Ho' SIGWINCH
5236                 *
5237                 * The rules when to forget and when to not forget traps
5238                 * get really complex and nonsensical.
5239                 *
5240                 * Our solution: ONLY bare $(trap) or `trap` is special.
5241                 */
5242                /* Save trap handler strings for trap builtin to print */
5243                trap_ptr = xmemdup(trap, sizeof(trap));
5244                /* Fall through into clearing traps */
5245        }
5246        clear_traps();
5247#if JOBS
5248        /* do job control only in root shell */
5249        doing_jobctl = 0;
5250        if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
5251                pid_t pgrp;
5252
5253                if (jp->nprocs == 0)
5254                        pgrp = getpid();
5255                else
5256                        pgrp = jp->ps[0].ps_pid;
5257                /* this can fail because we are doing it in the parent also */
5258                setpgid(0, pgrp);
5259                if (mode == FORK_FG)
5260                        xtcsetpgrp(ttyfd, pgrp);
5261                setsignal(SIGTSTP);
5262                setsignal(SIGTTOU);
5263        } else
5264#endif
5265        if (mode == FORK_BG) {
5266                /* man bash: "When job control is not in effect,
5267                 * asynchronous commands ignore SIGINT and SIGQUIT" */
5268                ignoresig(SIGINT);
5269                ignoresig(SIGQUIT);
5270                if (jp->nprocs == 0) {
5271                        close(0);
5272                        if (open(bb_dev_null, O_RDONLY) != 0)
5273                                ash_msg_and_raise_perror("can't open '%s'", bb_dev_null);
5274                }
5275        }
5276        if (oldlvl == 0) {
5277                if (iflag) { /* why if iflag only? */
5278                        setsignal(SIGINT);
5279                        setsignal(SIGTERM);
5280                }
5281                /* man bash:
5282                 * "In all cases, bash ignores SIGQUIT. Non-builtin
5283                 * commands run by bash have signal handlers
5284                 * set to the values inherited by the shell
5285                 * from its parent".
5286                 * Take care of the second rule: */
5287                setsignal(SIGQUIT);
5288        }
5289#if JOBS
5290        if (n && n->type == NCMD
5291         && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5292        ) {
5293                TRACE(("Job hack\n"));
5294                /* "jobs": we do not want to clear job list for it,
5295                 * instead we remove only _its_ own_ job from job list.
5296                 * This makes "jobs .... | cat" more useful.
5297                 */
5298                freejob(curjob);
5299                return;
5300        }
5301#endif
5302        for (jp = curjob; jp; jp = jp->prev_job)
5303                freejob(jp);
5304}
5305
5306/* Called after fork(), in parent */
5307#if !JOBS
5308#define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5309#endif
5310static void
5311forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5312{
5313        TRACE(("In parent shell: child = %d\n", pid));
5314        if (!jp) /* jp is NULL when called by openhere() for heredoc support */
5315                return;
5316#if JOBS
5317        if (mode != FORK_NOJOB && jp->jobctl) {
5318                int pgrp;
5319
5320                if (jp->nprocs == 0)
5321                        pgrp = pid;
5322                else
5323                        pgrp = jp->ps[0].ps_pid;
5324                /* This can fail because we are doing it in the child also */
5325                setpgid(pid, pgrp);
5326        }
5327#endif
5328        if (mode == FORK_BG) {
5329                backgndpid = pid;               /* set $! */
5330                set_curjob(jp, CUR_RUNNING);
5331        }
5332        if (jp) {
5333                struct procstat *ps = &jp->ps[jp->nprocs++];
5334                ps->ps_pid = pid;
5335                ps->ps_status = -1;
5336                ps->ps_cmd = nullstr;
5337#if JOBS
5338                if (doing_jobctl && n)
5339                        ps->ps_cmd = commandtext(n);
5340#endif
5341        }
5342}
5343
5344/* jp and n are NULL when called by openhere() for heredoc support */
5345static int
5346forkshell(struct job *jp, union node *n, int mode)
5347{
5348        int pid;
5349
5350        TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5351        pid = fork();
5352        if (pid < 0) {
5353                TRACE(("Fork failed, errno=%d", errno));
5354                if (jp)
5355                        freejob(jp);
5356                ash_msg_and_raise_perror("can't fork");
5357        }
5358        if (pid == 0) {
5359                CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5360                forkchild(jp, n, mode);
5361        } else {
5362                forkparent(jp, n, mode, pid);
5363        }
5364        return pid;
5365}
5366
5367/*
5368 * Wait for job to finish.
5369 *
5370 * Under job control we have the problem that while a child process
5371 * is running interrupts generated by the user are sent to the child
5372 * but not to the shell.  This means that an infinite loop started by
5373 * an interactive user may be hard to kill.  With job control turned off,
5374 * an interactive user may place an interactive program inside a loop.
5375 * If the interactive program catches interrupts, the user doesn't want
5376 * these interrupts to also abort the loop.  The approach we take here
5377 * is to have the shell ignore interrupt signals while waiting for a
5378 * foreground process to terminate, and then send itself an interrupt
5379 * signal if the child process was terminated by an interrupt signal.
5380 * Unfortunately, some programs want to do a bit of cleanup and then
5381 * exit on interrupt; unless these processes terminate themselves by
5382 * sending a signal to themselves (instead of calling exit) they will
5383 * confuse this approach.
5384 *
5385 * Called with interrupts off.
5386 */
5387static int
5388waitforjob(struct job *jp)
5389{
5390        int st;
5391
5392        TRACE(("waitforjob(%%%d) called\n", jp ? jobno(jp) : 0));
5393
5394        /* In non-interactive shells, we _can_ get
5395         * a keyboard signal here and be EINTRed, but we just loop
5396         * inside dowait(), waiting for command to complete.
5397         *
5398         * man bash:
5399         * "If bash is waiting for a command to complete and receives
5400         * a signal for which a trap has been set, the trap
5401         * will not be executed until the command completes."
5402         *
5403         * Reality is that even if trap is not set, bash
5404         * will not act on the signal until command completes.
5405         * Try this. sleep5intoff.c:
5406         * #include <signal.h>
5407         * #include <unistd.h>
5408         * int main() {
5409         *         sigset_t set;
5410         *         sigemptyset(&set);
5411         *         sigaddset(&set, SIGINT);
5412         *         sigaddset(&set, SIGQUIT);
5413         *         sigprocmask(SIG_BLOCK, &set, NULL);
5414         *         sleep(5);
5415         *         return 0;
5416         * }
5417         * $ bash -c './sleep5intoff; echo hi'
5418         * ^C^C^C^C <--- pressing ^C once a second
5419         * $ _
5420         * $ bash -c './sleep5intoff; echo hi'
5421         * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5422         * $ _
5423         */
5424        dowait(jp ? DOWAIT_BLOCK : DOWAIT_NONBLOCK, jp);
5425        if (!jp)
5426                return exitstatus;
5427
5428        st = getstatus(jp);
5429#if JOBS
5430        if (jp->jobctl) {
5431                xtcsetpgrp(ttyfd, rootpid);
5432                restore_tty_if_stopped_or_signaled(jp);
5433
5434                /*
5435                 * This is truly gross.
5436                 * If we're doing job control, then we did a TIOCSPGRP which
5437                 * caused us (the shell) to no longer be in the controlling
5438                 * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5439                 * intuit from the subprocess exit status whether a SIGINT
5440                 * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5441                 */
5442                if (jp->sigint) /* TODO: do the same with all signals */
5443                        raise(SIGINT); /* ... by raise(jp->sig) instead? */
5444        }
5445        if (jp->state == JOBDONE)
5446#endif
5447                freejob(jp);
5448        return st;
5449}
5450
5451/*
5452 * return 1 if there are stopped jobs, otherwise 0
5453 */
5454static int
5455stoppedjobs(void)
5456{
5457        struct job *jp;
5458        int retval;
5459
5460        retval = 0;
5461        if (job_warning)
5462                goto out;
5463        jp = curjob;
5464        if (jp && jp->state == JOBSTOPPED) {
5465                out2str("You have stopped jobs.\n");
5466                job_warning = 2;
5467                retval++;
5468        }
5469 out:
5470        return retval;
5471}
5472
5473
5474/*
5475 * Code for dealing with input/output redirection.
5476 */
5477
5478#undef EMPTY
5479#undef CLOSED
5480#define EMPTY -2                /* marks an unused slot in redirtab */
5481#define CLOSED -1               /* marks a slot of previously-closed fd */
5482
5483/*
5484 * Handle here documents.  Normally we fork off a process to write the
5485 * data to a pipe.  If the document is short, we can stuff the data in
5486 * the pipe without forking.
5487 */
5488/* openhere needs this forward reference */
5489static void expandhere(union node *arg);
5490static int
5491openhere(union node *redir)
5492{
5493        char *p;
5494        int pip[2];
5495        size_t len = 0;
5496
5497        if (pipe(pip) < 0)
5498                ash_msg_and_raise_perror("can't create pipe");
5499
5500        p = redir->nhere.doc->narg.text;
5501        if (redir->type == NXHERE) {
5502                expandhere(redir->nhere.doc);
5503                p = stackblock();
5504        }
5505
5506        len = strlen(p);
5507        if (len <= PIPE_BUF) {
5508                xwrite(pip[1], p, len);
5509                goto out;
5510        }
5511
5512        if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5513                /* child */
5514                close(pip[0]);
5515                ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5516                ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5517                ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5518                ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5519                signal(SIGPIPE, SIG_DFL);
5520                xwrite(pip[1], p, len);
5521                _exit(EXIT_SUCCESS);
5522        }
5523 out:
5524        close(pip[1]);
5525        return pip[0];
5526}
5527
5528static int
5529openredirect(union node *redir)
5530{
5531        struct stat sb;
5532        char *fname;
5533        int f;
5534
5535        switch (redir->nfile.type) {
5536/* Can't happen, our single caller does this itself */
5537//      case NTOFD:
5538//      case NFROMFD:
5539//              return -1;
5540        case NHERE:
5541        case NXHERE:
5542                return openhere(redir);
5543        }
5544
5545        /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5546         * allocated space. Do it only when we know it is safe.
5547         */
5548        fname = redir->nfile.expfname;
5549
5550        switch (redir->nfile.type) {
5551        default:
5552#if DEBUG
5553                abort();
5554#endif
5555        case NFROM:
5556                f = open(fname, O_RDONLY);
5557                if (f < 0)
5558                        goto eopen;
5559                break;
5560        case NFROMTO:
5561                f = open(fname, O_RDWR|O_CREAT, 0666);
5562                if (f < 0)
5563                        goto ecreate;
5564                break;
5565        case NTO:
5566#if BASH_REDIR_OUTPUT
5567        case NTO2:
5568#endif
5569                /* Take care of noclobber mode. */
5570                if (Cflag) {
5571                        if (stat(fname, &sb) < 0) {
5572                                f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5573                                if (f < 0)
5574                                        goto ecreate;
5575                        } else if (!S_ISREG(sb.st_mode)) {
5576                                f = open(fname, O_WRONLY, 0666);
5577                                if (f < 0)
5578                                        goto ecreate;
5579                                if (!fstat(f, &sb) && S_ISREG(sb.st_mode)) {
5580                                        close(f);
5581                                        errno = EEXIST;
5582                                        goto ecreate;
5583                                }
5584                        } else {
5585                                errno = EEXIST;
5586                                goto ecreate;
5587                        }
5588                        break;
5589                }
5590                /* FALLTHROUGH */
5591        case NCLOBBER:
5592                f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5593                if (f < 0)
5594                        goto ecreate;
5595                break;
5596        case NAPPEND:
5597                f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5598                if (f < 0)
5599                        goto ecreate;
5600                break;
5601        }
5602
5603        return f;
5604 ecreate:
5605        ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5606 eopen:
5607        ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5608}
5609
5610/*
5611 * Copy a file descriptor to be >= 10. Throws exception on error.
5612 */
5613static int
5614savefd(int from)
5615{
5616        int newfd;
5617        int err;
5618
5619        newfd = fcntl(from, F_DUPFD_CLOEXEC, 10);
5620        err = newfd < 0 ? errno : 0;
5621        if (err != EBADF) {
5622                if (err)
5623                        ash_msg_and_raise_perror("%d", from);
5624                close(from);
5625                if (F_DUPFD_CLOEXEC == F_DUPFD)
5626                        close_on_exec_on(newfd);
5627        }
5628
5629        return newfd;
5630}
5631static int
5632dup2_or_raise(int from, int to)
5633{
5634        int newfd;
5635
5636        newfd = (from != to) ? dup2(from, to) : to;
5637        if (newfd < 0) {
5638                /* Happens when source fd is not open: try "echo >&99" */
5639                ash_msg_and_raise_perror("%d", from);
5640        }
5641        return newfd;
5642}
5643static int
5644dup_CLOEXEC(int fd, int avoid_fd)
5645{
5646        int newfd;
5647 repeat:
5648        newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5649        if (newfd >= 0) {
5650                if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
5651                        close_on_exec_on(newfd);
5652        } else { /* newfd < 0 */
5653                if (errno == EBUSY)
5654                        goto repeat;
5655                if (errno == EINTR)
5656                        goto repeat;
5657        }
5658        return newfd;
5659}
5660static int
5661xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5662{
5663        int newfd;
5664 repeat:
5665        newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5666        if (newfd < 0) {
5667                if (errno == EBUSY)
5668                        goto repeat;
5669                if (errno == EINTR)
5670                        goto repeat;
5671                /* fd was not open? */
5672                if (errno == EBADF)
5673                        return fd;
5674                ash_msg_and_raise_perror("%d", newfd);
5675        }
5676        if (F_DUPFD_CLOEXEC == F_DUPFD)
5677                close_on_exec_on(newfd);
5678        close(fd);
5679        return newfd;
5680}
5681
5682/* Struct def and variable are moved down to the first usage site */
5683struct squirrel {
5684        int orig_fd;
5685        int moved_to;
5686};
5687struct redirtab {
5688        struct redirtab *next;
5689        int pair_count;
5690        struct squirrel two_fd[];
5691};
5692#define redirlist (G_var.redirlist)
5693
5694static void
5695add_squirrel_closed(struct redirtab *sq, int fd)
5696{
5697        int i;
5698
5699        if (!sq)
5700                return;
5701
5702        for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5703                /* If we collide with an already moved fd... */
5704                if (fd == sq->two_fd[i].orig_fd) {
5705                        /* Examples:
5706                         * "echo 3>FILE 3>&- 3>FILE"
5707                         * "echo 3>&- 3>FILE"
5708                         * No need for last redirect to insert
5709                         * another "need to close 3" indicator.
5710                         */
5711                        TRACE(("redirect_fd %d: already moved or closed\n", fd));
5712                        return;
5713                }
5714        }
5715        TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5716        sq->two_fd[i].orig_fd = fd;
5717        sq->two_fd[i].moved_to = CLOSED;
5718}
5719
5720static int
5721save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5722{
5723        int i, new_fd;
5724
5725        if (avoid_fd < 9) /* the important case here is that it can be -1 */
5726                avoid_fd = 9;
5727
5728#if JOBS
5729        if (fd == ttyfd) {
5730                /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5731                ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5732                TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5733                return 1; /* "we closed fd" */
5734        }
5735#endif
5736        /* Are we called from redirect(0)? E.g. redirect
5737         * in a forked child. No need to save fds,
5738         * we aren't going to use them anymore, ok to trash.
5739         */
5740        if (!sq)
5741                return 0;
5742
5743        /* If this one of script's fds? */
5744        if (fd != 0) {
5745                struct parsefile *pf = g_parsefile;
5746                while (pf) {
5747                        /* We skip fd == 0 case because of the following:
5748                         * $ ash  # running ash interactively
5749                         * $ . ./script.sh
5750                         * and in script.sh: "exec 9>&0".
5751                         * Even though top-level pf_fd _is_ 0,
5752                         * it's still ok to use it: "read" builtin uses it,
5753                         * why should we cripple "exec" builtin?
5754                         */
5755                        if (fd == pf->pf_fd) {
5756                                pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5757                                return 1; /* "we closed fd" */
5758                        }
5759                        pf = pf->prev;
5760                }
5761        }
5762
5763        /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5764
5765        /* First: do we collide with some already moved fds? */
5766        for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5767                /* If we collide with an already moved fd... */
5768                if (fd == sq->two_fd[i].moved_to) {
5769                        new_fd = dup_CLOEXEC(fd, avoid_fd);
5770                        sq->two_fd[i].moved_to = new_fd;
5771                        TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5772                        if (new_fd < 0) /* what? */
5773                                xfunc_die();
5774                        return 0; /* "we did not close fd" */
5775                }
5776                if (fd == sq->two_fd[i].orig_fd) {
5777                        /* Example: echo Hello >/dev/null 1>&2 */
5778                        TRACE(("redirect_fd %d: already moved\n", fd));
5779                        return 0; /* "we did not close fd" */
5780                }
5781        }
5782
5783        /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5784        new_fd = dup_CLOEXEC(fd, avoid_fd);
5785        TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5786        if (new_fd < 0) {
5787                if (errno != EBADF)
5788                        xfunc_die();
5789                /* new_fd = CLOSED; - already is -1 */
5790        }
5791        sq->two_fd[i].moved_to = new_fd;
5792        sq->two_fd[i].orig_fd = fd;
5793
5794        /* if we move stderr, let "set -x" code know */
5795        if (fd == preverrout_fd)
5796                preverrout_fd = new_fd;
5797
5798        return 0; /* "we did not close fd" */
5799}
5800
5801static int
5802internally_opened_fd(int fd, struct redirtab *sq)
5803{
5804        int i;
5805#if JOBS
5806        if (fd == ttyfd)
5807                return 1;
5808#endif
5809        /* If this one of script's fds? */
5810        if (fd != 0) {
5811                struct parsefile *pf = g_parsefile;
5812                while (pf) {
5813                        if (fd == pf->pf_fd)
5814                                return 1;
5815                        pf = pf->prev;
5816                }
5817        }
5818
5819        if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5820                if (fd == sq->two_fd[i].moved_to)
5821                        return 1;
5822        }
5823        return 0;
5824}
5825
5826/*
5827 * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5828 * old file descriptors are stashed away so that the redirection can be
5829 * undone by calling popredir.
5830 */
5831/* flags passed to redirect */
5832#define REDIR_PUSH    01        /* save previous values of file descriptors */
5833static void
5834redirect(union node *redir, int flags)
5835{
5836        struct redirtab *sv;
5837
5838        if (!redir)
5839                return;
5840
5841        sv = NULL;
5842        INT_OFF;
5843        if (flags & REDIR_PUSH)
5844                sv = redirlist;
5845        do {
5846                int fd;
5847                int newfd;
5848                int close_fd;
5849                int closed;
5850
5851                fd = redir->nfile.fd;
5852                if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5853                        //bb_error_msg("doing %d > %d", fd, newfd);
5854                        newfd = redir->ndup.dupfd;
5855                        close_fd = -1;
5856                } else {
5857                        newfd = openredirect(redir); /* always >= 0 */
5858                        if (fd == newfd) {
5859                                /* open() gave us precisely the fd we wanted.
5860                                 * This means that this fd was not busy
5861                                 * (not opened to anywhere).
5862                                 * Remember to close it on restore:
5863                                 */
5864                                add_squirrel_closed(sv, fd);
5865                                continue;
5866                        }
5867                        close_fd = newfd;
5868                }
5869
5870                if (fd == newfd)
5871                        continue;
5872
5873                /* if "N>FILE": move newfd to fd */
5874                /* if "N>&M": dup newfd to fd */
5875                /* if "N>&-": close fd (newfd is -1) */
5876
5877 IF_BASH_REDIR_OUTPUT(redirect_more:)
5878
5879                closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5880                if (newfd == -1) {
5881                        /* "N>&-" means "close me" */
5882                        if (!closed) {
5883                                /* ^^^ optimization: saving may already
5884                                 * have closed it. If not... */
5885                                close(fd);
5886                        }
5887                } else {
5888                        /* if newfd is a script fd or saved fd, simulate EBADF */
5889                        if (internally_opened_fd(newfd, sv)) {
5890                                errno = EBADF;
5891                                ash_msg_and_raise_perror("%d", newfd);
5892                        }
5893                        dup2_or_raise(newfd, fd);
5894                        if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5895                                close(close_fd);
5896#if BASH_REDIR_OUTPUT
5897                        if (redir->nfile.type == NTO2 && fd == 1) {
5898                                /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5899                                fd = 2;
5900                                newfd = 1;
5901                                close_fd = -1;
5902                                goto redirect_more;
5903                        }
5904#endif
5905                }
5906        } while ((redir = redir->nfile.next) != NULL);
5907        INT_ON;
5908
5909//dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5910#define REDIR_SAVEFD2 0
5911        // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5912        // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5913        // not only for calls with flags containing REDIR_SAVEFD2.
5914        // We do this unconditionally (see save_fd_on_redirect()).
5915        //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5916        //      preverrout_fd = copied_fd2;
5917}
5918
5919static int
5920redirectsafe(union node *redir, int flags)
5921{
5922        int err;
5923        volatile int saveint;
5924        struct jmploc *volatile savehandler = exception_handler;
5925        struct jmploc jmploc;
5926
5927        SAVE_INT(saveint);
5928        /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5929        err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5930        if (!err) {
5931                exception_handler = &jmploc;
5932                redirect(redir, flags);
5933        }
5934        exception_handler = savehandler;
5935        if (err && exception_type != EXERROR)
5936                longjmp(exception_handler->loc, 1);
5937        RESTORE_INT(saveint);
5938        return err;
5939}
5940
5941#if BASH_PROCESS_SUBST
5942static void
5943pushfd(int fd)
5944{
5945        struct redirtab *sv;
5946
5947        sv = ckzalloc(sizeof(*sv) + sizeof(sv->two_fd[0]));
5948        sv->pair_count = 1;
5949        sv->two_fd[0].orig_fd = fd;
5950        sv->two_fd[0].moved_to = CLOSED;
5951        sv->next = redirlist;
5952        redirlist = sv;
5953}
5954#endif
5955
5956static struct redirtab*
5957pushredir(union node *redir)
5958{
5959        struct redirtab *sv;
5960        int i;
5961
5962        if (!redir)
5963                return redirlist;
5964
5965        i = 0;
5966        do {
5967                i++;
5968#if BASH_REDIR_OUTPUT
5969                if (redir->nfile.type == NTO2)
5970                        i++;
5971#endif
5972                redir = redir->nfile.next;
5973        } while (redir);
5974
5975        sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5976        sv->pair_count = i;
5977        while (--i >= 0)
5978                sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5979        sv->next = redirlist;
5980        redirlist = sv;
5981        return sv->next;
5982}
5983
5984/*
5985 * Undo the effects of the last redirection.
5986 */
5987static void
5988popredir(int drop)
5989{
5990        struct redirtab *rp;
5991        int i;
5992
5993        if (redirlist == NULL)
5994                return;
5995        INT_OFF;
5996        rp = redirlist;
5997        for (i = 0; i < rp->pair_count; i++) {
5998                int fd = rp->two_fd[i].orig_fd;
5999                int copy = rp->two_fd[i].moved_to;
6000                if (copy == CLOSED) {
6001                        if (!drop)
6002                                close(fd);
6003                        continue;
6004                }
6005                if (copy != EMPTY) {
6006                        if (!drop) {
6007                                /*close(fd);*/
6008                                dup2_or_raise(copy, fd);
6009                        }
6010                        close(copy);
6011                }
6012        }
6013        redirlist = rp->next;
6014        free(rp);
6015        INT_ON;
6016}
6017
6018static void
6019unwindredir(struct redirtab *stop)
6020{
6021        while (redirlist != stop)
6022                popredir(/*drop:*/ 0);
6023}
6024
6025
6026/* ============ Routines to expand arguments to commands
6027 *
6028 * We have to deal with backquotes, shell variables, and file metacharacters.
6029 */
6030
6031#if ENABLE_FEATURE_SH_MATH
6032static arith_t
6033ash_arith(const char *s)
6034{
6035        arith_state_t math_state;
6036        arith_t result;
6037
6038        math_state.lookupvar = lookupvar;
6039        math_state.setvar    = setvar0;
6040        //math_state.endofname = endofname;
6041
6042        INT_OFF;
6043        result = arith(&math_state, s);
6044        if (math_state.errmsg)
6045                ash_msg_and_raise_error(math_state.errmsg);
6046        INT_ON;
6047
6048        return result;
6049}
6050#endif
6051#if BASH_SUBSTR
6052# if ENABLE_FEATURE_SH_MATH
6053static int substr_atoi(const char *s)
6054{
6055        arith_t t = ash_arith(s);
6056        if (sizeof(t) > sizeof(int)) {
6057                /* clamp very large or very large negative nums for ${v:N:M}:
6058                 * else "${v:0:0x100000001}" would work as "${v:0:1}"
6059                 */
6060                if (t > INT_MAX)
6061                        t = INT_MAX;
6062                if (t < INT_MIN)
6063                        t = INT_MIN;
6064        }
6065        return t;
6066}
6067# else
6068#  define substr_atoi(s) number(s)
6069# endif
6070#endif
6071
6072/*
6073 * expandarg flags
6074 */
6075#define EXP_FULL        0x1     /* perform word splitting & file globbing */
6076#define EXP_TILDE       0x2     /* do normal tilde expansion */
6077#define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
6078#define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
6079/* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
6080 * POSIX says for this case:
6081 *  Pathname expansion shall not be performed on the word by a
6082 *  non-interactive shell; an interactive shell may perform it, but shall
6083 *  do so only when the expansion would result in one word.
6084 * Currently, our code complies to the above rule by never globbing
6085 * redirection filenames.
6086 * Bash performs globbing, unless it is non-interactive and in POSIX mode.
6087 * (this means that on a typical Linux distro, bash almost always
6088 * performs globbing, and thus diverges from what we do).
6089 */
6090#define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
6091#define EXP_VARTILDE2   0x20    /* expand tildes after colons only */
6092#define EXP_WORD        0x40    /* expand word in parameter expansion */
6093#define EXP_QUOTED      0x100   /* expand word in double quotes */
6094#define EXP_KEEPNUL     0x200   /* do not skip NUL characters */
6095#define EXP_DISCARD     0x400   /* discard result of expansion */
6096
6097/*
6098 * rmescape() flags
6099 */
6100#define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
6101#define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
6102#define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
6103#define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
6104
6105/* Add CTLESC when necessary. */
6106#define QUOTES_ESC     (EXP_FULL | EXP_CASE)
6107
6108/*
6109 * Structure specifying which parts of the string should be searched
6110 * for IFS characters.
6111 */
6112struct ifsregion {
6113        struct ifsregion *next; /* next region in list */
6114        int begoff;             /* offset of start of region */
6115        int endoff;             /* offset of end of region */
6116        int nulonly;            /* search for nul bytes only */
6117};
6118
6119struct arglist {
6120        struct strlist *list;
6121        struct strlist **lastp;
6122};
6123
6124/* output of current string */
6125static char *expdest;
6126/* list of back quote expressions */
6127static struct nodelist *argbackq;
6128/* first struct in list of ifs regions */
6129static struct ifsregion ifsfirst;
6130/* last struct in list */
6131static struct ifsregion *ifslastp;
6132/* holds expanded arg list */
6133static struct arglist exparg;
6134
6135/*
6136 * Break the argument string into pieces based upon IFS and add the
6137 * strings to the argument list.  The regions of the string to be
6138 * searched for IFS characters have been stored by recordregion.
6139 */
6140static void
6141ifsbreakup(char *string, struct arglist *arglist)
6142{
6143        struct ifsregion *ifsp;
6144        struct strlist *sp;
6145        char *start;
6146        char *p;
6147        char *q;
6148        const char *ifs, *realifs;
6149        int ifsspc;
6150        int nulonly;
6151
6152        start = string;
6153        if (ifslastp != NULL) {
6154                ifsspc = 0;
6155                nulonly = 0;
6156                realifs = ifsset() ? ifsval() : defifs;
6157                ifsp = &ifsfirst;
6158                do {
6159                        int afternul;
6160
6161                        p = string + ifsp->begoff;
6162                        afternul = nulonly;
6163                        nulonly = ifsp->nulonly;
6164                        ifs = nulonly ? nullstr : realifs;
6165                        ifsspc = 0;
6166                        while (p < string + ifsp->endoff) {
6167                                q = p;
6168                                if ((unsigned char)*p == CTLESC)
6169                                        p++;
6170                                if (!strchr(ifs, *p)) {
6171                                        p++;
6172                                        continue;
6173                                }
6174                                if (!(afternul || nulonly))
6175                                        ifsspc = (strchr(defifs, *p) != NULL);
6176                                /* Ignore IFS whitespace at start */
6177                                if (q == start && ifsspc) {
6178                                        p++;
6179                                        start = p;
6180                                        continue;
6181                                }
6182                                *q = '\0';
6183                                sp = stzalloc(sizeof(*sp));
6184                                sp->text = start;
6185                                *arglist->lastp = sp;
6186                                arglist->lastp = &sp->next;
6187                                p++;
6188                                if (!nulonly) {
6189                                        for (;;) {
6190                                                if (p >= string + ifsp->endoff) {
6191                                                        break;
6192                                                }
6193                                                q = p;
6194                                                if ((unsigned char)*p == CTLESC)
6195                                                        p++;
6196                                                if (strchr(ifs, *p) == NULL) {
6197                                                        p = q;
6198                                                        break;
6199                                                }
6200                                                if (strchr(defifs, *p) == NULL) {
6201                                                        if (ifsspc) {
6202                                                                p++;
6203                                                                ifsspc = 0;
6204                                                        } else {
6205                                                                p = q;
6206                                                                break;
6207                                                        }
6208                                                } else
6209                                                        p++;
6210                                        }
6211                                }
6212                                start = p;
6213                        } /* while */
6214                        ifsp = ifsp->next;
6215                } while (ifsp != NULL);
6216                if (nulonly)
6217                        goto add;
6218        }
6219
6220        if (!*start)
6221                return;
6222
6223 add:
6224        sp = stzalloc(sizeof(*sp));
6225        sp->text = start;
6226        *arglist->lastp = sp;
6227        arglist->lastp = &sp->next;
6228}
6229
6230static void
6231ifsfree(void)
6232{
6233        struct ifsregion *p = ifsfirst.next;
6234
6235        if (!p)
6236                goto out;
6237
6238        INT_OFF;
6239        do {
6240                struct ifsregion *ifsp;
6241                ifsp = p->next;
6242                free(p);
6243                p = ifsp;
6244        } while (p);
6245        ifsfirst.next = NULL;
6246        INT_ON;
6247 out:
6248        ifslastp = NULL;
6249}
6250
6251static size_t
6252esclen(const char *start, const char *p)
6253{
6254        size_t esc = 0;
6255
6256        while (p > start && (unsigned char)*--p == CTLESC) {
6257                esc++;
6258        }
6259        return esc;
6260}
6261
6262/*
6263 * Remove any CTLESC characters from a string.
6264 */
6265#if !BASH_PATTERN_SUBST
6266#define rmescapes(str, flag, slash_position) \
6267        rmescapes(str, flag)
6268#endif
6269static char *
6270rmescapes(char *str, int flag, int *slash_position)
6271{
6272        static const char qchars[] ALIGN1 = {
6273                IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
6274
6275        char *p, *q, *r;
6276        unsigned protect_against_glob;
6277        unsigned globbing;
6278
6279        p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash_position));
6280        if (!p)
6281                return str;
6282
6283        q = p;
6284        r = str;
6285        if (flag & RMESCAPE_ALLOC) {
6286                size_t len = p - str;
6287                size_t fulllen = len + strlen(p) + 1;
6288
6289                if (flag & RMESCAPE_GROW) {
6290                        int strloc = str - (char *)stackblock();
6291                        r = makestrspace(fulllen, expdest);
6292                        /* p and str may be invalidated by makestrspace */
6293                        str = (char *)stackblock() + strloc;
6294                        p = str + len;
6295                } else if (flag & RMESCAPE_HEAP) {
6296                        r = ckmalloc(fulllen);
6297                } else {
6298                        r = stalloc(fulllen);
6299                }
6300                q = r;
6301                if (len > 0) {
6302                        q = (char *)mempcpy(q, str, len);
6303                }
6304        }
6305
6306        globbing = flag & RMESCAPE_GLOB;
6307        protect_against_glob = globbing;
6308        while (*p) {
6309                if ((unsigned char)*p == CTLQUOTEMARK) {
6310// Note: protect_against_glob only affect whether
6311// CTLESC,<ch> gets converted to <ch> or to \<ch>
6312                        p++;
6313                        protect_against_glob = globbing;
6314                        continue;
6315                }
6316                if (*p == '\\') {
6317                        /* naked back slash */
6318                        protect_against_glob = 0;
6319                        goto copy;
6320                }
6321                if ((unsigned char)*p == CTLESC) {
6322                        p++;
6323#if DEBUG
6324                        if (*p == '\0')
6325                                ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6326#endif
6327                        if (protect_against_glob) {
6328                                /*
6329                                 * We used to trust glob() and fnmatch() to eat
6330                                 * superfluous escapes (\z where z has no
6331                                 * special meaning anyway). But this causes
6332                                 * bugs such as string of one greek letter rho
6333                                 * (unicode-encoded as two bytes "cf,81")
6334                                 * getting encoded as "cf,CTLESC,81"
6335                                 * and here, converted to "cf,\,81" -
6336                                 * which does not go well with some flavors
6337                                 * of fnmatch() in unicode locales
6338                                 * (for example, glibc <= 2.22).
6339                                 *
6340                                 * Lets add "\" only on the chars which need it.
6341                                 * Testcases for less obvious chars are shown.
6342                                 */
6343                                if (*p == '*'
6344                                 || *p == '?'
6345                                 || *p == '['
6346                                 || *p == '\\' /* case '\' in \\    ) echo ok;; *) echo WRONG;; esac */
6347                                 || *p == ']'  /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6348                                 || *p == '-'  /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6349                                 || *p == '!'  /* case '!' in [\!]  ) echo ok;; *) echo WRONG;; esac */
6350                                /* Some libc support [^negate], that's why "^" also needs love */
6351                                 || *p == '^'  /* case '^' in [\^]  ) echo ok;; *) echo WRONG;; esac */
6352                                ) {
6353                                        *q++ = '\\';
6354                                }
6355                        }
6356                }
6357#if BASH_PATTERN_SUBST
6358                else if (slash_position && p == str + *slash_position) {
6359                        /* stop handling globbing */
6360                        globbing = 0;
6361                        *slash_position = q - r;
6362                        slash_position = NULL;
6363                }
6364#endif
6365                protect_against_glob = globbing;
6366 copy:
6367                *q++ = *p++;
6368        }
6369        *q = '\0';
6370        if (flag & RMESCAPE_GROW) {
6371                expdest = r;
6372                STADJUST(q - r + 1, expdest);
6373        }
6374        return r;
6375}
6376#define pmatch(a, b) !fnmatch((a), (b), 0)
6377
6378/*
6379 * Prepare a pattern for a expmeta (internal glob(3)) call.
6380 *
6381 * Returns an stalloced string.
6382 */
6383static char *
6384preglob(const char *pattern, int flag)
6385{
6386        return rmescapes((char *)pattern, flag | RMESCAPE_GLOB, NULL);
6387}
6388
6389/*
6390 * Put a string on the stack.
6391 */
6392static size_t
6393memtodest(const char *p, size_t len, int flags)
6394{
6395        int syntax = flags & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6396        char *q;
6397        char *s;
6398
6399        if (!len)
6400                return 0;
6401
6402        q = makestrspace(len * 2, expdest);
6403        s = q;
6404
6405        do {
6406                unsigned char c = *p++;
6407                if (c) {
6408                        if (flags & QUOTES_ESC) {
6409                                int n = SIT(c, syntax);
6410                                if (n == CCTL
6411                                 || ((flags & EXP_QUOTED) && n == CBACK)
6412                                ) {
6413                                        USTPUTC(CTLESC, q);
6414                                }
6415                        }
6416                } else if (!(flags & EXP_KEEPNUL))
6417                        continue;
6418                USTPUTC(c, q);
6419        } while (--len);
6420
6421        expdest = q;
6422        return q - s;
6423}
6424
6425static size_t
6426strtodest(const char *p, int flags)
6427{
6428        size_t len = strlen(p);
6429        memtodest(p, len, flags);
6430        return len;
6431}
6432
6433/*
6434 * Our own itoa().
6435 * cvtnum() is used even if math support is off (to prepare $? values and such).
6436 */
6437static int
6438cvtnum(arith_t num, int flags)
6439{
6440        /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
6441        /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
6442        int len = (sizeof(arith_t) >= 4) ? sizeof(arith_t) * 3 : sizeof(arith_t) * 3 + 2;
6443        char buf[len];
6444
6445        len = fmtstr(buf, len, ARITH_FMT, num);
6446        return memtodest(buf, len, flags);
6447}
6448
6449/*
6450 * Record the fact that we have to scan this region of the
6451 * string for IFS characters.
6452 */
6453static void
6454recordregion(int start, int end, int nulonly)
6455{
6456        struct ifsregion *ifsp;
6457
6458        if (ifslastp == NULL) {
6459                ifsp = &ifsfirst;
6460        } else {
6461                INT_OFF;
6462                ifsp = ckzalloc(sizeof(*ifsp));
6463                /*ifsp->next = NULL; - ckzalloc did it */
6464                ifslastp->next = ifsp;
6465                INT_ON;
6466        }
6467        ifslastp = ifsp;
6468        ifslastp->begoff = start;
6469        ifslastp->endoff = end;
6470        ifslastp->nulonly = nulonly;
6471}
6472
6473static void
6474removerecordregions(int endoff)
6475{
6476        if (ifslastp == NULL)
6477                return;
6478
6479        if (ifsfirst.endoff > endoff) {
6480                while (ifsfirst.next) {
6481                        struct ifsregion *ifsp;
6482                        INT_OFF;
6483                        ifsp = ifsfirst.next->next;
6484                        free(ifsfirst.next);
6485                        ifsfirst.next = ifsp;
6486                        INT_ON;
6487                }
6488                if (ifsfirst.begoff > endoff) {
6489                        ifslastp = NULL;
6490                } else {
6491                        ifslastp = &ifsfirst;
6492                        ifsfirst.endoff = endoff;
6493                }
6494                return;
6495        }
6496
6497        ifslastp = &ifsfirst;
6498        while (ifslastp->next && ifslastp->next->begoff < endoff)
6499                ifslastp = ifslastp->next;
6500        while (ifslastp->next) {
6501                struct ifsregion *ifsp;
6502                INT_OFF;
6503                ifsp = ifslastp->next->next;
6504                free(ifslastp->next);
6505                ifslastp->next = ifsp;
6506                INT_ON;
6507        }
6508        if (ifslastp->endoff > endoff)
6509                ifslastp->endoff = endoff;
6510}
6511
6512static char *
6513exptilde(char *startp, int flag)
6514{
6515        unsigned char c;
6516        char *name;
6517        struct passwd *pw;
6518        const char *home;
6519        char *p;
6520
6521        p = startp;
6522        name = p + 1;
6523
6524        while ((c = *++p) != '\0') {
6525                switch (c) {
6526                case CTLESC:
6527                        return startp;
6528                case CTLQUOTEMARK:
6529                        return startp;
6530                case ':':
6531                        if (flag & EXP_VARTILDE)
6532                                goto done;
6533                        break;
6534                case '/':
6535                case CTLENDVAR:
6536                        goto done;
6537                }
6538        }
6539 done:
6540        if (flag & EXP_DISCARD)
6541                goto out;
6542        *p = '\0';
6543        if (*name == '\0') {
6544                home = lookupvar("HOME");
6545        } else {
6546                pw = getpwnam(name);
6547                if (pw == NULL)
6548                        goto lose;
6549                home = pw->pw_dir;
6550        }
6551        *p = c;
6552        if (!home)
6553                goto lose;
6554        strtodest(home, flag | EXP_QUOTED);
6555 out:
6556        return p;
6557 lose:
6558        return startp;
6559}
6560
6561/*
6562 * Execute a command inside back quotes.  If it's a builtin command, we
6563 * want to save its output in a block obtained from malloc.  Otherwise
6564 * we fork off a subprocess and get the output of the command via a pipe.
6565 * Should be called with interrupts off.
6566 */
6567struct backcmd {                /* result of evalbackcmd */
6568        int fd;                 /* file descriptor to read from */
6569        int nleft;              /* number of chars in buffer */
6570        char *buf;              /* buffer */
6571        struct job *jp;         /* job structure for command */
6572};
6573
6574/* These forward decls are needed to use "eval" code for backticks handling: */
6575/* flags in argument to evaltree */
6576#define EV_EXIT    01           /* exit after evaluating tree */
6577#define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6578static int evaltree(union node *, int);
6579
6580/* An evaltree() which is known to never return.
6581 * Used to use an alias:
6582 * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6583 * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6584 */
6585static ALWAYS_INLINE NORETURN void
6586evaltreenr(union node *n, int flags)
6587{
6588        evaltree(n, flags);
6589        bb_unreachable(abort());
6590        /* NOTREACHED */
6591}
6592
6593static void FAST_FUNC
6594evalbackcmd(union node *n, struct backcmd *result
6595                                IF_BASH_PROCESS_SUBST(, int ctl))
6596{
6597        int pip[2];
6598        struct job *jp;
6599#if BASH_PROCESS_SUBST
6600        /* determine end of pipe used by parent (ip) and child (ic) */
6601        const int ip = (ctl == CTLTOPROC);
6602        const int ic = !(ctl == CTLTOPROC);
6603#else
6604        const int ctl = CTLBACKQ;
6605        const int ip = 0;
6606        const int ic = 1;
6607#endif
6608
6609        result->fd = -1;
6610        result->buf = NULL;
6611        result->nleft = 0;
6612        result->jp = NULL;
6613        if (n == NULL) {
6614                goto out;
6615        }
6616
6617        if (pipe(pip) < 0)
6618                ash_msg_and_raise_perror("can't create pipe");
6619        /* process substitution uses NULL job/node, like openhere() */
6620        jp = (ctl == CTLBACKQ) ? makejob(/*n,*/ 1) : NULL;
6621        if (forkshell(jp, (ctl == CTLBACKQ) ? n : NULL, FORK_NOJOB) == 0) {
6622                /* child */
6623                FORCE_INT_ON;
6624                close(pip[ip]);
6625                /* ic is index of child end of pipe *and* fd to connect it to */
6626                if (pip[ic] != ic) {
6627                        /*close(ic);*/
6628                        dup2_or_raise(pip[ic], ic);
6629                        close(pip[ic]);
6630                }
6631/* TODO: eflag clearing makes the following not abort:
6632 *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6633 * which is what bash does (unless it is in POSIX mode).
6634 * dash deleted "eflag = 0" line in the commit
6635 *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6636 *  [EVAL] Don't clear eflag in evalbackcmd
6637 * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6638 */
6639                eflag = 0;
6640                ifsfree();
6641                evaltreenr(n, EV_EXIT);
6642                /* NOTREACHED */
6643        }
6644        /* parent */
6645#if BASH_PROCESS_SUBST
6646        if (ctl != CTLBACKQ) {
6647                int fd = fcntl(pip[ip], F_DUPFD, 64);
6648                if (fd > 0) {
6649                        close(pip[ip]);
6650                        pip[ip] = fd;
6651                }
6652                pushfd(pip[ip]);
6653        }
6654#endif
6655        close(pip[ic]);
6656        result->fd = pip[ip];
6657        result->jp = jp;
6658
6659 out:
6660        TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6661                result->fd, result->buf, result->nleft, result->jp));
6662}
6663
6664/*
6665 * Expand stuff in backwards quotes.
6666 */
6667static void
6668expbackq(union node *cmd, int flag IF_BASH_PROCESS_SUBST(, int ctl))
6669{
6670#if !BASH_PROCESS_SUBST
6671        const int ctl = CTLBACKQ;
6672#endif
6673        struct backcmd in;
6674        int i;
6675        char buf[128];
6676        char *p;
6677        char *dest;
6678        int startloc;
6679        struct stackmark smark;
6680
6681        if (flag & EXP_DISCARD)
6682                goto out;
6683
6684        INT_OFF;
6685        startloc = expdest - (char *)stackblock();
6686        pushstackmark(&smark, startloc);
6687        evalbackcmd(cmd, &in IF_BASH_PROCESS_SUBST(, ctl));
6688        popstackmark(&smark);
6689
6690        if (ctl != CTLBACKQ) {
6691                sprintf(buf, DEV_FD_PREFIX"%d", in.fd);
6692                strtodest(buf, BASESYNTAX);
6693                goto done;
6694        }
6695
6696        p = in.buf;
6697        i = in.nleft;
6698        if (i == 0)
6699                goto read;
6700        for (;;) {
6701                memtodest(p, i, flag);
6702 read:
6703                if (in.fd < 0)
6704                        break;
6705                i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6706                TRACE(("expbackq: read returns %d\n", i));
6707                if (i <= 0)
6708                        break;
6709                p = buf;
6710        }
6711
6712        free(in.buf);
6713        if (in.fd >= 0) {
6714                close(in.fd);
6715                back_exitstatus = waitforjob(in.jp);
6716        }
6717 done:
6718        INT_ON;
6719
6720        /* Eat all trailing newlines */
6721        dest = expdest;
6722        for (; dest > ((char *)stackblock() + startloc) && dest[-1] == '\n';)
6723                STUNPUTC(dest);
6724        expdest = dest;
6725
6726        if (!(flag & EXP_QUOTED))
6727                recordregion(startloc, dest - (char *)stackblock(), 0);
6728        TRACE(("evalbackq: size:%d:'%.*s'\n",
6729                (int)((dest - (char *)stackblock()) - startloc),
6730                (int)((dest - (char *)stackblock()) - startloc),
6731                stackblock() + startloc));
6732
6733 out:
6734        argbackq = argbackq->next;
6735}
6736
6737/* expari needs it */
6738static char *argstr(char *p, int flag);
6739
6740#if ENABLE_FEATURE_SH_MATH
6741/*
6742 * Expand arithmetic expression.  Backup to start of expression,
6743 * evaluate, place result in (backed up) result, adjust string position.
6744 */
6745static char *
6746expari(char *start, int flag)
6747{
6748        struct stackmark sm;
6749        int begoff;
6750        int endoff;
6751        int len;
6752        arith_t result;
6753        char *p;
6754
6755        p = stackblock();
6756        begoff = expdest - p;
6757        p = argstr(start, flag & EXP_DISCARD);
6758
6759        if (flag & EXP_DISCARD)
6760                goto out;
6761
6762        start = stackblock();
6763        endoff = expdest - start;
6764        start += begoff;
6765        STADJUST(start - expdest, expdest);
6766
6767        removerecordregions(begoff);
6768
6769        if (flag & QUOTES_ESC)
6770                rmescapes(start, 0, NULL);
6771
6772        pushstackmark(&sm, endoff);
6773        result = ash_arith(start);
6774        popstackmark(&sm);
6775
6776        len = cvtnum(result, flag);
6777
6778        if (!(flag & EXP_QUOTED))
6779                recordregion(begoff, begoff + len, 0);
6780
6781 out:
6782        return p;
6783}
6784#endif
6785
6786/* argstr needs it */
6787static char *evalvar(char *p, int flags);
6788
6789/*
6790 * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6791 * characters to allow for further processing.  Otherwise treat
6792 * $@ like $* since no splitting will be performed.
6793 */
6794static char *
6795argstr(char *p, int flag)
6796{
6797        static const char spclchars[] ALIGN1 = {
6798                '=',
6799                ':',
6800                CTLQUOTEMARK,
6801                CTLENDVAR,
6802                CTLESC,
6803                CTLVAR,
6804                CTLBACKQ,
6805#if BASH_PROCESS_SUBST
6806                CTLTOPROC,
6807                CTLFROMPROC,
6808#endif
6809#if ENABLE_FEATURE_SH_MATH
6810                CTLARI,
6811                CTLENDARI,
6812#endif
6813                '\0'
6814        };
6815        const char *reject = spclchars;
6816        int breakall = (flag & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6817        int inquotes;
6818        size_t length;
6819        int startloc;
6820
6821        reject += !!(flag & EXP_VARTILDE2);
6822        reject += flag & EXP_VARTILDE ? 0 : 2;
6823        inquotes = 0;
6824        length = 0;
6825        if (flag & EXP_TILDE) {
6826                flag &= ~EXP_TILDE;
6827 tilde:
6828                if (*p == '~')
6829                        p = exptilde(p, flag);
6830        }
6831 start:
6832        startloc = expdest - (char *)stackblock();
6833        for (;;) {
6834                int end;
6835                unsigned char c;
6836
6837                length += strcspn(p + length, reject);
6838                end = 0;
6839                c = p[length];
6840                if (!(c & 0x80)
6841                 IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6842                 || c == CTLENDVAR
6843                ) {
6844                        /*
6845                         * c == '=' || c == ':' || c == '\0' ||
6846                         * c == CTLENDARI || c == CTLENDVAR
6847                         */
6848                        length++;
6849                        /* c == '\0' || c == CTLENDARI || c == CTLENDVAR */
6850                        end = !!((c - 1) & 0x80);
6851                }
6852                if (length > 0 && !(flag & EXP_DISCARD)) {
6853                        int newloc;
6854                        char *q;
6855
6856                        q = stnputs(p, length, expdest);
6857                        q[-1] &= end - 1;
6858                        expdest = q - (flag & EXP_WORD ? end : 0);
6859                        newloc = q - (char *)stackblock() - end;
6860                        if (breakall && !inquotes && newloc > startloc) {
6861                                recordregion(startloc, newloc, 0);
6862                        }
6863                        startloc = newloc;
6864                }
6865                p += length + 1;
6866                length = 0;
6867
6868                if (end)
6869                        break;
6870
6871                switch (c) {
6872                case '=':
6873                        flag |= EXP_VARTILDE2;
6874                        reject++;
6875                        /* fall through */
6876                case ':':
6877                        /*
6878                         * sort of a hack - expand tildes in variable
6879                         * assignments (after the first '=' and after ':'s).
6880                         */
6881                        if (*--p == '~') {
6882                                goto tilde;
6883                        }
6884                        continue;
6885                case CTLQUOTEMARK:
6886                        /* "$@" syntax adherence hack */
6887                        if (!inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6888                                p = evalvar(p + 1, flag | EXP_QUOTED) + 1;
6889                                goto start;
6890                        }
6891                        inquotes ^= EXP_QUOTED;
6892 addquote:
6893                        if (flag & QUOTES_ESC) {
6894                                p--;
6895                                length++;
6896                                startloc++;
6897                        }
6898                        break;
6899                case CTLESC:
6900                        startloc++;
6901                        length++;
6902                        goto addquote;
6903                case CTLVAR:
6904                        TRACE(("argstr: evalvar('%s')\n", p));
6905                        p = evalvar(p, flag | inquotes);
6906                        TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6907                        goto start;
6908#if BASH_PROCESS_SUBST
6909                case CTLTOPROC:
6910                case CTLFROMPROC:
6911#endif
6912                case CTLBACKQ:
6913                        expbackq(argbackq->n, flag | inquotes IF_BASH_PROCESS_SUBST(, c));
6914                        goto start;
6915#if ENABLE_FEATURE_SH_MATH
6916                case CTLARI:
6917                        p = expari(p, flag | inquotes);
6918                        goto start;
6919#endif
6920                }
6921        }
6922        return p - 1;
6923}
6924
6925static char *
6926scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6927                char *pattern, int quotes, int zero)
6928{
6929        char *loc, *loc2;
6930        char c;
6931
6932        loc = startp;
6933        loc2 = rmesc;
6934        do {
6935                int match;
6936                const char *s = loc2;
6937
6938                c = *loc2;
6939                if (zero) {
6940                        *loc2 = '\0';
6941                        s = rmesc;
6942                }
6943                match = pmatch(pattern, s);
6944
6945                *loc2 = c;
6946                if (match)
6947                        return loc;
6948                if (quotes && (unsigned char)*loc == CTLESC)
6949                        loc++;
6950                loc++;
6951                loc2++;
6952        } while (c);
6953        return NULL;
6954}
6955
6956static char *
6957scanright(char *startp, char *rmesc, char *rmescend,
6958                char *pattern, int quotes, int match_at_start)
6959{
6960#if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6961        int try2optimize = match_at_start;
6962#endif
6963        int esc = 0;
6964        char *loc;
6965        char *loc2;
6966
6967        /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6968         * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6969         * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6970         * Logic:
6971         * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6972         * and on each iteration they go back two/one char until they reach the beginning.
6973         * We try to match "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6974         * If one of these matches, return pointer past last matched char in startp.
6975         */
6976        /* TODO: document in what other circumstances we are called. */
6977
6978        for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6979                int match;
6980                char c = *loc2;
6981                const char *s = loc2;
6982                if (match_at_start) {
6983                        *loc2 = '\0';
6984                        s = rmesc;
6985                }
6986                match = pmatch(pattern, s);
6987                //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6988                *loc2 = c;
6989                if (match)
6990                        return loc;
6991#if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6992                if (try2optimize) {
6993                        /* Maybe we can optimize this:
6994                         * if pattern ends with unescaped *, we can avoid checking
6995                         * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6996                         * it won't match truncated "raw_value_of_" strings too.
6997                         */
6998                        unsigned plen = strlen(pattern);
6999                        /* Does it end with "*"? */
7000                        if (plen != 0 && pattern[--plen] == '*') {
7001                                /* "xxxx*" is not escaped */
7002                                /* "xxx\*" is escaped */
7003                                /* "xx\\*" is not escaped */
7004                                /* "x\\\*" is escaped */
7005                                int slashes = 0;
7006                                while (plen != 0 && pattern[--plen] == '\\')
7007                                        slashes++;
7008                                if (!(slashes & 1))
7009                                        break; /* ends with unescaped "*" */
7010                        }
7011                        try2optimize = 0;
7012                }
7013#endif
7014                loc--;
7015                if (quotes) {
7016                        if (--esc < 0) {
7017                                esc = esclen(startp, loc);
7018                        }
7019                        if (esc % 2) {
7020                                esc--;
7021                                loc--;
7022                        }
7023                }
7024        }
7025        return NULL;
7026}
7027
7028static void varunset(const char *, const char *, const char *, int) NORETURN;
7029static void
7030varunset(const char *end, const char *var, const char *umsg, int varflags)
7031{
7032        const char *msg;
7033        const char *tail;
7034
7035        tail = nullstr;
7036        msg = "parameter not set";
7037        if (umsg) {
7038                if ((unsigned char)*end == CTLENDVAR) {
7039                        if (varflags & VSNUL)
7040                                tail = " or null";
7041                } else {
7042                        msg = umsg;
7043                }
7044        }
7045        ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
7046}
7047
7048static char *
7049subevalvar(char *start, char *str, int strloc,
7050                int startloc, int varflags, int flag)
7051{
7052        int subtype = varflags & VSTYPE;
7053        int quotes = flag & QUOTES_ESC;
7054        char *startp;
7055        char *loc;
7056        char *rmesc, *rmescend;
7057        long amount;
7058        int resetloc;
7059        int argstr_flags;
7060        IF_BASH_PATTERN_SUBST(int workloc;)
7061        IF_BASH_PATTERN_SUBST(int slash_pos;)
7062        IF_BASH_PATTERN_SUBST(char *repl;)
7063        int zero;
7064        char *(*scan)(char*, char*, char*, char*, int, int);
7065        char *p;
7066
7067        //bb_error_msg("subevalvar(start:'%s',str:'%s',strloc:%d,startloc:%d,varflags:%x,quotes:%d)",
7068        //              start, str, strloc, startloc, varflags, quotes);
7069
7070#if BASH_PATTERN_SUBST
7071        /* For "${v/pattern/repl}", we must find the delimiter _before_
7072         * argstr() call expands possible variable references in pattern:
7073         * think about "v=a; a=a/; echo ${v/$a/r}" case.
7074         */
7075        repl = NULL;
7076        if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
7077                /* Find '/' and replace with NUL */
7078                repl = start;
7079                /* The pattern can't be empty.
7080                 * IOW: if the first char after "${v//" is a slash,
7081                 * it does not terminate the pattern - it's the first char of the pattern:
7082                 *  v=/dev/ram; echo ${v////-}  prints -dev-ram (pattern is "/")
7083                 *  v=/dev/ram; echo ${v///r/-} prints /dev-am  (pattern is "/r")
7084                 */
7085                if (*repl == '/')
7086                        repl++;
7087                for (;;) {
7088                        if (*repl == '\0') {
7089                                repl = NULL;
7090                                break;
7091                        }
7092                        if (*repl == '/') {
7093                                *repl = '\0';
7094                                break;
7095                        }
7096                        /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */
7097                        if ((unsigned char)*repl == CTLESC && repl[1])
7098                                repl++;
7099                        repl++;
7100                }
7101        }
7102#endif
7103        argstr_flags = (flag & EXP_DISCARD) | EXP_TILDE;
7104        if (!str
7105#if BASH_SUBSTR
7106         && subtype != VSSUBSTR
7107#endif
7108        ) {
7109                /* EXP_CASE keeps CTLESC's */
7110                argstr_flags |= EXP_CASE;
7111        }
7112        p = argstr(start, argstr_flags);
7113
7114        //bb_error_msg("str0:'%s'", (char *)stackblock() + strloc);
7115#if BASH_PATTERN_SUBST
7116        slash_pos = -1;
7117        if (repl) {
7118                slash_pos = expdest - ((char *)stackblock() + strloc);
7119                if (!(flag & EXP_DISCARD))
7120                        STPUTC('/', expdest);
7121                //bb_error_msg("repl+1:'%s'", repl + 1);
7122                p = argstr(repl + 1, (flag & EXP_DISCARD) | EXP_TILDE); /* EXP_TILDE: echo "${v/x/~}" expands ~ ! */
7123                *repl = '/';
7124        }
7125#endif
7126        if (flag & EXP_DISCARD)
7127                return p;
7128
7129        startp = (char *)stackblock() + startloc;
7130        //bb_error_msg("str1:'%s'", (char *)stackblock() + strloc);
7131
7132        switch (subtype) {
7133        case VSASSIGN:
7134                setvar0(str, startp);
7135
7136                loc = startp;
7137                goto out;
7138
7139        case VSQUESTION:
7140                varunset(start, str, startp, varflags);
7141                /* NOTREACHED */
7142
7143#if BASH_SUBSTR
7144        case VSSUBSTR: {
7145                int pos, len, orig_len;
7146                char *colon;
7147                char *vstr;
7148
7149                loc = vstr = stackblock() + strloc;
7150
7151                /* Read POS in ${var:POS:LEN} */
7152                colon = strchr(loc, ':');
7153                if (colon) *colon = '\0';
7154                pos = substr_atoi(loc);
7155                if (colon) *colon = ':';
7156
7157                /* Read LEN in ${var:POS:LEN} */
7158                len = vstr - startp - 1;
7159                /* *loc != '\0', guaranteed by parser */
7160                if (quotes) {
7161                        char *ptr;
7162                        /* Adjust the length by the number of escapes */
7163                        for (ptr = startp; ptr < (vstr - 1); ptr++) {
7164                                if ((unsigned char)*ptr == CTLESC) {
7165                                        len--;
7166                                        ptr++;
7167                                }
7168                        }
7169                }
7170                orig_len = len;
7171                if (*loc++ == ':') {
7172                        /* ${var::LEN} */
7173                        len = substr_atoi(loc);
7174                } else {
7175                        /* Skip POS in ${var:POS:LEN} */
7176                        len = orig_len;
7177                        while (*loc && *loc != ':')
7178                                loc++;
7179                        if (*loc++ == ':')
7180                                len = substr_atoi(loc);
7181                }
7182                if (pos < 0) {
7183                        /* ${VAR:$((-n)):l} starts n chars from the end */
7184                        pos = orig_len + pos;
7185                }
7186                if ((unsigned)pos >= orig_len) {
7187                        /* apart from obvious ${VAR:999999:l},
7188                         * covers ${VAR:$((-9999999)):l} - result is ""
7189                         * (bash compat)
7190                         */
7191                        pos = 0;
7192                        len = 0;
7193                }
7194                if (len < 0) {
7195                        /* ${VAR:N:-M} sets LEN to strlen()-M */
7196                        len = (orig_len - pos) + len;
7197                }
7198                if ((unsigned)len > (orig_len - pos))
7199                        len = orig_len - pos;
7200
7201                for (vstr = startp; pos; vstr++, pos--) {
7202                        if (quotes && (unsigned char)*vstr == CTLESC)
7203                                vstr++;
7204                }
7205                for (loc = startp; len; len--) {
7206                        if (quotes && (unsigned char)*vstr == CTLESC)
7207                                *loc++ = *vstr++;
7208                        *loc++ = *vstr++;
7209                }
7210                *loc = '\0';
7211                goto out;
7212        }
7213#endif /* BASH_SUBSTR */
7214        }
7215
7216        resetloc = expdest - (char *)stackblock();
7217
7218#if BASH_PATTERN_SUBST
7219        repl = NULL;
7220
7221        /* We'll comeback here if we grow the stack while handling
7222         * a VSREPLACE or VSREPLACEALL, since our pointers into the
7223         * stack will need rebasing, and we'll need to remove our work
7224         * areas each time
7225         */
7226 restart:
7227#endif
7228
7229        amount = expdest - ((char *)stackblock() + resetloc);
7230        STADJUST(-amount, expdest);
7231        startp = (char *)stackblock() + startloc;
7232
7233        rmesc = startp;
7234        rmescend = (char *)stackblock() + strloc;
7235        //bb_error_msg("str7:'%s'", rmescend);
7236        if (quotes) {
7237//TODO: how to handle slash_pos here if string changes (shortens?)
7238                rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW, NULL);
7239                if (rmesc != startp) {
7240                        rmescend = expdest;
7241                        startp = (char *)stackblock() + startloc;
7242                }
7243        }
7244        rmescend--;
7245        str = (char *)stackblock() + strloc;
7246        /*
7247         * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
7248         * The result is a_\_z_c (not a\_\_z_c)!
7249         *
7250         * The search pattern and replace string treat backslashes differently!
7251         * "&slash_pos" causes rmescapes() to work differently on the pattern
7252         * and string.  It's only used on the first call.
7253         */
7254        //bb_error_msg("str8:'%s' slash_pos:%d", str, slash_pos);
7255        rmescapes(str, RMESCAPE_GLOB,
7256                repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos)
7257        );
7258
7259#if BASH_PATTERN_SUBST
7260        workloc = expdest - (char *)stackblock();
7261        if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
7262                size_t no_meta_len;
7263                int len;
7264                char *idx, *end;
7265
7266                if (!repl) {
7267                        //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos);
7268                        repl = nullstr;
7269                        if (slash_pos >= 0) {
7270                                repl = str + slash_pos;
7271                                *repl++ = '\0';
7272                        }
7273                }
7274                //bb_error_msg("str:'%s' repl:'%s'", str, repl);
7275
7276                /* If there's no pattern to match, return the expansion unmolested */
7277                if (str[0] == '\0')
7278                        goto out1;
7279
7280                no_meta_len = (ENABLE_ASH_OPTIMIZE_FOR_SIZE || strpbrk(str, "*?[\\")) ? 0 : strlen(str);
7281                len = 0;
7282                idx = startp;
7283                end = str - 1;
7284                while (idx <= end) {
7285 try_to_match:
7286                        if (no_meta_len == 0) {
7287                                /* pattern has meta chars, have to glob; or ENABLE_ASH_OPTIMIZE_FOR_SIZE */
7288                                loc = scanright(idx, rmesc, rmescend, str, quotes, /*match_at_start:*/ 1);
7289                        } else {
7290                                /* Testcase for very slow replace (performs about 22k replaces):
7291                                 * x=::::::::::::::::::::::
7292                                 * 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}
7293                                 * echo "${x//:/|}"
7294                                 */
7295                                if (strncmp(rmesc, str, no_meta_len) != 0)
7296                                        goto no_match;
7297                                loc = idx;
7298                                if (!quotes) {
7299                                        loc += no_meta_len;
7300                                } else {
7301                                        size_t n = no_meta_len;
7302                                        do {
7303                                                if ((unsigned char)*loc == CTLESC)
7304                                                        loc++;
7305                                                loc++;
7306                                        } while (--n != 0);
7307                                }
7308                        }
7309                        //bb_error_msg("scanright('%s'):'%s'", str, loc);
7310                        if (!loc) {
7311                                char *restart_detect;
7312 no_match:
7313                                /* No match, advance */
7314                                restart_detect = stackblock();
7315 skip_matching:
7316                                if (idx >= end)
7317                                        break;
7318                                STPUTC(*idx, expdest);
7319                                if (quotes && (unsigned char)*idx == CTLESC) {
7320                                        idx++;
7321                                        len++;
7322                                        STPUTC(*idx, expdest);
7323                                }
7324                                if (stackblock() != restart_detect)
7325                                        goto restart;
7326                                idx++;
7327                                len++;
7328                                rmesc++;
7329                                /* continue; - prone to quadratic behavior, smarter code: */
7330                                if (str[0] == '*') {
7331                                        /* Pattern is "*foo". If "*foo" does not match "long_string",
7332                                         * it would never match "ong_string" etc, no point in trying.
7333                                         */
7334                                        goto skip_matching;
7335                                }
7336                                goto try_to_match;
7337                        }
7338
7339                        if (subtype == VSREPLACEALL) {
7340                                while (idx < loc) {
7341                                        if (quotes && (unsigned char)*idx == CTLESC)
7342                                                idx++;
7343                                        idx++;
7344                                        rmesc++;
7345                                }
7346                        } else {
7347                                idx = loc;
7348                        }
7349
7350                        //bb_error_msg("repl:'%s'", repl);
7351                        for (loc = (char*)repl; *loc; loc++) {
7352                                char *restart_detect = stackblock();
7353                                if (quotes && *loc == '\\') {
7354                                        STPUTC(CTLESC, expdest);
7355                                        len++;
7356                                }
7357                                STPUTC(*loc, expdest);
7358                                if (stackblock() != restart_detect)
7359                                        goto restart;
7360                                len++;
7361                        }
7362
7363                        if (subtype == VSREPLACE) {
7364                                //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
7365                                while (*idx) {
7366                                        char *restart_detect = stackblock();
7367                                        STPUTC(*idx, expdest);
7368                                        if (stackblock() != restart_detect)
7369                                                goto restart;
7370                                        len++;
7371                                        idx++;
7372                                }
7373                                break;
7374                        }
7375                }
7376
7377                /* We've put the replaced text into a buffer at workloc, now
7378                 * move it to the right place and adjust the stack.
7379                 */
7380                STPUTC('\0', expdest);
7381                startp = (char *)stackblock() + startloc;
7382                memmove(startp, (char *)stackblock() + workloc, len + 1);
7383                //bb_error_msg("startp:'%s'", startp);
7384                loc = startp + len;
7385                goto out;
7386        }
7387#endif /* BASH_PATTERN_SUBST */
7388
7389        subtype -= VSTRIMRIGHT;
7390#if DEBUG
7391        if (subtype < 0 || subtype > 7)
7392                abort();
7393#endif
7394        /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
7395        zero = subtype >> 1;
7396        /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
7397        scan = (subtype & 1) ^ zero ? scanleft : scanright;
7398
7399        loc = scan(startp, rmesc, rmescend, str, quotes, zero);
7400        if (loc) {
7401                if (zero) {
7402                        memmove(startp, loc, str - loc);
7403                        loc = startp + (str - loc) - 1;
7404                }
7405                *loc = '\0';
7406        } else
7407                loc = str - 1;
7408
7409 out:
7410        amount = loc - expdest;
7411        STADJUST(amount, expdest);
7412#if BASH_PATTERN_SUBST
7413 out1:
7414#endif
7415        /* Remove any recorded regions beyond start of variable */
7416        removerecordregions(startloc);
7417
7418        return p;
7419}
7420
7421/*
7422 * Add the value of a specialized variable to the stack string.
7423 * name parameter (examples):
7424 * ash -c 'echo $1'      name:'1='
7425 * ash -c 'echo $qwe'    name:'qwe='
7426 * ash -c 'echo $$'      name:'$='
7427 * ash -c 'echo ${$}'    name:'$='
7428 * ash -c 'echo ${$##q}' name:'$=q'
7429 * ash -c 'echo ${#$}'   name:'$='
7430 * note: examples with bad shell syntax:
7431 * ash -c 'echo ${#$1}'  name:'$=1'
7432 * ash -c 'echo ${#1#}'  name:'1=#'
7433 */
7434static NOINLINE ssize_t
7435varvalue(char *name, int varflags, int flags, int quoted)
7436{
7437        const char *p;
7438        int num;
7439        int i;
7440        ssize_t len = 0;
7441        int sep;
7442        int subtype = varflags & VSTYPE;
7443        int discard = (subtype == VSPLUS || subtype == VSLENGTH) | (flags & EXP_DISCARD);
7444
7445        if (!subtype) {
7446                if (discard)
7447                        return -1;
7448
7449                raise_error_syntax("bad substitution");
7450        }
7451
7452        flags |= EXP_KEEPNUL;
7453        flags &= discard ? ~QUOTES_ESC : ~0;
7454        sep = (flags & EXP_FULL) << CHAR_BIT;
7455
7456        switch (*name) {
7457        case '$':
7458                num = rootpid;
7459                goto numvar;
7460        case '?':
7461                num = exitstatus;
7462                goto numvar;
7463        case '#':
7464                num = shellparam.nparam;
7465                goto numvar;
7466        case '!':
7467                num = backgndpid;
7468                if (num == 0)
7469                        return -1;
7470 numvar:
7471                len = cvtnum(num, flags);
7472                goto check_1char_name;
7473        case '-':
7474                expdest = makestrspace(NOPTS, expdest);
7475                for (i = NOPTS - 1; i >= 0; i--) {
7476                        if (optlist[i] && optletters(i)) {
7477                                USTPUTC(optletters(i), expdest);
7478                                len++;
7479                        }
7480                }
7481 check_1char_name:
7482#if 0
7483                /* handles cases similar to ${#$1} */
7484                if (name[2] != '\0')
7485                        raise_error_syntax("bad substitution");
7486#endif
7487                break;
7488        case '@':
7489                if (quoted && sep)
7490                        goto param;
7491                /* fall through */
7492        case '*': {
7493                char **ap;
7494                char sepc;
7495                char c;
7496
7497                /* We will set c to 0 or ~0 depending on whether
7498                 * we're doing field splitting.  We won't do field
7499                 * splitting if either we're quoted or sep is zero.
7500                 *
7501                 * Instead of testing (quoted || !sep) the following
7502                 * trick optimises away any branches by using the
7503                 * fact that EXP_QUOTED (which is the only bit that
7504                 * can be set in quoted) is the same as EXP_FULL <<
7505                 * CHAR_BIT (which is the only bit that can be set
7506                 * in sep).
7507                 */
7508#if EXP_QUOTED >> CHAR_BIT != EXP_FULL
7509#error The following two lines expect EXP_QUOTED == EXP_FULL << CHAR_BIT
7510#endif
7511                c = !((quoted | ~sep) & EXP_QUOTED) - 1;
7512                sep &= ~quoted;
7513                sep |= ifsset() ? (unsigned char)(c & ifsval()[0]) : ' ';
7514 param:
7515                sepc = sep;
7516                ap = shellparam.p;
7517                if (!ap)
7518                        return -1;
7519                while ((p = *ap++) != NULL) {
7520                        len += strtodest(p, flags);
7521
7522                        if (*ap && sep) {
7523                                len++;
7524                                memtodest(&sepc, 1, flags);
7525                        }
7526                }
7527                break;
7528        } /* case '*' */
7529        case '0':
7530        case '1':
7531        case '2':
7532        case '3':
7533        case '4':
7534        case '5':
7535        case '6':
7536        case '7':
7537        case '8':
7538        case '9':
7539                num = atoi(name); /* number(name) fails on ${N#str} etc */
7540                if (num < 0 || num > shellparam.nparam)
7541                        return -1;
7542                p = num ? shellparam.p[num - 1] : arg0;
7543                goto value;
7544        default:
7545                /* NB: name has form "VAR=..." */
7546                p = lookupvar(name);
7547 value:
7548                if (!p)
7549                        return -1;
7550
7551                len = strtodest(p, flags);
7552#if ENABLE_UNICODE_SUPPORT
7553                if (subtype == VSLENGTH && len > 0) {
7554                        reinit_unicode_for_ash();
7555                        if (unicode_status == UNICODE_ON) {
7556                                STADJUST(-len, expdest);
7557                                discard = 0;
7558                                len = unicode_strlen(p);
7559                        }
7560                }
7561#endif
7562                break;
7563        }
7564
7565        if (discard)
7566                STADJUST(-len, expdest);
7567
7568        return len;
7569}
7570
7571/*
7572 * Expand a variable, and return a pointer to the next character in the
7573 * input string.
7574 */
7575static char *
7576evalvar(char *p, int flag)
7577{
7578        char varflags;
7579        char subtype;
7580        char *var;
7581        int patloc;
7582        int startloc;
7583        ssize_t varlen;
7584        int discard;
7585        int quoted;
7586
7587        varflags = (unsigned char) *p++;
7588        subtype = varflags & VSTYPE;
7589
7590        quoted = flag & EXP_QUOTED;
7591        var = p;
7592        startloc = expdest - (char *)stackblock();
7593        p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7594
7595 again:
7596        varlen = varvalue(var, varflags, flag, quoted);
7597        if (varflags & VSNUL)
7598                varlen--;
7599
7600        discard = varlen < 0 ? EXP_DISCARD : 0;
7601
7602        switch (subtype) {
7603        case VSPLUS:
7604                discard ^= EXP_DISCARD;
7605                /* fall through */
7606        case 0:
7607        case VSMINUS:
7608                p = argstr(p, flag | EXP_TILDE | EXP_WORD | (discard ^ EXP_DISCARD));
7609                goto record;
7610
7611        case VSASSIGN:
7612        case VSQUESTION:
7613                p = subevalvar(p, var, 0, startloc, varflags,
7614                        (flag & ~QUOTES_ESC) | (discard ^ EXP_DISCARD));
7615
7616                if ((flag | ~discard) & EXP_DISCARD)
7617                        goto record;
7618
7619                varflags &= ~VSNUL;
7620                subtype = VSNORMAL;
7621                goto again;
7622        }
7623
7624        if ((discard & ~flag) && uflag)
7625                varunset(p, var, 0, 0);
7626
7627        if (subtype == VSLENGTH) {
7628                p++;
7629                if (flag & EXP_DISCARD)
7630                        return p;
7631                cvtnum(varlen > 0 ? varlen : 0, flag);
7632                goto really_record;
7633        }
7634
7635        if (subtype == VSNORMAL)
7636                goto record;
7637
7638#if DEBUG
7639        switch (subtype) {
7640        case VSTRIMLEFT:
7641        case VSTRIMLEFTMAX:
7642        case VSTRIMRIGHT:
7643        case VSTRIMRIGHTMAX:
7644#if BASH_SUBSTR
7645        case VSSUBSTR:
7646#endif
7647#if BASH_PATTERN_SUBST
7648        case VSREPLACE:
7649        case VSREPLACEALL:
7650#endif
7651                break;
7652        default:
7653                abort();
7654        }
7655#endif
7656
7657        flag |= discard;
7658        if (!(flag & EXP_DISCARD)) {
7659                /*
7660                 * Terminate the string and start recording the pattern
7661                 * right after it
7662                 */
7663                STPUTC('\0', expdest);
7664        }
7665
7666        patloc = expdest - (char *)stackblock();
7667        p = subevalvar(p, NULL, patloc, startloc, varflags, flag);
7668
7669 record:
7670        if ((flag | discard) & EXP_DISCARD)
7671                return p;
7672
7673 really_record:
7674        if (quoted) {
7675                quoted = *var == '@' && shellparam.nparam;
7676                if (!quoted)
7677                        return p;
7678        }
7679        recordregion(startloc, expdest - (char *)stackblock(), quoted);
7680        return p;
7681}
7682
7683/*
7684 * Add a file name to the list.
7685 */
7686static void
7687addfname(const char *name)
7688{
7689        struct strlist *sp;
7690
7691        sp = stzalloc(sizeof(*sp));
7692        sp->text = sstrdup(name);
7693        *exparg.lastp = sp;
7694        exparg.lastp = &sp->next;
7695}
7696
7697/* Avoid glob() (and thus, stat() et al) for words like "echo" */
7698static int
7699hasmeta(const char *p)
7700{
7701        static const char chars[] ALIGN1 = {
7702                '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7703        };
7704
7705        for (;;) {
7706                p = strpbrk(p, chars);
7707                if (!p)
7708                        break;
7709                switch ((unsigned char)*p) {
7710                case CTLQUOTEMARK:
7711                        for (;;) {
7712                                p++;
7713                                if ((unsigned char)*p == CTLQUOTEMARK)
7714                                        break;
7715                                if ((unsigned char)*p == CTLESC)
7716                                        p++;
7717                                if (*p == '\0') /* huh? */
7718                                        return 0;
7719                        }
7720                        break;
7721                case '\\':
7722                case CTLESC:
7723                        p++;
7724                        if (*p == '\0')
7725                                return 0;
7726                        break;
7727                case '[':
7728                        if (!strchr(p + 1, ']')) {
7729                                /* It's not a properly closed [] pattern,
7730                                 * but other metas may follow. Continue checking.
7731                                 * my[file* _is_ globbed by bash
7732                                 * and matches filenames like "my[file1".
7733                                 */
7734                                break;
7735                        }
7736                        /* fallthrough */
7737                default:
7738                /* case '*': */
7739                /* case '?': */
7740                        return 1;
7741                }
7742                p++;
7743        }
7744
7745        return 0;
7746}
7747
7748/* If we want to use glob() from libc... */
7749#if !ENABLE_ASH_INTERNAL_GLOB
7750
7751/* Add the result of glob() to the list */
7752static void
7753addglob(const glob_t *pglob)
7754{
7755        char **p = pglob->gl_pathv;
7756
7757        do {
7758                addfname(*p);
7759        } while (*++p);
7760}
7761static void
7762expandmeta(struct strlist *str /*, int flag*/)
7763{
7764        /* TODO - EXP_REDIR */
7765
7766        while (str) {
7767                char *p;
7768                glob_t pglob;
7769                int i;
7770
7771                if (fflag)
7772                        goto nometa;
7773
7774                if (!hasmeta(str->text))
7775                        goto nometa;
7776
7777                INT_OFF;
7778                p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7779// GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7780// GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7781//
7782// glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7783// if you pass it "file\?", it returns "file\?", not "file?", if no match.
7784// Which means you need to unescape the string, right? Not so fast:
7785// if there _is_ a file named "file\?" (with backslash), it is returned
7786// as "file\?" too (whichever pattern you used to find it, say, "file*").
7787// You DON'T KNOW by looking at the result whether you need to unescape it.
7788//
7789// Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7790// returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7791// Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7792// With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7793//              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7794//              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7795                i = glob(p, 0, NULL, &pglob);
7796                //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7797                if (p != str->text)
7798                        free(p);
7799                switch (i) {
7800                case 0:
7801#if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7802                        /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7803                        if (!(pglob.gl_flags & GLOB_MAGCHAR))
7804                                goto nometa2;
7805#endif
7806                        addglob(&pglob);
7807                        globfree(&pglob);
7808                        INT_ON;
7809                        break;
7810                case GLOB_NOMATCH:
7811 //nometa2:
7812                        globfree(&pglob);
7813                        INT_ON;
7814 nometa:
7815                        *exparg.lastp = str;
7816                        rmescapes(str->text, 0, NULL);
7817                        exparg.lastp = &str->next;
7818                        break;
7819                default:        /* GLOB_NOSPACE */
7820                        globfree(&pglob);
7821                        INT_ON;
7822                        ash_msg_and_raise_error(bb_msg_memory_exhausted);
7823                }
7824                str = str->next;
7825        }
7826}
7827
7828#else
7829/* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7830
7831/*
7832 * Do metacharacter (i.e. *, ?, [...]) expansion.
7833 */
7834typedef struct exp_t {
7835        char *dir;
7836        unsigned dir_max;
7837} exp_t;
7838static void
7839expmeta(exp_t *exp, char *name, unsigned name_len, unsigned expdir_len)
7840{
7841#define expdir exp->dir
7842#define expdir_max exp->dir_max
7843        char *enddir = expdir + expdir_len;
7844        char *p;
7845        const char *cp;
7846        char *start;
7847        char *endname;
7848        int metaflag;
7849        struct stat statb;
7850        DIR *dirp;
7851        struct dirent *dp;
7852        int atend;
7853        int matchdot;
7854        int esc;
7855
7856        metaflag = 0;
7857        start = name;
7858        for (p = name; esc = 0, *p; p += esc + 1) {
7859                if (*p == '*' || *p == '?')
7860                        metaflag = 1;
7861                else if (*p == '[') {
7862                        char *q = p + 1;
7863                        if (*q == '!')
7864                                q++;
7865                        for (;;) {
7866                                if (*q == '\\')
7867                                        q++;
7868                                if (*q == '/' || *q == '\0')
7869                                        break;
7870                                if (*++q == ']') {
7871                                        metaflag = 1;
7872                                        break;
7873                                }
7874                        }
7875                } else {
7876                        if (*p == '\\' && p[1])
7877                                esc++;
7878                        if (p[esc] == '/') {
7879                                if (metaflag)
7880                                        break;
7881                                start = p + esc + 1;
7882                        }
7883                }
7884        }
7885        if (metaflag == 0) {    /* we've reached the end of the file name */
7886                if (!expdir_len)
7887                        return;
7888                p = name;
7889                do {
7890                        if (*p == '\\' && p[1])
7891                                p++;
7892                        *enddir++ = *p;
7893                } while (*p++);
7894                if (lstat(expdir, &statb) == 0)
7895                        addfname(expdir);
7896                return;
7897        }
7898        endname = p;
7899        if (name < start) {
7900                p = name;
7901                do {
7902                        if (*p == '\\' && p[1])
7903                                p++;
7904                        *enddir++ = *p++;
7905                } while (p < start);
7906        }
7907        *enddir = '\0';
7908        cp = expdir;
7909        expdir_len = enddir - cp;
7910        if (!expdir_len)
7911                cp = ".";
7912        dirp = opendir(cp);
7913        if (dirp == NULL)
7914                return;
7915        if (*endname == 0) {
7916                atend = 1;
7917        } else {
7918                atend = 0;
7919                *endname = '\0';
7920                endname += esc + 1;
7921        }
7922        name_len -= endname - name;
7923        matchdot = 0;
7924        p = start;
7925        if (*p == '\\')
7926                p++;
7927        if (*p == '.')
7928                matchdot++;
7929        while (!pending_int && (dp = readdir(dirp)) != NULL) {
7930                if (dp->d_name[0] == '.' && !matchdot)
7931                        continue;
7932                if (pmatch(start, dp->d_name)) {
7933                        if (atend) {
7934                                strcpy(enddir, dp->d_name);
7935                                addfname(expdir);
7936                        } else {
7937                                unsigned offset;
7938                                unsigned len;
7939
7940                                p = stpcpy(enddir, dp->d_name);
7941                                *p = '/';
7942
7943                                offset = p - expdir + 1;
7944                                len = offset + name_len + NAME_MAX;
7945                                if (len > expdir_max) {
7946                                        len += PATH_MAX;
7947                                        expdir = ckrealloc(expdir, len);
7948                                        expdir_max = len;
7949                                }
7950
7951                                expmeta(exp, endname, name_len, offset);
7952                                enddir = expdir + expdir_len;
7953                        }
7954                }
7955        }
7956        closedir(dirp);
7957        if (!atend)
7958                endname[-esc - 1] = esc ? '\\' : '/';
7959#undef expdir
7960#undef expdir_max
7961}
7962
7963static struct strlist *
7964msort(struct strlist *list, int len)
7965{
7966        struct strlist *p, *q = NULL;
7967        struct strlist **lpp;
7968        int half;
7969        int n;
7970
7971        if (len <= 1)
7972                return list;
7973        half = len >> 1;
7974        p = list;
7975        for (n = half; --n >= 0;) {
7976                q = p;
7977                p = p->next;
7978        }
7979        q->next = NULL;                 /* terminate first half of list */
7980        q = msort(list, half);          /* sort first half of list */
7981        p = msort(p, len - half);               /* sort second half */
7982        lpp = &list;
7983        for (;;) {
7984#if ENABLE_LOCALE_SUPPORT
7985                if (strcoll(p->text, q->text) < 0)
7986#else
7987                if (strcmp(p->text, q->text) < 0)
7988#endif
7989                                                {
7990                        *lpp = p;
7991                        lpp = &p->next;
7992                        p = *lpp;
7993                        if (p == NULL) {
7994                                *lpp = q;
7995                                break;
7996                        }
7997                } else {
7998                        *lpp = q;
7999                        lpp = &q->next;
8000                        q = *lpp;
8001                        if (q == NULL) {
8002                                *lpp = p;
8003                                break;
8004                        }
8005                }
8006        }
8007        return list;
8008}
8009
8010/*
8011 * Sort the results of file name expansion.  It calculates the number of
8012 * strings to sort and then calls msort (short for merge sort) to do the
8013 * work.
8014 */
8015static struct strlist *
8016expsort(struct strlist *str)
8017{
8018        int len;
8019        struct strlist *sp;
8020
8021        len = 0;
8022        for (sp = str; sp; sp = sp->next)
8023                len++;
8024        return msort(str, len);
8025}
8026
8027static void
8028expandmeta(struct strlist *str /*, int flag*/)
8029{
8030        /* TODO - EXP_REDIR */
8031
8032        while (str) {
8033                exp_t exp;
8034                struct strlist **savelastp;
8035                struct strlist *sp;
8036                char *p;
8037                unsigned len;
8038
8039                if (fflag)
8040                        goto nometa;
8041                if (!hasmeta(str->text))
8042                        goto nometa;
8043                savelastp = exparg.lastp;
8044
8045                INT_OFF;
8046                p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
8047                len = strlen(p);
8048                exp.dir_max = len + PATH_MAX;
8049                exp.dir = ckmalloc(exp.dir_max);
8050
8051                expmeta(&exp, p, len, 0);
8052                free(exp.dir);
8053                if (p != str->text)
8054                        free(p);
8055                INT_ON;
8056                if (exparg.lastp == savelastp) {
8057                        /*
8058                         * no matches
8059                         */
8060 nometa:
8061                        *exparg.lastp = str;
8062                        rmescapes(str->text, 0, NULL);
8063                        exparg.lastp = &str->next;
8064                } else {
8065                        *exparg.lastp = NULL;
8066                        *savelastp = sp = expsort(*savelastp);
8067                        while (sp->next != NULL)
8068                                sp = sp->next;
8069                        exparg.lastp = &sp->next;
8070                }
8071                str = str->next;
8072        }
8073}
8074#endif /* ENABLE_ASH_INTERNAL_GLOB */
8075
8076/*
8077 * Perform variable substitution and command substitution on an argument,
8078 * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
8079 * perform splitting and file name expansion.  When arglist is NULL, perform
8080 * here document expansion.
8081 */
8082static void
8083expandarg(union node *arg, struct arglist *arglist, int flag)
8084{
8085        struct strlist *sp;
8086        char *p;
8087
8088        argbackq = arg->narg.backquote;
8089        STARTSTACKSTR(expdest);
8090        TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
8091        argstr(arg->narg.text, flag);
8092        if (arglist == NULL) {
8093                /* here document expanded */
8094                goto out;
8095        }
8096        p = grabstackstr(expdest);
8097        TRACE(("expandarg: p:'%s'\n", p));
8098        exparg.lastp = &exparg.list;
8099        /*
8100         * TODO - EXP_REDIR
8101         */
8102        if (flag & EXP_FULL) {
8103                ifsbreakup(p, &exparg);
8104                *exparg.lastp = NULL;
8105                exparg.lastp = &exparg.list;
8106                expandmeta(exparg.list /*, flag*/);
8107        } else {
8108                sp = stzalloc(sizeof(*sp));
8109                sp->text = p;
8110                *exparg.lastp = sp;
8111                exparg.lastp = &sp->next;
8112        }
8113        *exparg.lastp = NULL;
8114        if (exparg.list) {
8115                *arglist->lastp = exparg.list;
8116                arglist->lastp = exparg.lastp;
8117        }
8118
8119 out:
8120        ifsfree();
8121}
8122
8123/*
8124 * Expand shell variables and backquotes inside a here document.
8125 */
8126static void
8127expandhere(union node *arg)
8128{
8129        expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
8130}
8131
8132/*
8133 * Returns true if the pattern matches the string.
8134 */
8135static int
8136patmatch(char *pattern, const char *string)
8137{
8138        char *p = preglob(pattern, 0);
8139        int r = pmatch(p, string);
8140        //bb_error_msg("!fnmatch(pattern:'%s',str:'%s',0):%d", p, string, r);
8141        return r;
8142}
8143
8144/*
8145 * See if a pattern matches in a case statement.
8146 */
8147static int
8148casematch(union node *pattern, char *val)
8149{
8150        struct stackmark smark;
8151        int result;
8152
8153        setstackmark(&smark);
8154        argbackq = pattern->narg.backquote;
8155        STARTSTACKSTR(expdest);
8156        argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
8157        ifsfree();
8158        result = patmatch(stackblock(), val);
8159        popstackmark(&smark);
8160        return result;
8161}
8162
8163
8164/* ============ find_command */
8165
8166struct builtincmd {
8167        const char *name;
8168        int (*builtin)(int, char **) FAST_FUNC;
8169        /* unsigned flags; */
8170};
8171#define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
8172/* "regular" builtins always take precedence over commands,
8173 * regardless of PATH=....%builtin... position */
8174#define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
8175#define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
8176
8177struct cmdentry {
8178        smallint cmdtype;       /* CMDxxx */
8179        union param {
8180                int index;
8181                /* index >= 0 for commands without path (slashes) */
8182                /* (TODO: what exactly does the value mean? PATH position?) */
8183                /* index == -1 for commands with slashes */
8184                /* index == (-2 - applet_no) for NOFORK applets */
8185                const struct builtincmd *cmd;
8186                struct funcnode *func;
8187        } u;
8188};
8189/* values of cmdtype */
8190#define CMDUNKNOWN      -1      /* no entry in table for command */
8191#define CMDNORMAL       0       /* command is an executable program */
8192#define CMDFUNCTION     1       /* command is a shell function */
8193#define CMDBUILTIN      2       /* command is a shell builtin */
8194
8195/* action to find_command() */
8196#define DO_ERR          0x01    /* prints errors */
8197#define DO_ABS          0x02    /* checks absolute paths */
8198#define DO_NOFUNC       0x04    /* don't return shell functions, for command */
8199#define DO_ALTPATH      0x08    /* using alternate path */
8200#define DO_REGBLTIN     0x10    /* regular built-ins and functions only */
8201
8202static void find_command(char *, struct cmdentry *, int, const char *);
8203
8204
8205/* ============ Hashing commands */
8206
8207/*
8208 * When commands are first encountered, they are entered in a hash table.
8209 * This ensures that a full path search will not have to be done for them
8210 * on each invocation.
8211 *
8212 * We should investigate converting to a linear search, even though that
8213 * would make the command name "hash" a misnomer.
8214 */
8215
8216struct tblentry {
8217        struct tblentry *next;  /* next entry in hash chain */
8218        union param param;      /* definition of builtin function */
8219        smallint cmdtype;       /* CMDxxx */
8220        char rehash;            /* if set, cd done since entry created */
8221        char cmdname[1];        /* name of command */
8222};
8223
8224static struct tblentry **cmdtable;
8225#define INIT_G_cmdtable() do { \
8226        cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
8227} while (0)
8228
8229static int builtinloc = -1;     /* index in path of %builtin, or -1 */
8230
8231
8232static void
8233tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
8234{
8235#if ENABLE_FEATURE_SH_STANDALONE
8236        if (applet_no >= 0) {
8237                if (APPLET_IS_NOEXEC(applet_no)) {
8238                        clearenv();
8239                        while (*envp)
8240                                putenv(*envp++);
8241                        popredir(/*drop:*/ 1);
8242                        run_noexec_applet_and_exit(applet_no, cmd, argv);
8243                }
8244                /* re-exec ourselves with the new arguments */
8245                execve(bb_busybox_exec_path, argv, envp);
8246                /* If they called chroot or otherwise made the binary no longer
8247                 * executable, fall through */
8248        }
8249#endif
8250
8251 repeat:
8252#ifdef SYSV
8253        do {
8254                execve(cmd, argv, envp);
8255        } while (errno == EINTR);
8256#else
8257        execve(cmd, argv, envp);
8258#endif
8259
8260        if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
8261                /* Run "cmd" as a shell script:
8262                 * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
8263                 * "If the execve() function fails with ENOEXEC, the shell
8264                 * shall execute a command equivalent to having a shell invoked
8265                 * with the command name as its first operand,
8266                 * with any remaining arguments passed to the new shell"
8267                 *
8268                 * That is, do not use $SHELL, user's shell, or /bin/sh;
8269                 * just call ourselves.
8270                 *
8271                 * Note that bash reads ~80 chars of the file, and if it sees
8272                 * a zero byte before it sees newline, it doesn't try to
8273                 * interpret it, but fails with "cannot execute binary file"
8274                 * message and exit code 126. For one, this prevents attempts
8275                 * to interpret foreign ELF binaries as shell scripts.
8276                 */
8277                argv[0] = (char*) cmd;
8278                cmd = bb_busybox_exec_path;
8279                /* NB: this is only possible because all callers of shellexec()
8280                 * ensure that the argv[-1] slot exists!
8281                 */
8282                argv--;
8283                argv[0] = (char*) "ash";
8284                goto repeat;
8285        }
8286}
8287
8288/*
8289 * Exec a program.  Never returns.  If you change this routine, you may
8290 * have to change the find_command routine as well.
8291 * argv[-1] must exist and be writable! See tryexec() for why.
8292 */
8293static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
8294static void shellexec(char *prog, char **argv, const char *path, int idx)
8295{
8296        char *cmdname;
8297        int e;
8298        char **envp;
8299        int exerrno;
8300        int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
8301
8302        envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
8303        if (strchr(prog, '/') != NULL
8304#if ENABLE_FEATURE_SH_STANDALONE
8305         || (applet_no = find_applet_by_name(prog)) >= 0
8306#endif
8307        ) {
8308                tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
8309                if (applet_no >= 0) {
8310                        /* We tried execing ourself, but it didn't work.
8311                         * Maybe /proc/self/exe doesn't exist?
8312                         * Try $PATH search.
8313                         */
8314                        goto try_PATH;
8315                }
8316                e = errno;
8317        } else {
8318 try_PATH:
8319                e = ENOENT;
8320                while (padvance(&path, argv[0]) >= 0) {
8321                        cmdname = stackblock();
8322                        if (--idx < 0 && pathopt == NULL) {
8323                                tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
8324                                if (errno != ENOENT && errno != ENOTDIR)
8325                                        e = errno;
8326                        }
8327                }
8328        }
8329
8330        /* Map to POSIX errors */
8331        switch (e) {
8332        default:
8333                exerrno = 126;
8334                break;
8335        case ELOOP:
8336        case ENAMETOOLONG:
8337        case ENOENT:
8338        case ENOTDIR:
8339                exerrno = 127;
8340                break;
8341        }
8342        exitstatus = exerrno;
8343        TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
8344                prog, e, suppress_int));
8345        ash_msg_and_raise(EXEND, "%s: %s", prog, errmsg(e, "not found"));
8346        /* NOTREACHED */
8347}
8348
8349static void
8350printentry(struct tblentry *cmdp)
8351{
8352        int idx;
8353        const char *path;
8354        char *name;
8355
8356        idx = cmdp->param.index;
8357        path = pathval();
8358        do {
8359                padvance(&path, cmdp->cmdname);
8360        } while (--idx >= 0);
8361        name = stackblock();
8362        out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
8363}
8364
8365/*
8366 * Clear out command entries.
8367 */
8368static void
8369clearcmdentry(void)
8370{
8371        struct tblentry **tblp;
8372        struct tblentry **pp;
8373        struct tblentry *cmdp;
8374
8375        INT_OFF;
8376        for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
8377                pp = tblp;
8378                while ((cmdp = *pp) != NULL) {
8379                        if (cmdp->cmdtype == CMDNORMAL
8380                         || (cmdp->cmdtype == CMDBUILTIN
8381                            && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8382                            && builtinloc > 0
8383                            )
8384                        ) {
8385                                *pp = cmdp->next;
8386                                free(cmdp);
8387                        } else {
8388                                pp = &cmdp->next;
8389                        }
8390                }
8391        }
8392        INT_ON;
8393}
8394
8395/*
8396 * Locate a command in the command hash table.  If "add" is nonzero,
8397 * add the command to the table if it is not already present.  The
8398 * variable "lastcmdentry" is set to point to the address of the link
8399 * pointing to the entry, so that delete_cmd_entry can delete the
8400 * entry.
8401 *
8402 * Interrupts must be off if called with add != 0.
8403 */
8404static struct tblentry **lastcmdentry;
8405
8406static struct tblentry *
8407cmdlookup(const char *name, int add)
8408{
8409        unsigned int hashval;
8410        const char *p;
8411        struct tblentry *cmdp;
8412        struct tblentry **pp;
8413
8414        p = name;
8415        hashval = (unsigned char)*p << 4;
8416        while (*p)
8417                hashval += (unsigned char)*p++;
8418        hashval &= 0x7FFF;
8419        pp = &cmdtable[hashval % CMDTABLESIZE];
8420        for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8421                if (strcmp(cmdp->cmdname, name) == 0)
8422                        break;
8423                pp = &cmdp->next;
8424        }
8425        if (add && cmdp == NULL) {
8426                cmdp = *pp = ckzalloc(sizeof(struct tblentry)
8427                                + strlen(name)
8428                                /* + 1 - already done because
8429                                 * tblentry::cmdname is char[1] */);
8430                /*cmdp->next = NULL; - ckzalloc did it */
8431                cmdp->cmdtype = CMDUNKNOWN;
8432                strcpy(cmdp->cmdname, name);
8433        }
8434        lastcmdentry = pp;
8435        return cmdp;
8436}
8437
8438/*
8439 * Delete the command entry returned on the last lookup.
8440 */
8441static void
8442delete_cmd_entry(void)
8443{
8444        struct tblentry *cmdp;
8445
8446        INT_OFF;
8447        cmdp = *lastcmdentry;
8448        *lastcmdentry = cmdp->next;
8449        if (cmdp->cmdtype == CMDFUNCTION)
8450                freefunc(cmdp->param.func);
8451        free(cmdp);
8452        INT_ON;
8453}
8454
8455/*
8456 * Add a new command entry, replacing any existing command entry for
8457 * the same name - except special builtins.
8458 */
8459static void
8460addcmdentry(char *name, struct cmdentry *entry)
8461{
8462        struct tblentry *cmdp;
8463
8464        cmdp = cmdlookup(name, 1);
8465        if (cmdp->cmdtype == CMDFUNCTION) {
8466                freefunc(cmdp->param.func);
8467        }
8468        cmdp->cmdtype = entry->cmdtype;
8469        cmdp->param = entry->u;
8470        cmdp->rehash = 0;
8471}
8472
8473static int FAST_FUNC
8474hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8475{
8476        struct tblentry **pp;
8477        struct tblentry *cmdp;
8478        int c;
8479        struct cmdentry entry;
8480        char *name;
8481
8482        if (nextopt("r") != '\0') {
8483                clearcmdentry();
8484                return 0;
8485        }
8486
8487        if (*argptr == NULL) {
8488                for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8489                        for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8490                                if (cmdp->cmdtype == CMDNORMAL)
8491                                        printentry(cmdp);
8492                        }
8493                }
8494                return 0;
8495        }
8496
8497        c = 0;
8498        while ((name = *argptr) != NULL) {
8499                cmdp = cmdlookup(name, 0);
8500                if (cmdp != NULL
8501                 && (cmdp->cmdtype == CMDNORMAL
8502                    || (cmdp->cmdtype == CMDBUILTIN
8503                        && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8504                        && builtinloc > 0
8505                        )
8506                    )
8507                ) {
8508                        delete_cmd_entry();
8509                }
8510                find_command(name, &entry, DO_ERR, pathval());
8511                if (entry.cmdtype == CMDUNKNOWN)
8512                        c = 1;
8513                argptr++;
8514        }
8515        return c;
8516}
8517
8518/*
8519 * Called when a cd is done.  Marks all commands so the next time they
8520 * are executed they will be rehashed.
8521 */
8522static void
8523hashcd(void)
8524{
8525        struct tblentry **pp;
8526        struct tblentry *cmdp;
8527
8528        for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8529                for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8530                        if (cmdp->cmdtype == CMDNORMAL
8531                         || (cmdp->cmdtype == CMDBUILTIN
8532                             && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8533                             && builtinloc > 0)
8534                        ) {
8535                                cmdp->rehash = 1;
8536                        }
8537                }
8538        }
8539}
8540
8541/*
8542 * Fix command hash table when PATH changed.
8543 * Called before PATH is changed.  The argument is the new value of PATH;
8544 * pathval() still returns the old value at this point.
8545 * Called with interrupts off.
8546 */
8547static void FAST_FUNC
8548changepath(const char *newval)
8549{
8550        const char *new;
8551        int idx;
8552        int bltin;
8553
8554        new = newval;
8555        idx = 0;
8556        bltin = -1;
8557        for (;;) {
8558                if (*new == '%' && prefix(new + 1, "builtin")) {
8559                        bltin = idx;
8560                        break;
8561                }
8562                new = strchr(new, ':');
8563                if (!new)
8564                        break;
8565                idx++;
8566                new++;
8567        }
8568        builtinloc = bltin;
8569        clearcmdentry();
8570}
8571enum {
8572        TEOF,
8573        TNL,
8574        TREDIR,
8575        TWORD,
8576        TSEMI,
8577        TBACKGND,
8578        TAND,
8579        TOR,
8580        TPIPE,
8581        TLP,
8582        TRP,
8583        TENDCASE,
8584        TENDBQUOTE,
8585        TNOT,
8586        TCASE,
8587        TDO,
8588        TDONE,
8589        TELIF,
8590        TELSE,
8591        TESAC,
8592        TFI,
8593        TFOR,
8594#if BASH_FUNCTION
8595        TFUNCTION,
8596#endif
8597        TIF,
8598        TIN,
8599        TTHEN,
8600        TUNTIL,
8601        TWHILE,
8602        TBEGIN,
8603        TEND
8604};
8605typedef smallint token_id_t;
8606
8607/* Nth bit indicates if token marks the end of a list */
8608enum {
8609        tokendlist = 0
8610        /*  0 */ | (1u << TEOF)
8611        /*  1 */ | (0u << TNL)
8612        /*  2 */ | (0u << TREDIR)
8613        /*  3 */ | (0u << TWORD)
8614        /*  4 */ | (0u << TSEMI)
8615        /*  5 */ | (0u << TBACKGND)
8616        /*  6 */ | (0u << TAND)
8617        /*  7 */ | (0u << TOR)
8618        /*  8 */ | (0u << TPIPE)
8619        /*  9 */ | (0u << TLP)
8620        /* 10 */ | (1u << TRP)
8621        /* 11 */ | (1u << TENDCASE)
8622        /* 12 */ | (1u << TENDBQUOTE)
8623        /* 13 */ | (0u << TNOT)
8624        /* 14 */ | (0u << TCASE)
8625        /* 15 */ | (1u << TDO)
8626        /* 16 */ | (1u << TDONE)
8627        /* 17 */ | (1u << TELIF)
8628        /* 18 */ | (1u << TELSE)
8629        /* 19 */ | (1u << TESAC)
8630        /* 20 */ | (1u << TFI)
8631        /* 21 */ | (0u << TFOR)
8632#if BASH_FUNCTION
8633        /* 22 */ | (0u << TFUNCTION)
8634#endif
8635        /* 23 */ | (0u << TIF)
8636        /* 24 */ | (0u << TIN)
8637        /* 25 */ | (1u << TTHEN)
8638        /* 26 */ | (0u << TUNTIL)
8639        /* 27 */ | (0u << TWHILE)
8640        /* 28 */ | (0u << TBEGIN)
8641        /* 29 */ | (1u << TEND)
8642        , /* thus far 29 bits used */
8643};
8644
8645static const char *const tokname_array[] ALIGN_PTR = {
8646        "end of file",
8647        "newline",
8648        "redirection",
8649        "word",
8650        ";",
8651        "&",
8652        "&&",
8653        "||",
8654        "|",
8655        "(",
8656        ")",
8657        ";;",
8658        "`",
8659#define KWDOFFSET 13
8660        /* the following are keywords */
8661        "!",
8662        "case",
8663        "do",
8664        "done",
8665        "elif",
8666        "else",
8667        "esac",
8668        "fi",
8669        "for",
8670#if BASH_FUNCTION
8671        "function",
8672#endif
8673        "if",
8674        "in",
8675        "then",
8676        "until",
8677        "while",
8678        "{",
8679        "}",
8680};
8681
8682/* Wrapper around strcmp for qsort/bsearch/... */
8683static int
8684pstrcmp(const void *a, const void *b)
8685{
8686        return strcmp((char*)a, *(char**)b);
8687}
8688
8689static const char *const *
8690findkwd(const char *s)
8691{
8692        return bsearch(s, tokname_array + KWDOFFSET,
8693                        ARRAY_SIZE(tokname_array) - KWDOFFSET,
8694                        sizeof(tokname_array[0]), pstrcmp);
8695}
8696
8697/*
8698 * Locate and print what a word is...
8699 */
8700static int
8701describe_command(char *command, const char *path, int describe_command_verbose)
8702{
8703        struct cmdentry entry;
8704#if ENABLE_ASH_ALIAS
8705        const struct alias *ap;
8706#endif
8707
8708        path = path ? path : pathval();
8709
8710        if (describe_command_verbose) {
8711                out1str(command);
8712        }
8713
8714        /* First look at the keywords */
8715        if (findkwd(command)) {
8716                out1str(describe_command_verbose ? " is a shell keyword" : command);
8717                goto out;
8718        }
8719
8720#if ENABLE_ASH_ALIAS
8721        /* Then look at the aliases */
8722        ap = lookupalias(command, 0);
8723        if (ap != NULL) {
8724                if (!describe_command_verbose) {
8725                        out1str("alias ");
8726                        printalias(ap);
8727                        return 0;
8728                }
8729                out1fmt(" is an alias for %s", ap->val);
8730                goto out;
8731        }
8732#endif
8733        /* Brute force */
8734        find_command(command, &entry, DO_ABS, path);
8735
8736        switch (entry.cmdtype) {
8737        case CMDNORMAL: {
8738                int j = entry.u.index;
8739                char *p;
8740                if (j < 0) {
8741                        p = command;
8742                } else {
8743                        do {
8744                                padvance(&path, command);
8745                        } while (--j >= 0);
8746                        p = stackblock();
8747                }
8748                if (describe_command_verbose) {
8749                        out1fmt(" is %s", p);
8750                } else {
8751                        out1str(p);
8752                }
8753                break;
8754        }
8755
8756        case CMDFUNCTION:
8757                if (describe_command_verbose) {
8758                        /*out1str(" is a shell function");*/
8759                        out1str(" is a function"); /* bash says this */
8760                } else {
8761                        out1str(command);
8762                }
8763                break;
8764
8765        case CMDBUILTIN:
8766                if (describe_command_verbose) {
8767                        out1fmt(" is a %sshell builtin",
8768                                IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8769                                        "special " : nullstr
8770                        );
8771                } else {
8772                        out1str(command);
8773                }
8774                break;
8775
8776        default:
8777                if (describe_command_verbose) {
8778                        out1str(": not found\n");
8779                }
8780                return 127;
8781        }
8782 out:
8783        out1str("\n");
8784        return 0;
8785}
8786
8787static int FAST_FUNC
8788typecmd(int argc UNUSED_PARAM, char **argv)
8789{
8790        int i = 1;
8791        int err = 0;
8792        int verbose = 1;
8793
8794        /* type -p ... ? (we don't bother checking for 'p') */
8795        if (argv[1] && argv[1][0] == '-') {
8796                i++;
8797                verbose = 0;
8798        }
8799        while (argv[i]) {
8800                err |= describe_command(argv[i++], NULL, verbose);
8801        }
8802        return err;
8803}
8804
8805static struct strlist *
8806fill_arglist(struct arglist *arglist, union node **argpp)
8807{
8808        struct strlist **lastp = arglist->lastp;
8809        union node *argp;
8810
8811        while ((argp = *argpp) != NULL) {
8812                expandarg(argp, arglist, EXP_FULL | EXP_TILDE);
8813                *argpp = argp->narg.next;
8814                if (*lastp)
8815                        break;
8816        }
8817
8818        return *lastp;
8819}
8820
8821#if ENABLE_ASH_CMDCMD
8822/* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8823static int
8824parse_command_args(struct arglist *arglist, union node **argpp, const char **path)
8825{
8826        struct strlist *sp = arglist->list;
8827        char *cp, c;
8828
8829        for (;;) {
8830                sp = sp->next ? sp->next : fill_arglist(arglist, argpp);
8831                if (!sp)
8832                        return 0;
8833                cp = sp->text;
8834                if (*cp++ != '-')
8835                        break;
8836                c = *cp++;
8837                if (!c)
8838                        break;
8839                if (c == '-' && !*cp) {
8840                        if (!sp->next && !fill_arglist(arglist, argpp))
8841                                return 0;
8842                        sp = sp->next;
8843                        break;
8844                }
8845                do {
8846                        switch (c) {
8847                        case 'p':
8848                                *path = bb_default_path;
8849                                break;
8850                        default:
8851                                /* run 'typecmd' for other options */
8852                                return 0;
8853                        }
8854                        c = *cp++;
8855                } while (c);
8856        }
8857
8858        arglist->list = sp;
8859        return DO_NOFUNC;
8860}
8861
8862static int FAST_FUNC
8863commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8864{
8865        char *cmd;
8866        int c;
8867        enum {
8868                VERIFY_BRIEF = 1,
8869                VERIFY_VERBOSE = 2,
8870        } verify = 0;
8871        const char *path = NULL;
8872
8873        /* "command [-p] PROG ARGS" (that is, without -V or -v)
8874         * never reaches this function.
8875         */
8876
8877        while ((c = nextopt("pvV")) != '\0')
8878                if (c == 'V')
8879                        verify |= VERIFY_VERBOSE;
8880                else if (c == 'v')
8881                        /*verify |= VERIFY_BRIEF*/;
8882#if DEBUG
8883                else if (c != 'p')
8884                        abort();
8885#endif
8886                else
8887                        path = bb_default_path;
8888
8889        /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8890        cmd = *argptr;
8891        if (/*verify && */ cmd)
8892                return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8893
8894        return 0;
8895}
8896#endif
8897
8898
8899/*static int funcblocksize;     // size of structures in function */
8900/*static int funcstringsize;    // size of strings in node */
8901static void *funcblock;         /* block to allocate function from */
8902static char *funcstring_end;    /* end of block to allocate strings from */
8903
8904static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8905        [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8906        [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8907        [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8908        [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8909        [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8910        [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8911        [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8912        [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8913        [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8914        [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8915        [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8916        [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8917        [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8918        [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8919        [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8920        [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8921        [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8922#if BASH_REDIR_OUTPUT
8923        [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8924#endif
8925        [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8926        [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8927        [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8928        [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8929        [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8930        [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8931        [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8932        [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8933        [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8934};
8935
8936static int calcsize(int funcblocksize, union node *n);
8937
8938static int
8939sizenodelist(int funcblocksize, struct nodelist *lp)
8940{
8941        while (lp) {
8942                funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8943                funcblocksize = calcsize(funcblocksize, lp->n);
8944                lp = lp->next;
8945        }
8946        return funcblocksize;
8947}
8948
8949static int
8950calcsize(int funcblocksize, union node *n)
8951{
8952        if (n == NULL)
8953                return funcblocksize;
8954        funcblocksize += nodesize[n->type];
8955        switch (n->type) {
8956        case NCMD:
8957                funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8958                funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8959                funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8960                break;
8961        case NPIPE:
8962                funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8963                break;
8964        case NREDIR:
8965        case NBACKGND:
8966        case NSUBSHELL:
8967                funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8968                funcblocksize = calcsize(funcblocksize, n->nredir.n);
8969                break;
8970        case NAND:
8971        case NOR:
8972        case NSEMI:
8973        case NWHILE:
8974        case NUNTIL:
8975                funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8976                funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8977                break;
8978        case NIF:
8979                funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8980                funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8981                funcblocksize = calcsize(funcblocksize, n->nif.test);
8982                break;
8983        case NFOR:
8984                funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8985                funcblocksize = calcsize(funcblocksize, n->nfor.body);
8986                funcblocksize = calcsize(funcblocksize, n->nfor.args);
8987                break;
8988        case NCASE:
8989                funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8990                funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8991                break;
8992        case NCLIST:
8993                funcblocksize = calcsize(funcblocksize, n->nclist.body);
8994                funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8995                funcblocksize = calcsize(funcblocksize, n->nclist.next);
8996                break;
8997        case NDEFUN:
8998                funcblocksize = calcsize(funcblocksize, n->ndefun.body);
8999                funcblocksize += SHELL_ALIGN(strlen(n->ndefun.text) + 1);
9000                break;
9001        case NARG:
9002                funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
9003                funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
9004                funcblocksize = calcsize(funcblocksize, n->narg.next);
9005                break;
9006        case NTO:
9007#if BASH_REDIR_OUTPUT
9008        case NTO2:
9009#endif
9010        case NCLOBBER:
9011        case NFROM:
9012        case NFROMTO:
9013        case NAPPEND:
9014                funcblocksize = calcsize(funcblocksize, n->nfile.fname);
9015                funcblocksize = calcsize(funcblocksize, n->nfile.next);
9016                break;
9017        case NTOFD:
9018        case NFROMFD:
9019                funcblocksize = calcsize(funcblocksize, n->ndup.vname);
9020                funcblocksize = calcsize(funcblocksize, n->ndup.next);
9021        break;
9022        case NHERE:
9023        case NXHERE:
9024                funcblocksize = calcsize(funcblocksize, n->nhere.doc);
9025                funcblocksize = calcsize(funcblocksize, n->nhere.next);
9026                break;
9027        case NNOT:
9028                funcblocksize = calcsize(funcblocksize, n->nnot.com);
9029                break;
9030        };
9031        return funcblocksize;
9032}
9033
9034static char *
9035nodeckstrdup(char *s)
9036{
9037        funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
9038        return strcpy(funcstring_end, s);
9039}
9040
9041static union node *copynode(union node *);
9042
9043static struct nodelist *
9044copynodelist(struct nodelist *lp)
9045{
9046        struct nodelist *start;
9047        struct nodelist **lpp;
9048
9049        lpp = &start;
9050        while (lp) {
9051                *lpp = funcblock;
9052                funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
9053                (*lpp)->n = copynode(lp->n);
9054                lp = lp->next;
9055                lpp = &(*lpp)->next;
9056        }
9057        *lpp = NULL;
9058        return start;
9059}
9060
9061static union node *
9062copynode(union node *n)
9063{
9064        union node *new;
9065
9066        if (n == NULL)
9067                return NULL;
9068        new = funcblock;
9069        funcblock = (char *) funcblock + nodesize[n->type];
9070
9071        switch (n->type) {
9072        case NCMD:
9073                new->ncmd.redirect = copynode(n->ncmd.redirect);
9074                new->ncmd.args = copynode(n->ncmd.args);
9075                new->ncmd.assign = copynode(n->ncmd.assign);
9076                new->ncmd.linno = n->ncmd.linno;
9077                break;
9078        case NPIPE:
9079                new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
9080                new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
9081                break;
9082        case NREDIR:
9083        case NBACKGND:
9084        case NSUBSHELL:
9085                new->nredir.redirect = copynode(n->nredir.redirect);
9086                new->nredir.n = copynode(n->nredir.n);
9087                new->nredir.linno = n->nredir.linno;
9088                break;
9089        case NAND:
9090        case NOR:
9091        case NSEMI:
9092        case NWHILE:
9093        case NUNTIL:
9094                new->nbinary.ch2 = copynode(n->nbinary.ch2);
9095                new->nbinary.ch1 = copynode(n->nbinary.ch1);
9096                break;
9097        case NIF:
9098                new->nif.elsepart = copynode(n->nif.elsepart);
9099                new->nif.ifpart = copynode(n->nif.ifpart);
9100                new->nif.test = copynode(n->nif.test);
9101                break;
9102        case NFOR:
9103                new->nfor.var = nodeckstrdup(n->nfor.var);
9104                new->nfor.body = copynode(n->nfor.body);
9105                new->nfor.args = copynode(n->nfor.args);
9106                new->nfor.linno = n->nfor.linno;
9107                break;
9108        case NCASE:
9109                new->ncase.cases = copynode(n->ncase.cases);
9110                new->ncase.expr = copynode(n->ncase.expr);
9111                new->ncase.linno = n->ncase.linno;
9112                break;
9113        case NCLIST:
9114                new->nclist.body = copynode(n->nclist.body);
9115                new->nclist.pattern = copynode(n->nclist.pattern);
9116                new->nclist.next = copynode(n->nclist.next);
9117                break;
9118        case NDEFUN:
9119                new->ndefun.body = copynode(n->ndefun.body);
9120                new->ndefun.text = nodeckstrdup(n->ndefun.text);
9121                new->ndefun.linno = n->ndefun.linno;
9122                break;
9123        case NARG:
9124                new->narg.backquote = copynodelist(n->narg.backquote);
9125                new->narg.text = nodeckstrdup(n->narg.text);
9126                new->narg.next = copynode(n->narg.next);
9127                break;
9128        case NTO:
9129#if BASH_REDIR_OUTPUT
9130        case NTO2:
9131#endif
9132        case NCLOBBER:
9133        case NFROM:
9134        case NFROMTO:
9135        case NAPPEND:
9136                new->nfile.fname = copynode(n->nfile.fname);
9137                new->nfile.fd = n->nfile.fd;
9138                new->nfile.next = copynode(n->nfile.next);
9139                break;
9140        case NTOFD:
9141        case NFROMFD:
9142                new->ndup.vname = copynode(n->ndup.vname);
9143                new->ndup.dupfd = n->ndup.dupfd;
9144                new->ndup.fd = n->ndup.fd;
9145                new->ndup.next = copynode(n->ndup.next);
9146                break;
9147        case NHERE:
9148        case NXHERE:
9149                new->nhere.doc = copynode(n->nhere.doc);
9150                new->nhere.fd = n->nhere.fd;
9151                new->nhere.next = copynode(n->nhere.next);
9152                break;
9153        case NNOT:
9154                new->nnot.com = copynode(n->nnot.com);
9155                break;
9156        };
9157        new->type = n->type;
9158        return new;
9159}
9160
9161/*
9162 * Make a copy of a parse tree.
9163 */
9164static struct funcnode *
9165copyfunc(union node *n)
9166{
9167        struct funcnode *f;
9168        size_t blocksize;
9169
9170        /*funcstringsize = 0;*/
9171        blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
9172        f = ckzalloc(blocksize /* + funcstringsize */);
9173        funcblock = (char *) f + offsetof(struct funcnode, n);
9174        funcstring_end = (char *) f + blocksize;
9175        copynode(n);
9176        /* f->count = 0; - ckzalloc did it */
9177        return f;
9178}
9179
9180/*
9181 * Define a shell function.
9182 */
9183static void
9184defun(union node *func)
9185{
9186        struct cmdentry entry;
9187
9188        INT_OFF;
9189        entry.cmdtype = CMDFUNCTION;
9190        entry.u.func = copyfunc(func);
9191        addcmdentry(func->ndefun.text, &entry);
9192        INT_ON;
9193}
9194
9195/* Reasons for skipping commands (see comment on breakcmd routine) */
9196#define SKIPBREAK      (1 << 0)
9197#define SKIPCONT       (1 << 1)
9198#define SKIPFUNC       (1 << 2)
9199#define SKIPFUNCDEF    (1 << 3)
9200static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
9201static int skipcount;           /* number of levels to skip */
9202static int loopnest;            /* current loop nesting level */
9203static int funcline;            /* starting line number of current function, or 0 if not in a function */
9204
9205/* Forward decl way out to parsing code - dotrap needs it */
9206static int evalstring(char *s, int flags);
9207
9208/* Called to execute a trap.
9209 * Single callsite - at the end of evaltree().
9210 * If we return non-zero, evaltree raises EXEXIT exception.
9211 *
9212 * Perhaps we should avoid entering new trap handlers
9213 * while we are executing a trap handler. [is it a TODO?]
9214 */
9215static void
9216dotrap(void)
9217{
9218        uint8_t *g;
9219        int sig;
9220        int status, last_status;
9221
9222        if (!pending_sig)
9223                return;
9224
9225        status = savestatus;
9226        last_status = status;
9227        if (status < 0) {
9228                status = exitstatus;
9229                savestatus = status;
9230        }
9231        pending_sig = 0;
9232        barrier();
9233
9234        TRACE(("dotrap entered\n"));
9235        for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
9236                char *p;
9237
9238                if (!*g)
9239                        continue;
9240
9241                if (evalskip) {
9242                        pending_sig = sig;
9243                        break;
9244                }
9245
9246                p = trap[sig];
9247                /* non-trapped SIGINT is handled separately by raise_interrupt,
9248                 * don't upset it by resetting gotsig[SIGINT-1] */
9249                if (sig == SIGINT && !p)
9250                        continue;
9251
9252                TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
9253                *g = 0;
9254                if (!p)
9255                        continue;
9256                evalstring(p, 0);
9257                if (evalskip != SKIPFUNC)
9258                        exitstatus = status;
9259        }
9260
9261        savestatus = last_status;
9262        TRACE(("dotrap returns\n"));
9263}
9264
9265/* forward declarations - evaluation is fairly recursive business... */
9266static int evalloop(union node *, int);
9267static int evalfor(union node *, int);
9268static int evalcase(union node *, int);
9269static int evalsubshell(union node *, int);
9270static void expredir(union node *);
9271static int evalpipe(union node *, int);
9272static int evalcommand(union node *, int);
9273static int evalbltin(const struct builtincmd *, int, char **, int);
9274static void prehash(union node *);
9275
9276/*
9277 * Evaluate a parse tree.  The value is left in the global variable
9278 * exitstatus.
9279 */
9280static int
9281evaltree(union node *n, int flags)
9282{
9283        int checkexit = 0;
9284        int (*evalfn)(union node *, int);
9285        struct stackmark smark;
9286        int status = 0;
9287
9288        setstackmark(&smark);
9289
9290        if (n == NULL) {
9291                TRACE(("evaltree(NULL) called\n"));
9292                goto out;
9293        }
9294        TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
9295
9296        dotrap();
9297
9298        switch (n->type) {
9299        default:
9300#if DEBUG
9301                out1fmt("Node type = %d\n", n->type);
9302                fflush_all();
9303                break;
9304#endif
9305        case NNOT:
9306                status = !evaltree(n->nnot.com, EV_TESTED);
9307                goto setstatus;
9308        case NREDIR:
9309                errlinno = lineno = n->nredir.linno;
9310                if (funcline)
9311                        lineno -= funcline - 1;
9312                expredir(n->nredir.redirect);
9313                pushredir(n->nredir.redirect);
9314                status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
9315                if (!status) {
9316                        status = evaltree(n->nredir.n, flags & EV_TESTED);
9317                }
9318                if (n->nredir.redirect)
9319                        popredir(/*drop:*/ 0);
9320                goto setstatus;
9321        case NCMD:
9322                evalfn = evalcommand;
9323 checkexit:
9324                if (eflag && !(flags & EV_TESTED))
9325                        checkexit = ~0;
9326                goto calleval;
9327        case NFOR:
9328                evalfn = evalfor;
9329                goto calleval;
9330        case NWHILE:
9331        case NUNTIL:
9332                evalfn = evalloop;
9333                goto calleval;
9334        case NSUBSHELL:
9335        case NBACKGND:
9336                evalfn = evalsubshell;
9337                goto checkexit;
9338        case NPIPE:
9339                evalfn = evalpipe;
9340                goto checkexit;
9341        case NCASE:
9342                evalfn = evalcase;
9343                goto calleval;
9344        case NAND:
9345        case NOR:
9346        case NSEMI: {
9347
9348#if NAND + 1 != NOR
9349#error NAND + 1 != NOR
9350#endif
9351#if NOR + 1 != NSEMI
9352#error NOR + 1 != NSEMI
9353#endif
9354                unsigned is_or = n->type - NAND;
9355                status = evaltree(
9356                        n->nbinary.ch1,
9357                        (flags | ((is_or >> 1) - 1)) & EV_TESTED
9358                );
9359                if ((!status) == is_or || evalskip)
9360                        break;
9361                n = n->nbinary.ch2;
9362 evaln:
9363                evalfn = evaltree;
9364 calleval:
9365                status = evalfn(n, flags);
9366                goto setstatus;
9367        }
9368        case NIF:
9369                status = evaltree(n->nif.test, EV_TESTED);
9370                if (evalskip)
9371                        break;
9372                if (!status) {
9373                        n = n->nif.ifpart;
9374                        goto evaln;
9375                }
9376                if (n->nif.elsepart) {
9377                        n = n->nif.elsepart;
9378                        goto evaln;
9379                }
9380                status = 0;
9381                goto setstatus;
9382        case NDEFUN:
9383                defun(n);
9384                /* Not necessary. To test it:
9385                 * "false; f() { qwerty; }; echo $?" should print 0.
9386                 */
9387                /* status = 0; */
9388 setstatus:
9389                exitstatus = status;
9390                break;
9391        }
9392 out:
9393        /* Order of checks below is important:
9394         * signal handlers trigger before exit caused by "set -e".
9395         */
9396        dotrap();
9397
9398        if (checkexit & status)
9399                raise_exception(EXEND);
9400        if (flags & EV_EXIT)
9401                raise_exception(EXEND);
9402
9403        popstackmark(&smark);
9404        TRACE(("leaving evaltree (no interrupts)\n"));
9405        return exitstatus;
9406}
9407
9408static int
9409skiploop(void)
9410{
9411        int skip = evalskip;
9412
9413        switch (skip) {
9414        case 0:
9415                break;
9416        case SKIPBREAK:
9417        case SKIPCONT:
9418                if (--skipcount <= 0) {
9419                        evalskip = 0;
9420                        break;
9421                }
9422                skip = SKIPBREAK;
9423                break;
9424        }
9425        return skip;
9426}
9427
9428static int
9429evalloop(union node *n, int flags)
9430{
9431        int skip;
9432        int status;
9433
9434        loopnest++;
9435        status = 0;
9436        flags &= EV_TESTED;
9437        do {
9438                int i;
9439
9440                i = evaltree(n->nbinary.ch1, EV_TESTED);
9441                skip = skiploop();
9442                if (skip == SKIPFUNC)
9443                        status = i;
9444                if (skip)
9445                        continue;
9446                if (n->type != NWHILE)
9447                        i = !i;
9448                if (i != 0)
9449                        break;
9450                status = evaltree(n->nbinary.ch2, flags);
9451                skip = skiploop();
9452        } while (!(skip & ~SKIPCONT));
9453        loopnest--;
9454
9455        return status;
9456}
9457
9458static int
9459evalfor(union node *n, int flags)
9460{
9461        struct arglist arglist;
9462        union node *argp;
9463        struct strlist *sp;
9464        int status = 0;
9465
9466        errlinno = lineno = n->ncase.linno;
9467        if (funcline)
9468                lineno -= funcline - 1;
9469
9470        arglist.list = NULL;
9471        arglist.lastp = &arglist.list;
9472        for (argp = n->nfor.args; argp; argp = argp->narg.next) {
9473                expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9474        }
9475        *arglist.lastp = NULL;
9476
9477        loopnest++;
9478        flags &= EV_TESTED;
9479        for (sp = arglist.list; sp; sp = sp->next) {
9480                setvar0(n->nfor.var, sp->text);
9481                status = evaltree(n->nfor.body, flags);
9482                if (skiploop() & ~SKIPCONT)
9483                        break;
9484        }
9485        loopnest--;
9486
9487        return status;
9488}
9489
9490static int
9491evalcase(union node *n, int flags)
9492{
9493        union node *cp;
9494        union node *patp;
9495        struct arglist arglist;
9496        int status = 0;
9497
9498        errlinno = lineno = n->ncase.linno;
9499        if (funcline)
9500                lineno -= funcline - 1;
9501
9502        arglist.list = NULL;
9503        arglist.lastp = &arglist.list;
9504        expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9505        for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9506                for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9507                        if (casematch(patp, arglist.list->text)) {
9508                                /* Ensure body is non-empty as otherwise
9509                                 * EV_EXIT may prevent us from setting the
9510                                 * exit status.
9511                                 */
9512                                if (evalskip == 0 && cp->nclist.body) {
9513                                        status = evaltree(cp->nclist.body, flags);
9514                                }
9515                                goto out;
9516                        }
9517                }
9518        }
9519 out:
9520        return status;
9521}
9522
9523/*
9524 * Kick off a subshell to evaluate a tree.
9525 */
9526static int
9527evalsubshell(union node *n, int flags)
9528{
9529        struct job *jp;
9530        int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9531        int status;
9532
9533        errlinno = lineno = n->nredir.linno;
9534        if (funcline)
9535                lineno -= funcline - 1;
9536
9537        expredir(n->nredir.redirect);
9538        if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9539                goto nofork;
9540        INT_OFF;
9541        if (backgnd == FORK_FG)
9542                get_tty_state();
9543        jp = makejob(/*n,*/ 1);
9544        if (forkshell(jp, n, backgnd) == 0) {
9545                /* child */
9546                INT_ON;
9547                flags |= EV_EXIT;
9548                if (backgnd)
9549                        flags &= ~EV_TESTED;
9550 nofork:
9551                redirect(n->nredir.redirect, 0);
9552                evaltreenr(n->nredir.n, flags);
9553                /* never returns */
9554        }
9555        /* parent */
9556        status = 0;
9557        if (backgnd == FORK_FG)
9558                status = waitforjob(jp);
9559        INT_ON;
9560        return status;
9561}
9562
9563/*
9564 * Compute the names of the files in a redirection list.
9565 */
9566static void fixredir(union node *, const char *, int);
9567static void
9568expredir(union node *n)
9569{
9570        union node *redir;
9571
9572        for (redir = n; redir; redir = redir->nfile.next) {
9573                struct arglist fn;
9574
9575                fn.list = NULL;
9576                fn.lastp = &fn.list;
9577                switch (redir->type) {
9578                case NFROMTO:
9579                case NFROM:
9580                case NTO:
9581#if BASH_REDIR_OUTPUT
9582                case NTO2:
9583#endif
9584                case NCLOBBER:
9585                case NAPPEND:
9586                        expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9587                        TRACE(("expredir expanded to '%s'\n", fn.list->text));
9588#if BASH_REDIR_OUTPUT
9589 store_expfname:
9590#endif
9591#if 0
9592// By the design of stack allocator, the loop of this kind:
9593//      while true; do while true; do break; done </dev/null; done
9594// will look like a memory leak: ash plans to free expfname's
9595// of "/dev/null" as soon as it finishes running the loop
9596// (in this case, never).
9597// This "fix" is wrong:
9598                        if (redir->nfile.expfname)
9599                                stunalloc(redir->nfile.expfname);
9600// It results in corrupted state of stacked allocations.
9601#endif
9602                        redir->nfile.expfname = fn.list->text;
9603                        break;
9604                case NFROMFD:
9605                case NTOFD: /* >& */
9606                        if (redir->ndup.vname) {
9607                                expandarg(redir->ndup.vname, &fn, EXP_TILDE | EXP_REDIR);
9608                                if (fn.list == NULL)
9609                                        ash_msg_and_raise_error("redir error");
9610#if BASH_REDIR_OUTPUT
9611                                if (!isdigit_str9(fn.list->text)) {
9612                                        /* >&file, not >&fd */
9613                                        if (redir->nfile.fd != 1) /* 123>&file - BAD */
9614                                                ash_msg_and_raise_error("redir error");
9615                                        redir->type = NTO2;
9616                                        goto store_expfname;
9617                                }
9618#endif
9619                                fixredir(redir, fn.list->text, 1);
9620                        }
9621                        break;
9622                }
9623        }
9624}
9625
9626/*
9627 * Evaluate a pipeline.  All the processes in the pipeline are children
9628 * of the process creating the pipeline.  (This differs from some versions
9629 * of the shell, which make the last process in a pipeline the parent
9630 * of all the rest.)
9631 */
9632static int
9633evalpipe(union node *n, int flags)
9634{
9635        struct job *jp;
9636        struct nodelist *lp;
9637        int pipelen;
9638        int prevfd;
9639        int pip[2];
9640        int status = 0;
9641
9642        TRACE(("evalpipe(0x%lx) called\n", (long)n));
9643        pipelen = 0;
9644        for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9645                pipelen++;
9646        flags |= EV_EXIT;
9647        INT_OFF;
9648        if (n->npipe.pipe_backgnd == 0)
9649                get_tty_state();
9650        jp = makejob(/*n,*/ pipelen);
9651        prevfd = -1;
9652        for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9653                prehash(lp->n);
9654                pip[1] = -1;
9655                if (lp->next) {
9656                        if (pipe(pip) < 0) {
9657                                close(prevfd);
9658                                ash_msg_and_raise_perror("can't create pipe");
9659                        }
9660                }
9661                if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9662                        /* child */
9663                        INT_ON;
9664                        if (pip[1] >= 0) {
9665                                close(pip[0]);
9666                        }
9667                        if (prevfd > 0) {
9668                                dup2(prevfd, 0);
9669                                close(prevfd);
9670                        }
9671                        if (pip[1] > 1) {
9672                                dup2(pip[1], 1);
9673                                close(pip[1]);
9674                        }
9675                        evaltreenr(lp->n, flags);
9676                        /* never returns */
9677                }
9678                /* parent */
9679                if (prevfd >= 0)
9680                        close(prevfd);
9681                prevfd = pip[0];
9682                /* Don't want to trigger debugging */
9683                if (pip[1] != -1)
9684                        close(pip[1]);
9685        }
9686        if (n->npipe.pipe_backgnd == 0) {
9687                status = waitforjob(jp);
9688                TRACE(("evalpipe:  job done exit status %d\n", status));
9689        }
9690        INT_ON;
9691
9692        return status;
9693}
9694
9695/* setinteractive needs this forward reference */
9696#if EDITING_HAS_get_exe_name
9697static const char *get_builtin_name(int i) FAST_FUNC;
9698#endif
9699
9700/*
9701 * Controls whether the shell is interactive or not.
9702 */
9703static void
9704setinteractive(int on)
9705{
9706        static smallint is_interactive;
9707
9708        if (++on == is_interactive)
9709                return;
9710        is_interactive = on;
9711        setsignal(SIGINT);
9712        setsignal(SIGQUIT);
9713        setsignal(SIGTERM);
9714        if (is_interactive > 1) {
9715#if !ENABLE_FEATURE_SH_EXTRA_QUIET
9716                /* Looks like they want an interactive shell */
9717                static smallint did_banner;
9718
9719                if (!did_banner) {
9720                        /* note: ash and hush share this string */
9721                        out1fmt("\n\n%s %s\n"
9722                                IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9723                                "\n",
9724                                bb_banner,
9725                                "built-in shell (ash)"
9726                        );
9727                        did_banner = 1;
9728                }
9729#endif
9730#if ENABLE_FEATURE_EDITING
9731                if (!line_input_state) {
9732                        line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
9733# if EDITING_HAS_get_exe_name
9734                        line_input_state->get_exe_name = get_builtin_name;
9735# endif
9736                }
9737#endif
9738        }
9739}
9740
9741static void
9742optschanged(void)
9743{
9744#if DEBUG
9745        opentrace();
9746#endif
9747        setinteractive(iflag);
9748        setjobctl(mflag);
9749#if ENABLE_FEATURE_EDITING_VI
9750        if (line_input_state) {
9751                if (viflag)
9752                        line_input_state->flags |= VI_MODE;
9753                else
9754                        line_input_state->flags &= ~VI_MODE;
9755        }
9756#else
9757        viflag = 0; /* forcibly keep the option off */
9758#endif
9759}
9760
9761struct localvar_list {
9762        struct localvar_list *next;
9763        struct localvar *lv;
9764};
9765
9766static struct localvar_list *localvar_stack;
9767
9768/*
9769 * Called after a function returns.
9770 * Interrupts must be off.
9771 */
9772static void
9773poplocalvars(int keep)
9774{
9775        struct localvar_list *ll;
9776        struct localvar *lvp, *next;
9777        struct var *vp;
9778
9779        INT_OFF;
9780        ll = localvar_stack;
9781        localvar_stack = ll->next;
9782
9783        next = ll->lv;
9784        free(ll);
9785
9786        while ((lvp = next) != NULL) {
9787                next = lvp->next;
9788                vp = lvp->vp;
9789                TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9790                if (keep) {
9791                        int bits = VSTRFIXED;
9792
9793                        if (lvp->flags != VUNSET) {
9794                                if (vp->var_text == lvp->text)
9795                                        bits |= VTEXTFIXED;
9796                                else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9797                                        free((char*)lvp->text);
9798                        }
9799
9800                        vp->flags &= ~bits;
9801                        vp->flags |= (lvp->flags & bits);
9802
9803                        if ((vp->flags &
9804                             (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9805                                unsetvar(vp->var_text);
9806                } else if (vp == NULL) {        /* $- saved */
9807                        memcpy(optlist, lvp->text, sizeof(optlist));
9808                        free((char*)lvp->text);
9809                        optschanged();
9810                } else if (lvp->flags == VUNSET) {
9811                        vp->flags &= ~(VSTRFIXED|VREADONLY);
9812                        unsetvar(vp->var_text);
9813                } else {
9814                        if (vp->var_func)
9815                                vp->var_func(var_end(lvp->text));
9816                        if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9817                                free((char*)vp->var_text);
9818                        vp->flags = lvp->flags;
9819                        vp->var_text = lvp->text;
9820                }
9821                free(lvp);
9822        }
9823        INT_ON;
9824}
9825
9826/*
9827 * Create a new localvar environment.
9828 */
9829static struct localvar_list *
9830pushlocalvars(int push)
9831{
9832        struct localvar_list *ll;
9833        struct localvar_list *top;
9834
9835        top = localvar_stack;
9836        if (!push)
9837                goto out;
9838
9839        INT_OFF;
9840        ll = ckzalloc(sizeof(*ll));
9841        /*ll->lv = NULL; - zalloc did it */
9842        ll->next = top;
9843        localvar_stack = ll;
9844        INT_ON;
9845 out:
9846        return top;
9847}
9848
9849static void
9850unwindlocalvars(struct localvar_list *stop)
9851{
9852        while (localvar_stack != stop)
9853                poplocalvars(0);
9854}
9855
9856static int
9857evalfun(struct funcnode *func, int argc, char **argv, int flags)
9858{
9859        volatile struct shparam saveparam;
9860        struct jmploc *volatile savehandler;
9861        struct jmploc jmploc;
9862        int e;
9863        int savefuncline;
9864
9865        saveparam = shellparam;
9866        savefuncline = funcline;
9867        savehandler = exception_handler;
9868        e = setjmp(jmploc.loc);
9869        if (e) {
9870                goto funcdone;
9871        }
9872        INT_OFF;
9873        exception_handler = &jmploc;
9874        shellparam.malloced = 0;
9875        func->count++;
9876        funcline = func->n.ndefun.linno;
9877        INT_ON;
9878        shellparam.nparam = argc - 1;
9879        shellparam.p = argv + 1;
9880#if ENABLE_ASH_GETOPTS
9881        shellparam.optind = 1;
9882        shellparam.optoff = -1;
9883#endif
9884        evaltree(func->n.ndefun.body, flags & EV_TESTED);
9885 funcdone:
9886        INT_OFF;
9887        funcline = savefuncline;
9888        freefunc(func);
9889        freeparam(&shellparam);
9890        shellparam = saveparam;
9891        exception_handler = savehandler;
9892        INT_ON;
9893        evalskip &= ~(SKIPFUNC | SKIPFUNCDEF);
9894        return e;
9895}
9896
9897/*
9898 * Make a variable a local variable.  When a variable is made local, it's
9899 * value and flags are saved in a localvar structure.  The saved values
9900 * will be restored when the shell function returns.  We handle the name
9901 * "-" as a special case: it makes changes to "set +-options" local
9902 * (options will be restored on return from the function).
9903 */
9904static void
9905mklocal(char *name, int flags)
9906{
9907        struct localvar *lvp;
9908        struct var **vpp;
9909        struct var *vp;
9910        char *eq = strchr(name, '=');
9911
9912        INT_OFF;
9913        /* Cater for duplicate "local". Examples:
9914         * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9915         * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9916         */
9917        lvp = localvar_stack->lv;
9918        while (lvp) {
9919                if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9920                        if (eq)
9921                                setvareq(name, 0);
9922                        /* else:
9923                         * it's a duplicate "local VAR" declaration, do nothing
9924                         */
9925                        goto ret;
9926                }
9927                lvp = lvp->next;
9928        }
9929
9930        lvp = ckzalloc(sizeof(*lvp));
9931        if (LONE_DASH(name)) {
9932                char *p;
9933                p = ckmalloc(sizeof(optlist));
9934                lvp->text = memcpy(p, optlist, sizeof(optlist));
9935                vp = NULL;
9936        } else {
9937                vpp = hashvar(name);
9938                vp = *findvar(vpp, name);
9939                if (vp == NULL) {
9940                        /* variable did not exist yet */
9941                        if (eq)
9942                                vp = setvareq(name, VSTRFIXED | flags);
9943                        else
9944                                vp = setvar(name, NULL, VSTRFIXED | flags);
9945                        lvp->flags = VUNSET;
9946                } else {
9947                        lvp->text = vp->var_text;
9948                        lvp->flags = vp->flags;
9949                        /* make sure neither "struct var" nor string gets freed
9950                         * during (un)setting:
9951                         */
9952                        vp->flags |= VSTRFIXED|VTEXTFIXED;
9953                        if (eq)
9954                                setvareq(name, flags);
9955                        else
9956                                /* "local VAR" unsets VAR: */
9957                                setvar0(name, NULL);
9958                }
9959        }
9960        lvp->vp = vp;
9961        lvp->next = localvar_stack->lv;
9962        localvar_stack->lv = lvp;
9963 ret:
9964        INT_ON;
9965}
9966
9967/*
9968 * The "local" command.
9969 */
9970static int FAST_FUNC
9971localcmd(int argc UNUSED_PARAM, char **argv)
9972{
9973        char *name;
9974
9975        if (!localvar_stack)
9976                ash_msg_and_raise_error("not in a function");
9977
9978        argv = argptr;
9979        while ((name = *argv++) != NULL) {
9980                mklocal(name, 0);
9981        }
9982        return 0;
9983}
9984
9985static int FAST_FUNC
9986falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9987{
9988        return 1;
9989}
9990
9991static int FAST_FUNC
9992truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9993{
9994        return 0;
9995}
9996
9997static int FAST_FUNC
9998execcmd(int argc UNUSED_PARAM, char **argv)
9999{
10000        optionarg = NULL;
10001        while (nextopt("a:") != '\0')
10002                /* nextopt() sets optionarg to "-a ARGV0" */;
10003
10004        argv = argptr;
10005        if (argv[0]) {
10006                char *prog;
10007
10008                iflag = 0;              /* exit on error */
10009                mflag = 0;
10010                optschanged();
10011                /* We should set up signals for "exec CMD"
10012                 * the same way as for "CMD" without "exec".
10013                 * But optschanged->setinteractive->setsignal
10014                 * still thought we are a root shell. Therefore, for example,
10015                 * SIGQUIT is still set to IGN. Fix it:
10016                 */
10017                shlvl++;
10018                setsignal(SIGQUIT);
10019                /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
10020                /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
10021                /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
10022
10023                prog = argv[0];
10024                if (optionarg)
10025                        argv[0] = optionarg;
10026                shellexec(prog, argv, pathval(), 0);
10027                /* NOTREACHED */
10028        }
10029        return 0;
10030}
10031
10032/*
10033 * The return command.
10034 */
10035static int FAST_FUNC
10036returncmd(int argc UNUSED_PARAM, char **argv)
10037{
10038        int skip;
10039        int status;
10040
10041        /*
10042         * If called outside a function, do what ksh does;
10043         * skip the rest of the file.
10044         */
10045        if (argv[1]) {
10046                skip = SKIPFUNC;
10047                status = number(argv[1]);
10048        } else {
10049                skip = SKIPFUNCDEF;
10050                status = exitstatus;
10051        }
10052        evalskip = skip;
10053
10054        return status;
10055}
10056
10057/* Forward declarations for builtintab[] */
10058static int breakcmd(int, char **) FAST_FUNC;
10059static int dotcmd(int, char **) FAST_FUNC;
10060static int evalcmd(int, char **, int) FAST_FUNC;
10061static int exitcmd(int, char **) FAST_FUNC;
10062static int exportcmd(int, char **) FAST_FUNC;
10063#if ENABLE_ASH_GETOPTS
10064static int getoptscmd(int, char **) FAST_FUNC;
10065#endif
10066#if ENABLE_ASH_HELP
10067static int helpcmd(int, char **) FAST_FUNC;
10068#endif
10069#if MAX_HISTORY
10070static int historycmd(int, char **) FAST_FUNC;
10071#endif
10072#if ENABLE_FEATURE_SH_MATH
10073static int letcmd(int, char **) FAST_FUNC;
10074#endif
10075static int readcmd(int, char **) FAST_FUNC;
10076static int setcmd(int, char **) FAST_FUNC;
10077static int shiftcmd(int, char **) FAST_FUNC;
10078static int timescmd(int, char **) FAST_FUNC;
10079static int trapcmd(int, char **) FAST_FUNC;
10080static int umaskcmd(int, char **) FAST_FUNC;
10081static int unsetcmd(int, char **) FAST_FUNC;
10082static int ulimitcmd(int, char **) FAST_FUNC;
10083
10084#define BUILTIN_NOSPEC          "0"
10085#define BUILTIN_SPECIAL         "1"
10086#define BUILTIN_REGULAR         "2"
10087#define BUILTIN_SPEC_REG        "3"
10088#define BUILTIN_ASSIGN          "4"
10089#define BUILTIN_SPEC_ASSG       "5"
10090#define BUILTIN_REG_ASSG        "6"
10091#define BUILTIN_SPEC_REG_ASSG   "7"
10092
10093/* Stubs for calling non-FAST_FUNC's */
10094#if ENABLE_ASH_ECHO
10095static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
10096#endif
10097#if ENABLE_ASH_PRINTF
10098static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
10099#endif
10100#if ENABLE_ASH_TEST || BASH_TEST2
10101static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
10102#endif
10103
10104/* Keep these in proper order since it is searched via bsearch() */
10105static const struct builtincmd builtintab[] = {
10106        { BUILTIN_SPEC_REG      "."       , dotcmd     },
10107        { BUILTIN_SPEC_REG      ":"       , truecmd    },
10108#if ENABLE_ASH_TEST
10109        { BUILTIN_REGULAR       "["       , testcmd    },
10110#endif
10111#if BASH_TEST2
10112        { BUILTIN_REGULAR       "[["      , testcmd    },
10113#endif
10114#if ENABLE_ASH_ALIAS
10115        { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
10116#endif
10117#if JOBS
10118        { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
10119#endif
10120        { BUILTIN_SPEC_REG      "break"   , breakcmd   },
10121        { BUILTIN_REGULAR       "cd"      , cdcmd      },
10122        { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
10123#if ENABLE_ASH_CMDCMD
10124        { BUILTIN_REGULAR       "command" , commandcmd },
10125#endif
10126        { BUILTIN_SPEC_REG      "continue", breakcmd   },
10127#if ENABLE_ASH_ECHO
10128        { BUILTIN_REGULAR       "echo"    , echocmd    },
10129#endif
10130        { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
10131        { BUILTIN_SPEC_REG      "exec"    , execcmd    },
10132        { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
10133        { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
10134        { BUILTIN_REGULAR       "false"   , falsecmd   },
10135#if JOBS
10136        { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
10137#endif
10138#if ENABLE_ASH_GETOPTS
10139        { BUILTIN_REGULAR       "getopts" , getoptscmd },
10140#endif
10141        { BUILTIN_REGULAR       "hash"    , hashcmd    },
10142#if ENABLE_ASH_HELP
10143        { BUILTIN_NOSPEC        "help"    , helpcmd    },
10144#endif
10145#if MAX_HISTORY
10146        { BUILTIN_NOSPEC        "history" , historycmd },
10147#endif
10148#if JOBS
10149        { BUILTIN_REGULAR       "jobs"    , jobscmd    },
10150        { BUILTIN_REGULAR       "kill"    , killcmd    },
10151#endif
10152#if ENABLE_FEATURE_SH_MATH
10153        { BUILTIN_NOSPEC        "let"     , letcmd     },
10154#endif
10155        { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
10156#if ENABLE_ASH_PRINTF
10157        { BUILTIN_REGULAR       "printf"  , printfcmd  },
10158#endif
10159        { BUILTIN_REGULAR       "pwd"     , pwdcmd     },
10160        { BUILTIN_REGULAR       "read"    , readcmd    },
10161        { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
10162        { BUILTIN_SPEC_REG      "return"  , returncmd  },
10163        { BUILTIN_SPEC_REG      "set"     , setcmd     },
10164        { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
10165#if BASH_SOURCE
10166        { BUILTIN_SPEC_REG      "source"  , dotcmd     },
10167#endif
10168#if ENABLE_ASH_TEST
10169        { BUILTIN_REGULAR       "test"    , testcmd    },
10170#endif
10171        { BUILTIN_SPEC_REG      "times"   , timescmd   },
10172        { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
10173        { BUILTIN_REGULAR       "true"    , truecmd    },
10174        { BUILTIN_REGULAR       "type"    , typecmd    },
10175        { BUILTIN_REGULAR       "ulimit"  , ulimitcmd  },
10176        { BUILTIN_REGULAR       "umask"   , umaskcmd   },
10177#if ENABLE_ASH_ALIAS
10178        { BUILTIN_REGULAR       "unalias" , unaliascmd },
10179#endif
10180        { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
10181        { BUILTIN_REGULAR       "wait"    , waitcmd    },
10182};
10183
10184/* Should match the above table! */
10185#define COMMANDCMD (builtintab + \
10186        /* . : */       2 + \
10187        /* [ */         1 * ENABLE_ASH_TEST + \
10188        /* [[ */        1 * BASH_TEST2 + \
10189        /* alias */     1 * ENABLE_ASH_ALIAS + \
10190        /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
10191        /* break cd cddir  */   3)
10192#define EVALCMD (COMMANDCMD + \
10193        /* command */   1 * ENABLE_ASH_CMDCMD + \
10194        /* continue */  1 + \
10195        /* echo */      1 * ENABLE_ASH_ECHO + \
10196        0)
10197#define EXECCMD (EVALCMD + \
10198        /* eval */      1)
10199
10200/*
10201 * Search the table of builtin commands.
10202 */
10203static int
10204pstrcmp1(const void *a, const void *b)
10205{
10206        return strcmp((char*)a, *(char**)b + 1);
10207}
10208static struct builtincmd *
10209find_builtin(const char *name)
10210{
10211        struct builtincmd *bp;
10212
10213        bp = bsearch(
10214                name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
10215                pstrcmp1
10216        );
10217        return bp;
10218}
10219
10220#if EDITING_HAS_get_exe_name
10221static const char * FAST_FUNC
10222get_builtin_name(int i)
10223{
10224        return /*i >= 0 &&*/ i < ARRAY_SIZE(builtintab) ? builtintab[i].name + 1 : NULL;
10225}
10226#endif
10227
10228/*
10229 * Execute a simple command.
10230 */
10231static void unwindfiles(struct parsefile *stop);
10232static int
10233isassignment(const char *p)
10234{
10235        const char *q = endofname(p);
10236        if (p == q)
10237                return 0;
10238        return *q == '=';
10239}
10240static int FAST_FUNC
10241bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10242{
10243        /* Preserve exitstatus of a previous possible redirection
10244         * as POSIX mandates */
10245        return back_exitstatus;
10246}
10247static int
10248evalcommand(union node *cmd, int flags)
10249{
10250        static const struct builtincmd null_bltin = {
10251                BUILTIN_REGULAR "", bltincmd
10252        };
10253        struct localvar_list *localvar_stop;
10254        struct parsefile *file_stop;
10255        struct redirtab *redir_stop;
10256        union node *argp;
10257        struct arglist arglist;
10258        struct arglist varlist;
10259        char **argv;
10260        int argc;
10261        struct strlist *osp;
10262        const struct strlist *sp;
10263        struct cmdentry cmdentry;
10264        struct job *jp;
10265        char *lastarg;
10266        const char *path;
10267        int spclbltin;
10268        int cmd_flag;
10269        int status;
10270        char **nargv;
10271        smallint cmd_is_exec;
10272        int vflags;
10273        int vlocal;
10274
10275        errlinno = lineno = cmd->ncmd.linno;
10276        if (funcline)
10277                lineno -= funcline - 1;
10278
10279        /* First expand the arguments. */
10280        TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
10281#if BASH_PROCESS_SUBST
10282        redir_stop = redirlist;
10283#endif
10284        file_stop = g_parsefile;
10285        back_exitstatus = 0;
10286
10287        cmdentry.cmdtype = CMDBUILTIN;
10288        cmdentry.u.cmd = &null_bltin;
10289        varlist.lastp = &varlist.list;
10290        *varlist.lastp = NULL;
10291        arglist.lastp = &arglist.list;
10292        *arglist.lastp = NULL;
10293
10294        cmd_flag = 0;
10295        cmd_is_exec = 0;
10296        spclbltin = -1;
10297        vflags = 0;
10298        vlocal = 0;
10299        path = NULL;
10300
10301        argc = 0;
10302        argp = cmd->ncmd.args;
10303        osp = fill_arglist(&arglist, &argp);
10304        if (osp) {
10305                int pseudovarflag = 0;
10306
10307                for (;;) {
10308                        find_command(arglist.list->text, &cmdentry,
10309                                        cmd_flag | DO_REGBLTIN, pathval());
10310
10311                        vlocal++;
10312
10313                        /* implement bltin and command here */
10314                        if (cmdentry.cmdtype != CMDBUILTIN)
10315                                break;
10316
10317                        pseudovarflag = IS_BUILTIN_ASSIGN(cmdentry.u.cmd);
10318                        if (spclbltin < 0) {
10319                                spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
10320                                vlocal = !spclbltin;
10321                        }
10322                        cmd_is_exec = cmdentry.u.cmd == EXECCMD;
10323#if ENABLE_ASH_CMDCMD
10324                        if (cmdentry.u.cmd != COMMANDCMD)
10325                                break;
10326
10327                        cmd_flag = parse_command_args(&arglist, &argp, &path);
10328                        if (!cmd_flag)
10329#endif
10330                                break;
10331                }
10332
10333                for (; argp; argp = argp->narg.next)
10334                        expandarg(argp, &arglist,
10335                                        pseudovarflag &&
10336                                        isassignment(argp->narg.text) ?
10337                                        EXP_VARTILDE : EXP_FULL | EXP_TILDE);
10338
10339                for (sp = arglist.list; sp; sp = sp->next)
10340                        argc++;
10341
10342                if (cmd_is_exec && argc > 1)
10343                        vflags = VEXPORT;
10344        }
10345
10346        localvar_stop = pushlocalvars(vlocal);
10347
10348        /* Reserve one extra spot at the front for shellexec. */
10349        nargv = stalloc(sizeof(char *) * (argc + 2));
10350        argv = ++nargv;
10351        for (sp = arglist.list; sp; sp = sp->next) {
10352                TRACE(("evalcommand arg: %s\n", sp->text));
10353                *nargv++ = sp->text;
10354        }
10355        *nargv = NULL;
10356
10357        lastarg = NULL;
10358        if (iflag && funcline == 0 && argc > 0)
10359                lastarg = nargv[-1];
10360
10361        expredir(cmd->ncmd.redirect);
10362#if !BASH_PROCESS_SUBST
10363        redir_stop = pushredir(cmd->ncmd.redirect);
10364#else
10365        pushredir(cmd->ncmd.redirect);
10366#endif
10367        preverrout_fd = 2;
10368        if (BASH_XTRACEFD && xflag) {
10369                /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
10370                 * we do not emulate this. We only use its value.
10371                 */
10372                const char *xtracefd = lookupvar("BASH_XTRACEFD");
10373                if (xtracefd && is_number(xtracefd))
10374                        preverrout_fd = atoi(xtracefd);
10375
10376        }
10377        status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
10378
10379        if (status) {
10380 bail:
10381                exitstatus = status;
10382
10383                /* We have a redirection error. */
10384                if (spclbltin > 0)
10385                        raise_exception(EXERROR);
10386
10387                goto out;
10388        }
10389
10390        for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
10391                struct strlist **spp;
10392
10393                spp = varlist.lastp;
10394                expandarg(argp, &varlist, EXP_VARTILDE);
10395
10396                if (vlocal)
10397                        mklocal((*spp)->text, VEXPORT);
10398                else
10399                        setvareq((*spp)->text, vflags);
10400        }
10401
10402        /* Print the command if xflag is set. */
10403        if (xflag) {
10404                const char *pfx = "";
10405
10406                fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
10407
10408                sp = varlist.list;
10409                while (sp) {
10410                        char *varval = sp->text;
10411                        char *eq = strchrnul(varval, '=');
10412                        if (*eq)
10413                                eq++;
10414                        fdprintf(preverrout_fd, "%s%.*s%s",
10415                                pfx,
10416                                (int)(eq - varval), varval,
10417                                maybe_single_quote(eq)
10418                        );
10419                        sp = sp->next;
10420                        pfx = " ";
10421                }
10422
10423                sp = arglist.list;
10424                while (sp) {
10425                        fdprintf(preverrout_fd, "%s%s",
10426                                pfx,
10427                                /* always quote if matches reserved word: */
10428                                findkwd(sp->text)
10429                                ? single_quote(sp->text)
10430                                : maybe_single_quote(sp->text)
10431                        );
10432                        sp = sp->next;
10433                        pfx = " ";
10434                }
10435                safe_write(preverrout_fd, "\n", 1);
10436        }
10437
10438        /* Now locate the command. */
10439        if (cmdentry.cmdtype != CMDBUILTIN
10440         || !(IS_BUILTIN_REGULAR(cmdentry.u.cmd))
10441        ) {
10442                path = path ? path : pathval();
10443                find_command(argv[0], &cmdentry, cmd_flag | DO_ERR, path);
10444        }
10445
10446        jp = NULL;
10447
10448        /* Execute the command. */
10449        switch (cmdentry.cmdtype) {
10450        case CMDUNKNOWN:
10451                status = 127;
10452                flush_stdout_stderr();
10453                goto bail;
10454
10455        default: {
10456
10457#if ENABLE_FEATURE_SH_STANDALONE \
10458 && ENABLE_FEATURE_SH_NOFORK \
10459 && NUM_APPLETS > 1
10460/* (1) BUG: if variables are set, we need to fork, or save/restore them
10461 *     around run_nofork_applet() call.
10462 * (2) Should this check also be done in forkshell()?
10463 *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
10464 */
10465                /* find_command() encodes applet_no as (-2 - applet_no) */
10466                int applet_no = (- cmdentry.u.index - 2);
10467                if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
10468                        char **sv_environ;
10469
10470                        INT_OFF;
10471                        sv_environ = environ;
10472                        environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
10473                        /*
10474                         * Run <applet>_main().
10475                         * Signals (^C) can't interrupt here.
10476                         * Otherwise we can mangle stdio or malloc internal state.
10477                         * This makes applets which can run for a long time
10478                         * and/or wait for user input ineligible for NOFORK:
10479                         * for example, "yes" or "rm" (rm -i waits for input).
10480                         */
10481                        exitstatus = run_nofork_applet(applet_no, argv);
10482                        environ = sv_environ;
10483                        /*
10484                         * Try enabling NOFORK for "yes" applet.
10485                         * ^C _will_ stop it (write returns EINTR),
10486                         * but this causes stdout FILE to be stuck
10487                         * and needing clearerr(). What if other applets
10488                         * also can get EINTRs? Do we need to switch
10489                         * our signals to SA_RESTART?
10490                         */
10491                        /*clearerr(stdout);*/
10492                        INT_ON;
10493                        break;
10494                }
10495#endif
10496                /* Can we avoid forking? For example, very last command
10497                 * in a script or a subshell does not need forking,
10498                 * we can just exec it.
10499                 */
10500                if (!(flags & EV_EXIT) || may_have_traps) {
10501                        /* No, forking off a child is necessary */
10502                        INT_OFF;
10503                        get_tty_state();
10504                        jp = makejob(/*cmd,*/ 1);
10505                        if (forkshell(jp, cmd, FORK_FG) != 0) {
10506                                /* parent */
10507                                break;
10508                        }
10509                        /* child */
10510                        FORCE_INT_ON;
10511                        /* fall through to exec'ing external program */
10512                }
10513                shellexec(argv[0], argv, path, cmdentry.u.index);
10514                /* NOTREACHED */
10515        } /* default */
10516        case CMDBUILTIN:
10517                if (evalbltin(cmdentry.u.cmd, argc, argv, flags)
10518                 && !(exception_type == EXERROR && spclbltin <= 0)
10519                ) {
10520 raise:
10521                        longjmp(exception_handler->loc, 1);
10522                }
10523                break;
10524
10525        case CMDFUNCTION:
10526                if (evalfun(cmdentry.u.func, argc, argv, flags))
10527                        goto raise;
10528                break;
10529        } /* switch */
10530
10531        status = waitforjob(jp);
10532        if (jp)
10533                TRACE(("forked child exited with %d\n", status));
10534        FORCE_INT_ON;
10535
10536 out:
10537        if (cmd->ncmd.redirect)
10538                popredir(/*drop:*/ cmd_is_exec);
10539        unwindredir(redir_stop);
10540        unwindfiles(file_stop);
10541        unwindlocalvars(localvar_stop);
10542        if (lastarg) {
10543                /* dsl: I think this is intended to be used to support
10544                 * '_' in 'vi' command mode during line editing...
10545                 * However I implemented that within libedit itself.
10546                 */
10547                setvar0("_", lastarg);
10548        }
10549
10550        return status;
10551}
10552
10553static int
10554evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10555{
10556        char *volatile savecmdname;
10557        struct jmploc *volatile savehandler;
10558        struct jmploc jmploc;
10559        int status;
10560        int i;
10561
10562        savecmdname = commandname;
10563        savehandler = exception_handler;
10564        i = setjmp(jmploc.loc);
10565        if (i)
10566                goto cmddone;
10567        exception_handler = &jmploc;
10568        commandname = argv[0];
10569        argptr = argv + 1;
10570        optptr = NULL;                  /* initialize nextopt */
10571        if (cmd == EVALCMD)
10572                status = evalcmd(argc, argv, flags);
10573        else
10574                status = (*cmd->builtin)(argc, argv);
10575        flush_stdout_stderr();
10576        status |= ferror(stdout);
10577        exitstatus = status;
10578 cmddone:
10579        clearerr(stdout);
10580        commandname = savecmdname;
10581        exception_handler = savehandler;
10582
10583        return i;
10584}
10585
10586static int
10587goodname(const char *p)
10588{
10589        return endofname(p)[0] == '\0';
10590}
10591
10592
10593/*
10594 * Search for a command.  This is called before we fork so that the
10595 * location of the command will be available in the parent as well as
10596 * the child.  The check for "goodname" is an overly conservative
10597 * check that the name will not be subject to expansion.
10598 */
10599static void
10600prehash(union node *n)
10601{
10602        struct cmdentry entry;
10603
10604        if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10605                find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10606}
10607
10608
10609/* ============ Builtin commands
10610 *
10611 * Builtin commands whose functions are closely tied to evaluation
10612 * are implemented here.
10613 */
10614
10615/*
10616 * Handle break and continue commands.  Break, continue, and return are
10617 * all handled by setting the evalskip flag.  The evaluation routines
10618 * above all check this flag, and if it is set they start skipping
10619 * commands rather than executing them.  The variable skipcount is
10620 * the number of loops to break/continue, or the number of function
10621 * levels to return.  (The latter is always 1.)  It should probably
10622 * be an error to break out of more loops than exist, but it isn't
10623 * in the standard shell so we don't make it one here.
10624 */
10625static int FAST_FUNC
10626breakcmd(int argc UNUSED_PARAM, char **argv)
10627{
10628        int n = argv[1] ? number(argv[1]) : 1;
10629
10630        if (n <= 0)
10631                ash_msg_and_raise_error(msg_illnum, argv[1]);
10632        if (n > loopnest)
10633                n = loopnest;
10634        if (n > 0) {
10635                evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10636                skipcount = n;
10637        }
10638        return 0;
10639}
10640
10641
10642/*
10643 * This implements the input routines used by the parser.
10644 */
10645
10646enum {
10647        INPUT_PUSH_FILE = 1,
10648        INPUT_NOFILE_OK = 2,
10649};
10650
10651static smallint checkkwd;
10652/* values of checkkwd variable */
10653#define CHKALIAS        0x1
10654#define CHKKWD          0x2
10655#define CHKNL           0x4
10656#define CHKEOFMARK      0x8
10657
10658/*
10659 * Push a string back onto the input at this current parsefile level.
10660 * We handle aliases this way.
10661 */
10662#if !ENABLE_ASH_ALIAS
10663#define pushstring(s, ap) pushstring(s)
10664#endif
10665static void
10666pushstring(char *s, struct alias *ap)
10667{
10668        struct strpush *sp;
10669        int len;
10670
10671        len = strlen(s);
10672        INT_OFF;
10673        if (g_parsefile->strpush) {
10674                sp = ckzalloc(sizeof(*sp));
10675                sp->prev = g_parsefile->strpush;
10676        } else {
10677                sp = &(g_parsefile->basestrpush);
10678        }
10679        g_parsefile->strpush = sp;
10680        sp->prev_string = g_parsefile->next_to_pgetc;
10681        sp->prev_left_in_line = g_parsefile->left_in_line;
10682        sp->unget = g_parsefile->unget;
10683        memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10684#if ENABLE_ASH_ALIAS
10685        sp->ap = ap;
10686        if (ap) {
10687                ap->flag |= ALIASINUSE;
10688                sp->string = s;
10689        }
10690#endif
10691        g_parsefile->next_to_pgetc = s;
10692        g_parsefile->left_in_line = len;
10693        g_parsefile->unget = 0;
10694        INT_ON;
10695}
10696
10697static void
10698popstring(void)
10699{
10700        struct strpush *sp = g_parsefile->strpush;
10701
10702        INT_OFF;
10703#if ENABLE_ASH_ALIAS
10704        if (sp->ap) {
10705                if (g_parsefile->next_to_pgetc[-1] == ' '
10706                 || g_parsefile->next_to_pgetc[-1] == '\t'
10707                ) {
10708                        checkkwd |= CHKALIAS;
10709                }
10710                if (sp->string != sp->ap->val) {
10711                        free(sp->string);
10712                }
10713                sp->ap->flag &= ~ALIASINUSE;
10714                if (sp->ap->flag & ALIASDEAD) {
10715                        unalias(sp->ap->name);
10716                }
10717        }
10718#endif
10719        g_parsefile->next_to_pgetc = sp->prev_string;
10720        g_parsefile->left_in_line = sp->prev_left_in_line;
10721        g_parsefile->unget = sp->unget;
10722        memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10723        g_parsefile->strpush = sp->prev;
10724        if (sp != &(g_parsefile->basestrpush))
10725                free(sp);
10726        INT_ON;
10727}
10728
10729static int
10730preadfd(void)
10731{
10732        int nr;
10733        char *buf = g_parsefile->buf;
10734
10735        g_parsefile->next_to_pgetc = buf;
10736#if ENABLE_FEATURE_EDITING
10737 /* retry: */
10738        if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10739                nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10740        else {
10741# if ENABLE_ASH_IDLE_TIMEOUT
10742                int timeout = -1;
10743                const char *tmout_var = lookupvar("TMOUT");
10744                if (tmout_var) {
10745                        timeout = atoi(tmout_var) * 1000;
10746                        if (timeout <= 0)
10747                                timeout = -1;
10748                }
10749                line_input_state->timeout = timeout;
10750# endif
10751# if ENABLE_FEATURE_TAB_COMPLETION
10752                line_input_state->path_lookup = pathval();
10753# endif
10754                reinit_unicode_for_ash();
10755                nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10756                if (nr == 0) {
10757                        /* ^C pressed, "convert" to SIGINT */
10758                        write(STDOUT_FILENO, "^C", 2);
10759                        raise(SIGINT);
10760                        if (trap[SIGINT]) {
10761                                buf[0] = '\n';
10762                                buf[1] = '\0';
10763                                return 1;
10764                        }
10765                        exitstatus = 128 + SIGINT;
10766                        return -1;
10767                }
10768                if (nr < 0) {
10769                        if (errno == 0) {
10770                                /* Ctrl+D pressed */
10771                                nr = 0;
10772                        }
10773# if ENABLE_ASH_IDLE_TIMEOUT
10774                        else if (errno == EAGAIN && timeout > 0) {
10775                                puts("\007timed out waiting for input: auto-logout");
10776                                exitshell();
10777                        }
10778# endif
10779                }
10780        }
10781#else
10782        nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10783#endif
10784
10785#if 0 /* disabled: nonblock_immune_read() handles this problem */
10786        if (nr < 0) {
10787                if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10788                        int flags = fcntl(0, F_GETFL);
10789                        if (flags >= 0 && (flags & O_NONBLOCK)) {
10790                                flags &= ~O_NONBLOCK;
10791                                if (fcntl(0, F_SETFL, flags) >= 0) {
10792                                        out2str("sh: turning off NDELAY mode\n");
10793                                        goto retry;
10794                                }
10795                        }
10796                }
10797        }
10798#endif
10799        return nr;
10800}
10801
10802/*
10803 * Refill the input buffer and return the next input character:
10804 *
10805 * 1) If a string was pushed back on the input, pop it;
10806 * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10807 *    or we are reading from a string so we can't refill the buffer,
10808 *    return EOF.
10809 * 3) If there is more stuff in this buffer, use it else call read to fill it.
10810 * 4) Process input up to the next newline, deleting nul characters.
10811 */
10812//#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10813#define pgetc_debug(...) ((void)0)
10814static int pgetc(void);
10815static int
10816preadbuffer(void)
10817{
10818        char *q;
10819        int more;
10820
10821        if (g_parsefile->strpush) {
10822#if ENABLE_ASH_ALIAS
10823                if (g_parsefile->left_in_line == -1
10824                 && g_parsefile->strpush->ap
10825                 && g_parsefile->next_to_pgetc[-1] != ' '
10826                 && g_parsefile->next_to_pgetc[-1] != '\t'
10827                ) {
10828                        pgetc_debug("preadbuffer PEOA");
10829                        return PEOA;
10830                }
10831#endif
10832                popstring();
10833                return pgetc();
10834        }
10835        /* on both branches above g_parsefile->left_in_line < 0.
10836         * "pgetc" needs refilling.
10837         */
10838
10839        /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10840         * pungetc() may increment it a few times.
10841         * Assuming it won't increment it to less than -90.
10842         */
10843        if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10844                pgetc_debug("preadbuffer PEOF1");
10845                /* even in failure keep left_in_line and next_to_pgetc
10846                 * in lock step, for correct multi-layer pungetc.
10847                 * left_in_line was decremented before preadbuffer(),
10848                 * must inc next_to_pgetc: */
10849                g_parsefile->next_to_pgetc++;
10850                return PEOF;
10851        }
10852
10853        more = g_parsefile->left_in_buffer;
10854        if (more <= 0) {
10855                flush_stdout_stderr();
10856 again:
10857                more = preadfd();
10858                if (more <= 0) {
10859                        /* don't try reading again */
10860                        g_parsefile->left_in_line = -99;
10861                        pgetc_debug("preadbuffer PEOF2");
10862                        g_parsefile->next_to_pgetc++;
10863                        return PEOF;
10864                }
10865        }
10866
10867        /* Find out where's the end of line.
10868         * Set g_parsefile->left_in_line
10869         * and g_parsefile->left_in_buffer acordingly.
10870         * NUL chars are deleted.
10871         */
10872        q = g_parsefile->next_to_pgetc;
10873        for (;;) {
10874                char c;
10875
10876                more--;
10877
10878                c = *q;
10879                if (c == '\0') {
10880                        memmove(q, q + 1, more);
10881                } else {
10882                        q++;
10883                        if (c == '\n') {
10884                                g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10885                                break;
10886                        }
10887                }
10888
10889                if (more <= 0) {
10890                        g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10891                        if (g_parsefile->left_in_line < 0)
10892                                goto again;
10893                        break;
10894                }
10895        }
10896        g_parsefile->left_in_buffer = more;
10897
10898        if (vflag) {
10899                char save = *q;
10900                *q = '\0';
10901                out2str(g_parsefile->next_to_pgetc);
10902                *q = save;
10903        }
10904
10905        pgetc_debug("preadbuffer at %d:%p'%s'",
10906                        g_parsefile->left_in_line,
10907                        g_parsefile->next_to_pgetc,
10908                        g_parsefile->next_to_pgetc);
10909        return (unsigned char)*g_parsefile->next_to_pgetc++;
10910}
10911
10912static void
10913nlprompt(void)
10914{
10915        g_parsefile->linno++;
10916        setprompt_if(doprompt, 2);
10917}
10918static void
10919nlnoprompt(void)
10920{
10921        g_parsefile->linno++;
10922        needprompt = doprompt;
10923}
10924
10925static int
10926pgetc(void)
10927{
10928        int c;
10929
10930        pgetc_debug("pgetc at %d:%p'%s'",
10931                        g_parsefile->left_in_line,
10932                        g_parsefile->next_to_pgetc,
10933                        g_parsefile->next_to_pgetc);
10934        if (g_parsefile->unget)
10935                return g_parsefile->lastc[--g_parsefile->unget];
10936
10937        if (--g_parsefile->left_in_line >= 0)
10938                c = (unsigned char)*g_parsefile->next_to_pgetc++;
10939        else
10940                c = preadbuffer();
10941
10942        g_parsefile->lastc[1] = g_parsefile->lastc[0];
10943        g_parsefile->lastc[0] = c;
10944
10945        return c;
10946}
10947
10948#if ENABLE_ASH_ALIAS
10949static int
10950pgetc_without_PEOA(void)
10951{
10952        int c;
10953        do {
10954                pgetc_debug("pgetc at %d:%p'%s'",
10955                                g_parsefile->left_in_line,
10956                                g_parsefile->next_to_pgetc,
10957                                g_parsefile->next_to_pgetc);
10958                c = pgetc();
10959        } while (c == PEOA);
10960        return c;
10961}
10962#else
10963# define pgetc_without_PEOA() pgetc()
10964#endif
10965
10966/*
10967 * Undo a call to pgetc.  Only two characters may be pushed back.
10968 * PEOF may be pushed back.
10969 */
10970static void
10971pungetc(void)
10972{
10973        g_parsefile->unget++;
10974}
10975
10976/* This one eats backslash+newline */
10977static int
10978pgetc_eatbnl(void)
10979{
10980        int c;
10981
10982        while ((c = pgetc()) == '\\') {
10983                if (pgetc() != '\n') {
10984                        pungetc();
10985                        break;
10986                }
10987
10988                nlprompt();
10989        }
10990
10991        return c;
10992}
10993
10994struct synstack {
10995        smalluint syntax;
10996        uint8_t innerdq   :1;
10997        uint8_t varpushed :1;
10998        uint8_t dblquote  :1;
10999        int varnest;            /* levels of variables expansion */
11000        int dqvarnest;          /* levels of variables expansion within double quotes */
11001        int parenlevel;         /* levels of parens in arithmetic */
11002        struct synstack *prev;
11003        struct synstack *next;
11004};
11005
11006static int
11007pgetc_top(struct synstack *stack)
11008{
11009        return stack->syntax == SQSYNTAX ? pgetc() : pgetc_eatbnl();
11010}
11011
11012static void
11013synstack_push(struct synstack **stack, struct synstack *next, int syntax)
11014{
11015        memset(next, 0, sizeof(*next));
11016        next->syntax = syntax;
11017        next->next = *stack;
11018        (*stack)->prev = next;
11019        *stack = next;
11020}
11021
11022static ALWAYS_INLINE void
11023synstack_pop(struct synstack **stack)
11024{
11025        *stack = (*stack)->next;
11026}
11027
11028/*
11029 * To handle the "." command, a stack of input files is used.  Pushfile
11030 * adds a new entry to the stack and popfile restores the previous level.
11031 */
11032static void
11033pushfile(void)
11034{
11035        struct parsefile *pf;
11036
11037        pf = ckzalloc(sizeof(*pf));
11038        pf->prev = g_parsefile;
11039        pf->pf_fd = -1;
11040        /*pf->strpush = NULL; - ckzalloc did it */
11041        /*pf->basestrpush.prev = NULL;*/
11042        /*pf->unget = 0;*/
11043        g_parsefile = pf;
11044}
11045
11046static void
11047popfile(void)
11048{
11049        struct parsefile *pf = g_parsefile;
11050
11051        if (pf == &basepf)
11052                return;
11053
11054        INT_OFF;
11055        if (pf->pf_fd >= 0)
11056                close(pf->pf_fd);
11057        free(pf->buf);
11058        while (pf->strpush)
11059                popstring();
11060        g_parsefile = pf->prev;
11061        free(pf);
11062        INT_ON;
11063}
11064
11065static void
11066unwindfiles(struct parsefile *stop)
11067{
11068        while (g_parsefile != stop)
11069                popfile();
11070}
11071
11072/*
11073 * Return to top level.
11074 */
11075static void
11076popallfiles(void)
11077{
11078        unwindfiles(&basepf);
11079}
11080
11081/*
11082 * Close the file(s) that the shell is reading commands from.  Called
11083 * after a fork is done.
11084 */
11085static void
11086closescript(void)
11087{
11088        popallfiles();
11089        if (g_parsefile->pf_fd > 0) {
11090                close(g_parsefile->pf_fd);
11091                g_parsefile->pf_fd = 0;
11092        }
11093}
11094
11095/*
11096 * Like setinputfile, but takes an open file descriptor.  Call this with
11097 * interrupts off.
11098 */
11099static void
11100setinputfd(int fd, int push)
11101{
11102        if (push) {
11103                pushfile();
11104                g_parsefile->buf = NULL;
11105        }
11106        g_parsefile->pf_fd = fd;
11107        if (g_parsefile->buf == NULL)
11108                g_parsefile->buf = ckmalloc(IBUFSIZ);
11109        g_parsefile->left_in_buffer = 0;
11110        g_parsefile->left_in_line = 0;
11111        g_parsefile->linno = 1;
11112}
11113
11114/*
11115 * Set the input to take input from a file.  If push is set, push the
11116 * old input onto the stack first.
11117 */
11118static int
11119setinputfile(const char *fname, int flags)
11120{
11121        int fd;
11122
11123        INT_OFF;
11124        fd = open(fname, O_RDONLY | O_CLOEXEC);
11125        if (fd < 0) {
11126                if (flags & INPUT_NOFILE_OK)
11127                        goto out;
11128                exitstatus = 127;
11129                ash_msg_and_raise_perror("can't open '%s'", fname);
11130        }
11131        if (fd < 10)
11132                fd = savefd(fd);
11133        else if (O_CLOEXEC == 0) /* old libc */
11134                close_on_exec_on(fd);
11135
11136        setinputfd(fd, flags & INPUT_PUSH_FILE);
11137 out:
11138        INT_ON;
11139        return fd;
11140}
11141
11142/*
11143 * Like setinputfile, but takes input from a string.
11144 */
11145static void
11146setinputstring(char *string)
11147{
11148        INT_OFF;
11149        pushfile();
11150        g_parsefile->next_to_pgetc = string;
11151        g_parsefile->left_in_line = strlen(string);
11152        g_parsefile->buf = NULL;
11153        g_parsefile->linno = 1;
11154        INT_ON;
11155}
11156
11157
11158/*
11159 * Routines to check for mail.
11160 */
11161
11162#if ENABLE_ASH_MAIL
11163
11164/* Hash of mtimes of mailboxes */
11165static unsigned mailtime_hash;
11166/* Set if MAIL or MAILPATH is changed. */
11167static smallint mail_var_path_changed;
11168
11169/*
11170 * Print appropriate message(s) if mail has arrived.
11171 * If mail_var_path_changed is set,
11172 * then the value of MAIL has mail_var_path_changed,
11173 * so we just update the values.
11174 */
11175static void
11176chkmail(void)
11177{
11178        const char *mpath;
11179        char *p;
11180        char *q;
11181        unsigned new_hash;
11182        struct stackmark smark;
11183        struct stat statb;
11184
11185        setstackmark(&smark);
11186        mpath = mpathset() ? mpathval() : mailval();
11187        new_hash = 0;
11188        for (;;) {
11189                int len;
11190
11191                len = padvance_magic(&mpath, nullstr, 2);
11192                if (!len)
11193                        break;
11194                p = stackblock();
11195                        break;
11196                if (*p == '\0')
11197                        continue;
11198                for (q = p; *q; q++)
11199                        continue;
11200#if DEBUG
11201                if (q[-1] != '/')
11202                        abort();
11203#endif
11204                q[-1] = '\0';                   /* delete trailing '/' */
11205                if (stat(p, &statb) < 0) {
11206                        continue;
11207                }
11208                /* Very simplistic "hash": just a sum of all mtimes */
11209                new_hash += (unsigned)statb.st_mtime;
11210        }
11211        if (!mail_var_path_changed && mailtime_hash != new_hash) {
11212                if (mailtime_hash != 0)
11213                        out2str("you have mail\n");
11214                mailtime_hash = new_hash;
11215        }
11216        mail_var_path_changed = 0;
11217        popstackmark(&smark);
11218}
11219
11220static void FAST_FUNC
11221changemail(const char *val UNUSED_PARAM)
11222{
11223        mail_var_path_changed = 1;
11224}
11225
11226#endif /* ASH_MAIL */
11227
11228
11229/* ============ ??? */
11230
11231/*
11232 * Set the shell parameters.
11233 */
11234static void
11235setparam(char **argv)
11236{
11237        char **newparam;
11238        char **ap;
11239        int nparam;
11240
11241        for (nparam = 0; argv[nparam]; nparam++)
11242                continue;
11243        ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
11244        while (*argv) {
11245                *ap++ = ckstrdup(*argv++);
11246        }
11247        *ap = NULL;
11248        freeparam(&shellparam);
11249        shellparam.malloced = 1;
11250        shellparam.nparam = nparam;
11251        shellparam.p = newparam;
11252#if ENABLE_ASH_GETOPTS
11253        shellparam.optind = 1;
11254        shellparam.optoff = -1;
11255#endif
11256}
11257
11258/*
11259 * Process shell options.  The global variable argptr contains a pointer
11260 * to the argument list; we advance it past the options.
11261 *
11262 * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
11263 * For a non-interactive shell, an error condition encountered
11264 * by a special built-in ... shall cause the shell to write a diagnostic message
11265 * to standard error and exit as shown in the following table:
11266 * Error                                           Special Built-In
11267 * ...
11268 * Utility syntax error (option or operand error)  Shall exit
11269 * ...
11270 * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
11271 * we see that bash does not do that (set "finishes" with error code 1 instead,
11272 * and shell continues), and people rely on this behavior!
11273 * Testcase:
11274 * set -o barfoo 2>/dev/null
11275 * echo $?
11276 *
11277 * Oh well. Let's mimic that.
11278 */
11279static int
11280plus_minus_o(char *name, int val)
11281{
11282        int i;
11283
11284        if (name) {
11285                for (i = 0; i < NOPTS; i++) {
11286                        if (strcmp(name, optnames(i)) == 0) {
11287                                optlist[i] = val;
11288                                return 0;
11289                        }
11290                }
11291                ash_msg("illegal option %co %s", val ? '-' : '+', name);
11292                return 1;
11293        }
11294        for (i = 0; i < NOPTS; i++) {
11295                if (optnames(i)[0] == '\0')
11296                        continue;
11297                if (val) {
11298                        out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
11299                } else {
11300                        out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
11301                }
11302        }
11303        return 0;
11304}
11305static void
11306setoption(int flag, int val)
11307{
11308        int i;
11309
11310        for (i = 0; i < NOPTS; i++) {
11311                if (optletters(i) == flag && optnames(i)[0] != '\0') {
11312                        optlist[i] = val;
11313                        return;
11314                }
11315        }
11316        ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
11317        /* NOTREACHED */
11318}
11319/* If login_sh is not NULL, we are called to parse command line opts,
11320 * not "set -opts"
11321 */
11322static int
11323options(int *login_sh)
11324{
11325        char *p;
11326        int val;
11327        int c;
11328
11329        if (login_sh)
11330                minusc = NULL;
11331        while ((p = *argptr) != NULL) {
11332                c = *p++;
11333                if (c != '-' && c != '+')
11334                        break;
11335                argptr++;
11336                val = 0; /* val = 0 if c == '+' */
11337                if (c == '-') {
11338                        val = 1;
11339                        if (p[0] == '\0' || LONE_DASH(p)) {
11340                                if (!login_sh) {
11341                                        /* "-" means turn off -x and -v */
11342                                        if (p[0] == '\0')
11343                                                xflag = vflag = 0;
11344                                        /* "--" means reset params */
11345                                        else if (*argptr == NULL)
11346                                                setparam(argptr);
11347                                }
11348                                break;    /* "-" or "--" terminates options */
11349                        }
11350                }
11351                /* first char was + or - */
11352                while ((c = *p++) != '\0') {
11353                        if (login_sh) {
11354                                /* bash 3.2 indeed handles -c CMD and +c CMD the same */
11355                                if (c == 'c') {
11356                                        minusc = p; /* command is after shell args */
11357                                        cflag = 1;
11358                                        continue;
11359                                }
11360                                if (c == 's') { /* -s, +s */
11361                                        sflag = 1;
11362                                        continue;
11363                                }
11364                                if (c == 'i') { /* -i, +i */
11365                                        iflag = 1;
11366                                        continue;
11367                                }
11368                                if (c == 'l') {
11369                                        *login_sh = 1; /* -l or +l == --login */
11370                                        continue;
11371                                }
11372                                /* bash does not accept +-login, we also won't */
11373                                if (val && (c == '-')) { /* long options */
11374                                        if (strcmp(p, "login") == 0) {
11375                                                *login_sh = 1;
11376                                        }
11377                                        break;
11378                                }
11379                        }
11380                        if (c == 'o') {
11381                                if (plus_minus_o(*argptr, val)) {
11382                                        /* it already printed err message */
11383                                        return 1; /* error */
11384                                }
11385                                if (*argptr)
11386                                        argptr++;
11387                        } else {
11388                                setoption(c, val);
11389                        }
11390                }
11391        }
11392        return 0;
11393}
11394
11395/*
11396 * The shift builtin command.
11397 */
11398static int FAST_FUNC
11399shiftcmd(int argc UNUSED_PARAM, char **argv)
11400{
11401        int n;
11402        char **ap1, **ap2;
11403
11404        n = 1;
11405        if (argv[1])
11406                n = number(argv[1]);
11407        if (n > shellparam.nparam)
11408                return 1;
11409        INT_OFF;
11410        shellparam.nparam -= n;
11411        for (ap1 = shellparam.p; --n >= 0; ap1++) {
11412                if (shellparam.malloced)
11413                        free(*ap1);
11414        }
11415        ap2 = shellparam.p;
11416        while ((*ap2++ = *ap1++) != NULL)
11417                continue;
11418#if ENABLE_ASH_GETOPTS
11419        shellparam.optind = 1;
11420        shellparam.optoff = -1;
11421#endif
11422        INT_ON;
11423        return 0;
11424}
11425
11426/*
11427 * POSIX requires that 'set' (but not export or readonly) output the
11428 * variables in lexicographic order - by the locale's collating order (sigh).
11429 * Maybe we could keep them in an ordered balanced binary tree
11430 * instead of hashed lists.
11431 * For now just roll 'em through qsort for printing...
11432 */
11433static int
11434showvars(const char *sep_prefix, int on, int off)
11435{
11436        const char *sep;
11437        char **ep, **epend;
11438
11439        ep = listvars(on, off, /*strlist:*/ NULL, &epend);
11440        qsort(ep, epend - ep, sizeof(char *), vpcmp);
11441
11442        sep = *sep_prefix ? " " : sep_prefix;
11443
11444        for (; ep < epend; ep++) {
11445                const char *p;
11446                const char *q;
11447
11448                p = endofname(*ep);
11449/* Used to have simple "p = strchrnul(*ep, '=')" here instead, but this
11450 * makes "export -p" to have output not suitable for "eval":
11451 * import os
11452 * os.environ["test-test"]="test"
11453 * if os.fork() == 0:
11454 *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
11455 * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])
11456 */
11457                q = nullstr;
11458                if (*p == '=')
11459                        q = single_quote(++p);
11460                out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
11461        }
11462        return 0;
11463}
11464
11465/*
11466 * The set command builtin.
11467 */
11468static int FAST_FUNC
11469setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11470{
11471        int retval;
11472
11473        if (!argv[1])
11474                return showvars(nullstr, 0, VUNSET);
11475
11476        INT_OFF;
11477        retval = options(/*login_sh:*/ NULL);
11478        if (retval == 0) { /* if no parse error... */
11479                optschanged();
11480                if (*argptr != NULL) {
11481                        setparam(argptr);
11482                }
11483        }
11484        INT_ON;
11485        return retval;
11486}
11487
11488#if ENABLE_ASH_RANDOM_SUPPORT
11489static void FAST_FUNC
11490change_random(const char *value)
11491{
11492        uint32_t t;
11493
11494        if (value == NULL) {
11495                /* "get", generate */
11496                t = next_random(&random_gen);
11497                /* set without recursion */
11498                setvar(vrandom.var_text, utoa(t), VNOFUNC);
11499                vrandom.flags &= ~VNOFUNC;
11500        } else {
11501                /* set/reset */
11502                t = strtoul(value, NULL, 10);
11503                INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
11504        }
11505}
11506#endif
11507
11508#if BASH_EPOCH_VARS
11509static void FAST_FUNC
11510change_epoch(struct var *vepoch, const char *fmt)
11511{
11512        struct timeval tv;
11513        char buffer[sizeof("%llu.nnnnnn") + sizeof(long long)*3];
11514
11515        xgettimeofday(&tv);
11516        sprintf(buffer, fmt, (unsigned long long)tv.tv_sec, (unsigned)tv.tv_usec);
11517        setvar(vepoch->var_text, buffer, VNOFUNC);
11518        vepoch->flags &= ~VNOFUNC;
11519}
11520
11521static void FAST_FUNC
11522change_seconds(const char *value UNUSED_PARAM)
11523{
11524        change_epoch(&vepochs, "%llu");
11525}
11526
11527static void FAST_FUNC
11528change_realtime(const char *value UNUSED_PARAM)
11529{
11530        change_epoch(&vepochr, "%llu.%06u");
11531}
11532#endif
11533
11534#if ENABLE_ASH_GETOPTS
11535static int
11536getopts(char *optstr, char *optvar, char **optfirst)
11537{
11538        char *p, *q;
11539        char c = '?';
11540        int done = 0;
11541        char sbuf[2];
11542        char **optnext;
11543        int ind = shellparam.optind;
11544        int off = shellparam.optoff;
11545
11546        sbuf[1] = '\0';
11547
11548        shellparam.optind = -1;
11549        optnext = optfirst + ind - 1;
11550
11551        if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
11552                p = NULL;
11553        else
11554                p = optnext[-1] + off;
11555        if (p == NULL || *p == '\0') {
11556                /* Current word is done, advance */
11557                p = *optnext;
11558                if (p == NULL || *p != '-' || *++p == '\0') {
11559 atend:
11560                        unsetvar("OPTARG");
11561                        p = NULL;
11562                        done = 1;
11563                        goto out;
11564                }
11565                optnext++;
11566                if (LONE_DASH(p))        /* check for "--" */
11567                        goto atend;
11568        }
11569
11570        c = *p++;
11571        for (q = optstr; *q != c;) {
11572                if (*q == '\0') {
11573                        /* OPTERR is a bashism */
11574                        const char *cp = lookupvar("OPTERR");
11575                        if ((cp && LONE_CHAR(cp, '0'))
11576                         || (optstr[0] == ':')
11577                        ) {
11578                                sbuf[0] = c;
11579                                /*sbuf[1] = '\0'; - already is */
11580                                setvar0("OPTARG", sbuf);
11581                        } else {
11582                                fprintf(stderr, "Illegal option -%c\n", c);
11583                                unsetvar("OPTARG");
11584                        }
11585                        c = '?';
11586                        goto out;
11587                }
11588                if (*++q == ':')
11589                        q++;
11590        }
11591
11592        if (*++q == ':') {
11593                if (*p == '\0' && (p = *optnext) == NULL) {
11594                        /* OPTERR is a bashism */
11595                        const char *cp = lookupvar("OPTERR");
11596                        if ((cp && LONE_CHAR(cp, '0'))
11597                         || (optstr[0] == ':')
11598                        ) {
11599                                sbuf[0] = c;
11600                                /*sbuf[1] = '\0'; - already is */
11601                                setvar0("OPTARG", sbuf);
11602                                c = ':';
11603                        } else {
11604                                fprintf(stderr, "No arg for -%c option\n", c);
11605                                unsetvar("OPTARG");
11606                                c = '?';
11607                        }
11608                        goto out;
11609                }
11610
11611                if (p == *optnext)
11612                        optnext++;
11613                setvar0("OPTARG", p);
11614                p = NULL;
11615        } else
11616                setvar0("OPTARG", nullstr);
11617 out:
11618        ind = optnext - optfirst + 1;
11619        setvar("OPTIND", itoa(ind), VNOFUNC);
11620        sbuf[0] = c;
11621        /*sbuf[1] = '\0'; - already is */
11622        setvar0(optvar, sbuf);
11623
11624        shellparam.optoff = p ? p - *(optnext - 1) : -1;
11625        shellparam.optind = ind;
11626
11627        return done;
11628}
11629
11630/*
11631 * The getopts builtin.  Shellparam.optnext points to the next argument
11632 * to be processed.  Shellparam.optptr points to the next character to
11633 * be processed in the current argument.  If shellparam.optnext is NULL,
11634 * then it's the first time getopts has been called.
11635 */
11636static int FAST_FUNC
11637getoptscmd(int argc, char **argv)
11638{
11639        char **optbase;
11640
11641        if (argc < 3)
11642                ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11643        if (argc == 3) {
11644                optbase = shellparam.p;
11645                if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11646                        shellparam.optind = 1;
11647                        shellparam.optoff = -1;
11648                }
11649        } else {
11650                optbase = &argv[3];
11651                if ((unsigned)shellparam.optind > argc - 2) {
11652                        shellparam.optind = 1;
11653                        shellparam.optoff = -1;
11654                }
11655        }
11656
11657        return getopts(argv[1], argv[2], optbase);
11658}
11659#endif /* ASH_GETOPTS */
11660
11661
11662/* ============ Shell parser */
11663
11664struct heredoc {
11665        struct heredoc *next;   /* next here document in list */
11666        union node *here;       /* redirection node */
11667        char *eofmark;          /* string indicating end of input */
11668        smallint striptabs;     /* if set, strip leading tabs */
11669};
11670
11671static smallint tokpushback;           /* last token pushed back */
11672static smallint quoteflag;             /* set if (part of) last token was quoted */
11673static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11674static struct heredoc *heredoclist;    /* list of here documents to read */
11675static char *wordtext;                 /* text of last word returned by readtoken */
11676static struct nodelist *backquotelist;
11677static union node *redirnode;
11678static struct heredoc *heredoc;
11679
11680static const char *
11681tokname(char *buf, int tok)
11682{
11683        if (tok < TSEMI)
11684                return tokname_array[tok];
11685        sprintf(buf, "\"%s\"", tokname_array[tok]);
11686        return buf;
11687}
11688
11689/* raise_error_unexpected_syntax:
11690 * Called when an unexpected token is read during the parse.  The argument
11691 * is the token that is expected, or -1 if more than one type of token can
11692 * occur at this point.
11693 */
11694static void raise_error_unexpected_syntax(int) NORETURN;
11695static void
11696raise_error_unexpected_syntax(int token)
11697{
11698        char msg[64];
11699        char buf[16];
11700        int l;
11701
11702        l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11703        if (token >= 0)
11704                sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11705        raise_error_syntax(msg);
11706        /* NOTREACHED */
11707}
11708
11709/* parsing is heavily cross-recursive, need these forward decls */
11710static union node *andor(void);
11711static union node *pipeline(void);
11712static union node *parse_command(void);
11713static void parseheredoc(void);
11714static int peektoken(void);
11715static int readtoken(void);
11716
11717static union node *
11718list(int nlflag)
11719{
11720        union node *n1, *n2, *n3;
11721        int tok;
11722
11723        n1 = NULL;
11724        for (;;) {
11725                switch (readtoken()) {
11726                case TNL:
11727                        if (!(nlflag & 1))
11728                                break;
11729                        parseheredoc();
11730                        return n1;
11731
11732                case TEOF:
11733                        if (!n1 && (nlflag & 1))
11734                                n1 = NODE_EOF;
11735                        parseheredoc();
11736                        tokpushback++;
11737                        lasttoken = TEOF;
11738                        return n1;
11739                }
11740
11741                tokpushback++;
11742                checkkwd = CHKNL | CHKKWD | CHKALIAS;
11743                if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11744                        return n1;
11745                nlflag |= 2;
11746
11747                n2 = andor();
11748                tok = readtoken();
11749                if (tok == TBACKGND) {
11750                        if (n2->type == NPIPE) {
11751                                n2->npipe.pipe_backgnd = 1;
11752                        } else {
11753                                if (n2->type != NREDIR) {
11754                                        n3 = stzalloc(sizeof(struct nredir));
11755                                        n3->nredir.n = n2;
11756                                        /*n3->nredir.redirect = NULL; - stzalloc did it */
11757                                        n2 = n3;
11758                                }
11759                                n2->type = NBACKGND;
11760                        }
11761                }
11762                if (n1 == NULL) {
11763                        n1 = n2;
11764                } else {
11765                        n3 = stzalloc(sizeof(struct nbinary));
11766                        n3->type = NSEMI;
11767                        n3->nbinary.ch1 = n1;
11768                        n3->nbinary.ch2 = n2;
11769                        n1 = n3;
11770                }
11771                switch (tok) {
11772                case TNL:
11773                case TEOF:
11774                        tokpushback = 1;
11775                        /* fall through */
11776                case TBACKGND:
11777                case TSEMI:
11778                        break;
11779                default:
11780                        if ((nlflag & 1))
11781                                raise_error_unexpected_syntax(-1);
11782                        tokpushback = 1;
11783                        return n1;
11784                }
11785        }
11786}
11787
11788static union node *
11789andor(void)
11790{
11791        union node *n1, *n2, *n3;
11792        int t;
11793
11794        n1 = pipeline();
11795        for (;;) {
11796                t = readtoken();
11797                if (t == TAND) {
11798                        t = NAND;
11799                } else if (t == TOR) {
11800                        t = NOR;
11801                } else {
11802                        tokpushback = 1;
11803                        return n1;
11804                }
11805                checkkwd = CHKNL | CHKKWD | CHKALIAS;
11806                n2 = pipeline();
11807                n3 = stzalloc(sizeof(struct nbinary));
11808                n3->type = t;
11809                n3->nbinary.ch1 = n1;
11810                n3->nbinary.ch2 = n2;
11811                n1 = n3;
11812        }
11813}
11814
11815static union node *
11816pipeline(void)
11817{
11818        union node *n1, *n2, *pipenode;
11819        struct nodelist *lp, *prev;
11820        int negate;
11821
11822        negate = 0;
11823        TRACE(("pipeline: entered\n"));
11824        if (readtoken() == TNOT) {
11825                negate = !negate;
11826                checkkwd = CHKKWD | CHKALIAS;
11827        } else
11828                tokpushback = 1;
11829        n1 = parse_command();
11830        if (readtoken() == TPIPE) {
11831                pipenode = stzalloc(sizeof(struct npipe));
11832                pipenode->type = NPIPE;
11833                /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11834                lp = stzalloc(sizeof(struct nodelist));
11835                pipenode->npipe.cmdlist = lp;
11836                lp->n = n1;
11837                do {
11838                        prev = lp;
11839                        lp = stzalloc(sizeof(struct nodelist));
11840                        checkkwd = CHKNL | CHKKWD | CHKALIAS;
11841                        lp->n = parse_command();
11842                        prev->next = lp;
11843                } while (readtoken() == TPIPE);
11844                lp->next = NULL;
11845                n1 = pipenode;
11846        }
11847        tokpushback = 1;
11848        if (negate) {
11849                n2 = stzalloc(sizeof(struct nnot));
11850                n2->type = NNOT;
11851                n2->nnot.com = n1;
11852                return n2;
11853        }
11854        return n1;
11855}
11856
11857static union node *
11858makename(void)
11859{
11860        union node *n;
11861
11862        n = stzalloc(sizeof(struct narg));
11863        n->type = NARG;
11864        /*n->narg.next = NULL; - stzalloc did it */
11865        n->narg.text = wordtext;
11866        n->narg.backquote = backquotelist;
11867        return n;
11868}
11869
11870static void
11871fixredir(union node *n, const char *text, int err)
11872{
11873        int fd;
11874
11875        TRACE(("Fix redir %s %d\n", text, err));
11876        if (!err)
11877                n->ndup.vname = NULL;
11878
11879        fd = bb_strtou(text, NULL, 10);
11880        if (!errno && fd >= 0)
11881                n->ndup.dupfd = fd;
11882        else if (LONE_DASH(text))
11883                n->ndup.dupfd = -1;
11884        else {
11885                if (err)
11886                        raise_error_syntax("bad fd number");
11887                n->ndup.vname = makename();
11888        }
11889}
11890
11891static void
11892parsefname(void)
11893{
11894        union node *n = redirnode;
11895
11896        if (n->type == NHERE)
11897                checkkwd = CHKEOFMARK;
11898        if (readtoken() != TWORD)
11899                raise_error_unexpected_syntax(-1);
11900        if (n->type == NHERE) {
11901                struct heredoc *here = heredoc;
11902                struct heredoc *p;
11903
11904                if (quoteflag == 0)
11905                        n->type = NXHERE;
11906                TRACE(("Here document %d\n", n->type));
11907                rmescapes(wordtext, 0, NULL);
11908                here->eofmark = wordtext;
11909                here->next = NULL;
11910                if (heredoclist == NULL)
11911                        heredoclist = here;
11912                else {
11913                        for (p = heredoclist; p->next; p = p->next)
11914                                continue;
11915                        p->next = here;
11916                }
11917        } else if (n->type == NTOFD || n->type == NFROMFD) {
11918                fixredir(n, wordtext, 0);
11919        } else {
11920                n->nfile.fname = makename();
11921        }
11922}
11923
11924static union node *
11925simplecmd(void)
11926{
11927        union node *args, **app;
11928        union node *n = NULL;
11929        union node *vars, **vpp;
11930        union node **rpp, *redir;
11931        int savecheckkwd;
11932        int savelinno;
11933#if BASH_TEST2
11934        smallint double_brackets_flag = 0;
11935#endif
11936        IF_BASH_FUNCTION(smallint function_flag = 0;)
11937
11938        args = NULL;
11939        app = &args;
11940        vars = NULL;
11941        vpp = &vars;
11942        redir = NULL;
11943        rpp = &redir;
11944
11945        savecheckkwd = CHKALIAS;
11946        savelinno = g_parsefile->linno;
11947        for (;;) {
11948                int t;
11949                checkkwd = savecheckkwd;
11950                t = readtoken();
11951                switch (t) {
11952#if BASH_FUNCTION
11953                case TFUNCTION:
11954                        if (peektoken() != TWORD)
11955                                raise_error_unexpected_syntax(TWORD);
11956                        function_flag = 1;
11957                        break;
11958#endif
11959#if BASH_TEST2
11960                case TAND: /* "&&" */
11961                case TOR: /* "||" */
11962                        if (!double_brackets_flag) {
11963                                tokpushback = 1;
11964                                goto out;
11965                        }
11966                        /* pass "&&" or "||" to [[ ]] as literal args */
11967                        wordtext = (char *) (t == TAND ? "&&" : "||");
11968#endif
11969                case TWORD:
11970                        n = stzalloc(sizeof(struct narg));
11971                        n->type = NARG;
11972                        /*n->narg.next = NULL; - stzalloc did it */
11973                        n->narg.text = wordtext;
11974#if BASH_TEST2
11975                        if (strcmp("[[", wordtext) == 0)
11976                                double_brackets_flag = 1;
11977                        else if (strcmp("]]", wordtext) == 0)
11978                                double_brackets_flag = 0;
11979#endif
11980                        n->narg.backquote = backquotelist;
11981                        if (savecheckkwd && isassignment(wordtext)) {
11982                                *vpp = n;
11983                                vpp = &n->narg.next;
11984                        } else {
11985                                *app = n;
11986                                app = &n->narg.next;
11987                                savecheckkwd = 0;
11988                        }
11989#if BASH_FUNCTION
11990                        if (function_flag) {
11991                                checkkwd = CHKNL | CHKKWD;
11992                                switch (peektoken()) {
11993                                case TBEGIN:
11994                                case TIF:
11995                                case TCASE:
11996                                case TUNTIL:
11997                                case TWHILE:
11998                                case TFOR:
11999                                        goto do_func;
12000                                case TLP:
12001                                        function_flag = 0;
12002                                        break;
12003# if BASH_TEST2
12004                                case TWORD:
12005                                        if (strcmp("[[", wordtext) == 0)
12006                                                goto do_func;
12007                                        /* fall through */
12008# endif
12009                                default:
12010                                        raise_error_unexpected_syntax(-1);
12011                                }
12012                        }
12013#endif
12014                        break;
12015                case TREDIR:
12016                        *rpp = n = redirnode;
12017                        rpp = &n->nfile.next;
12018                        parsefname();   /* read name of redirection file */
12019                        break;
12020                case TLP:
12021 IF_BASH_FUNCTION(do_func:)
12022                        if (args && app == &args->narg.next
12023                         && !vars && !redir
12024                        ) {
12025                                struct builtincmd *bcmd;
12026                                const char *name;
12027
12028                                /* We have a function */
12029                                if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
12030                                        raise_error_unexpected_syntax(TRP);
12031                                name = n->narg.text;
12032                                if (!goodname(name)
12033                                 || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
12034                                ) {
12035                                        raise_error_syntax("bad function name");
12036                                }
12037                                n->type = NDEFUN;
12038                                checkkwd = CHKNL | CHKKWD | CHKALIAS;
12039                                n->ndefun.text = n->narg.text;
12040                                n->ndefun.linno = g_parsefile->linno;
12041                                n->ndefun.body = parse_command();
12042                                return n;
12043                        }
12044                        IF_BASH_FUNCTION(function_flag = 0;)
12045                        /* fall through */
12046                default:
12047                        tokpushback = 1;
12048                        goto out;
12049                }
12050        }
12051 out:
12052        *app = NULL;
12053        *vpp = NULL;
12054        *rpp = NULL;
12055        n = stzalloc(sizeof(struct ncmd));
12056        if (NCMD != 0)
12057                n->type = NCMD;
12058        n->ncmd.linno = savelinno;
12059        n->ncmd.args = args;
12060        n->ncmd.assign = vars;
12061        n->ncmd.redirect = redir;
12062        return n;
12063}
12064
12065static union node *
12066parse_command(void)
12067{
12068        union node *n1, *n2;
12069        union node *ap, **app;
12070        union node *cp, **cpp;
12071        union node *redir, **rpp;
12072        union node **rpp2;
12073        int t;
12074        int savelinno;
12075
12076        redir = NULL;
12077        rpp2 = &redir;
12078
12079        savelinno = g_parsefile->linno;
12080
12081        switch (readtoken()) {
12082        default:
12083                raise_error_unexpected_syntax(-1);
12084                /* NOTREACHED */
12085        case TIF:
12086                n1 = stzalloc(sizeof(struct nif));
12087                n1->type = NIF;
12088                n1->nif.test = list(0);
12089                if (readtoken() != TTHEN)
12090                        raise_error_unexpected_syntax(TTHEN);
12091                n1->nif.ifpart = list(0);
12092                n2 = n1;
12093                while (readtoken() == TELIF) {
12094                        n2->nif.elsepart = stzalloc(sizeof(struct nif));
12095                        n2 = n2->nif.elsepart;
12096                        n2->type = NIF;
12097                        n2->nif.test = list(0);
12098                        if (readtoken() != TTHEN)
12099                                raise_error_unexpected_syntax(TTHEN);
12100                        n2->nif.ifpart = list(0);
12101                }
12102                if (lasttoken == TELSE)
12103                        n2->nif.elsepart = list(0);
12104                else {
12105                        n2->nif.elsepart = NULL;
12106                        tokpushback = 1;
12107                }
12108                t = TFI;
12109                break;
12110        case TWHILE:
12111        case TUNTIL: {
12112                int got;
12113                n1 = stzalloc(sizeof(struct nbinary));
12114                n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
12115                n1->nbinary.ch1 = list(0);
12116                got = readtoken();
12117                if (got != TDO) {
12118                        TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
12119                                        got == TWORD ? wordtext : ""));
12120                        raise_error_unexpected_syntax(TDO);
12121                }
12122                n1->nbinary.ch2 = list(0);
12123                t = TDONE;
12124                break;
12125        }
12126        case TFOR:
12127                if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
12128                        raise_error_syntax("bad for loop variable");
12129                n1 = stzalloc(sizeof(struct nfor));
12130                n1->type = NFOR;
12131                n1->nfor.linno = savelinno;
12132                n1->nfor.var = wordtext;
12133                checkkwd = CHKNL | CHKKWD | CHKALIAS;
12134                if (readtoken() == TIN) {
12135                        app = &ap;
12136                        while (readtoken() == TWORD) {
12137                                n2 = stzalloc(sizeof(struct narg));
12138                                n2->type = NARG;
12139                                /*n2->narg.next = NULL; - stzalloc did it */
12140                                n2->narg.text = wordtext;
12141                                n2->narg.backquote = backquotelist;
12142                                *app = n2;
12143                                app = &n2->narg.next;
12144                        }
12145                        *app = NULL;
12146                        n1->nfor.args = ap;
12147                        if (lasttoken != TNL && lasttoken != TSEMI)
12148                                raise_error_unexpected_syntax(-1);
12149                } else {
12150                        n2 = stzalloc(sizeof(struct narg));
12151                        n2->type = NARG;
12152                        /*n2->narg.next = NULL; - stzalloc did it */
12153                        n2->narg.text = (char *)dolatstr;
12154                        /*n2->narg.backquote = NULL;*/
12155                        n1->nfor.args = n2;
12156                        /*
12157                         * Newline or semicolon here is optional (but note
12158                         * that the original Bourne shell only allowed NL).
12159                         */
12160                        if (lasttoken != TSEMI)
12161                                tokpushback = 1;
12162                }
12163                checkkwd = CHKNL | CHKKWD | CHKALIAS;
12164                if (readtoken() != TDO)
12165                        raise_error_unexpected_syntax(TDO);
12166                n1->nfor.body = list(0);
12167                t = TDONE;
12168                break;
12169        case TCASE:
12170                n1 = stzalloc(sizeof(struct ncase));
12171                n1->type = NCASE;
12172                n1->ncase.linno = savelinno;
12173                if (readtoken() != TWORD)
12174                        raise_error_unexpected_syntax(TWORD);
12175                n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
12176                n2->type = NARG;
12177                /*n2->narg.next = NULL; - stzalloc did it */
12178                n2->narg.text = wordtext;
12179                n2->narg.backquote = backquotelist;
12180                checkkwd = CHKNL | CHKKWD | CHKALIAS;
12181                if (readtoken() != TIN)
12182                        raise_error_unexpected_syntax(TIN);
12183                cpp = &n1->ncase.cases;
12184 next_case:
12185                checkkwd = CHKNL | CHKKWD;
12186                t = readtoken();
12187                while (t != TESAC) {
12188                        if (lasttoken == TLP)
12189                                readtoken();
12190                        *cpp = cp = stzalloc(sizeof(struct nclist));
12191                        cp->type = NCLIST;
12192                        app = &cp->nclist.pattern;
12193                        for (;;) {
12194                                *app = ap = stzalloc(sizeof(struct narg));
12195                                ap->type = NARG;
12196                                /*ap->narg.next = NULL; - stzalloc did it */
12197                                ap->narg.text = wordtext;
12198                                ap->narg.backquote = backquotelist;
12199                                if (readtoken() != TPIPE)
12200                                        break;
12201                                app = &ap->narg.next;
12202                                readtoken();
12203                        }
12204                        //ap->narg.next = NULL;
12205                        if (lasttoken != TRP)
12206                                raise_error_unexpected_syntax(TRP);
12207                        cp->nclist.body = list(2);
12208
12209                        cpp = &cp->nclist.next;
12210
12211                        checkkwd = CHKNL | CHKKWD;
12212                        t = readtoken();
12213                        if (t != TESAC) {
12214                                if (t != TENDCASE)
12215                                        raise_error_unexpected_syntax(TENDCASE);
12216                                goto next_case;
12217                        }
12218                }
12219                *cpp = NULL;
12220                goto redir;
12221        case TLP:
12222                n1 = stzalloc(sizeof(struct nredir));
12223                n1->type = NSUBSHELL;
12224                n1->nredir.linno = savelinno;
12225                n1->nredir.n = list(0);
12226                /*n1->nredir.redirect = NULL; - stzalloc did it */
12227                t = TRP;
12228                break;
12229        case TBEGIN:
12230                n1 = list(0);
12231                t = TEND;
12232                break;
12233        IF_BASH_FUNCTION(case TFUNCTION:)
12234        case TWORD:
12235        case TREDIR:
12236                tokpushback = 1;
12237                return simplecmd();
12238        }
12239
12240        if (readtoken() != t)
12241                raise_error_unexpected_syntax(t);
12242
12243 redir:
12244        /* Now check for redirection which may follow command */
12245        checkkwd = CHKKWD | CHKALIAS;
12246        rpp = rpp2;
12247        while (readtoken() == TREDIR) {
12248                *rpp = n2 = redirnode;
12249                rpp = &n2->nfile.next;
12250                parsefname();
12251        }
12252        tokpushback = 1;
12253        *rpp = NULL;
12254        if (redir) {
12255                if (n1->type != NSUBSHELL) {
12256                        n2 = stzalloc(sizeof(struct nredir));
12257                        n2->type = NREDIR;
12258                        n2->nredir.linno = savelinno;
12259                        n2->nredir.n = n1;
12260                        n1 = n2;
12261                }
12262                n1->nredir.redirect = redir;
12263        }
12264        return n1;
12265}
12266
12267#if BASH_DOLLAR_SQUOTE
12268static int
12269decode_dollar_squote(void)
12270{
12271        static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
12272        int c, cnt;
12273        char *p;
12274        char buf[4];
12275
12276        c = pgetc();
12277        p = strchr(C_escapes, c);
12278        if (p) {
12279                buf[0] = c;
12280                p = buf;
12281                cnt = 3;
12282                if ((unsigned char)(c - '0') <= 7) { /* \ooo */
12283                        do {
12284                                c = pgetc();
12285                                *++p = c;
12286                        } while ((unsigned char)(c - '0') <= 7 && --cnt);
12287                        pungetc();
12288                } else if (c == 'x') { /* \xHH */
12289                        do {
12290                                c = pgetc();
12291                                *++p = c;
12292                        } while (isxdigit(c) && --cnt);
12293                        pungetc();
12294                        if (cnt == 3) { /* \x but next char is "bad" */
12295                                c = 'x';
12296                                goto unrecognized;
12297                        }
12298                } else { /* simple seq like \\ or \t */
12299                        p++;
12300                }
12301                *p = '\0';
12302                p = buf;
12303                c = bb_process_escape_sequence((void*)&p);
12304        } else { /* unrecognized "\z": print both chars unless ' or " */
12305                if (c != '\'' && c != '"') {
12306 unrecognized:
12307                        c |= 0x100; /* "please encode \, then me" */
12308                }
12309        }
12310        return c;
12311}
12312#endif
12313
12314/* Used by expandstr to get here-doc like behaviour. */
12315#define FAKEEOFMARK ((char*)(uintptr_t)1)
12316
12317static ALWAYS_INLINE int
12318realeofmark(const char *eofmark)
12319{
12320        return eofmark && eofmark != FAKEEOFMARK;
12321}
12322
12323/*
12324 * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
12325 * is not NULL, read a here document.  In the latter case, eofmark is the
12326 * word which marks the end of the document and striptabs is true if
12327 * leading tabs should be stripped from the document.  The argument c
12328 * is the first character of the input token or document.
12329 *
12330 * Because C does not have internal subroutines, I have simulated them
12331 * using goto's to implement the subroutine linkage.  The following macros
12332 * will run code that appears at the end of readtoken1.
12333 */
12334#define CHECKEND()      {goto checkend; checkend_return:;}
12335#define PARSEREDIR()    {goto parseredir; parseredir_return:;}
12336#define PARSESUB()      {goto parsesub; parsesub_return:;}
12337#define PARSEBACKQOLD() {style = OLD; goto parsebackq; parsebackq_oldreturn:;}
12338#define PARSEBACKQNEW() {style = NEW; goto parsebackq; parsebackq_newreturn:;}
12339#define PARSEPROCSUB()  {style = PSUB; goto parsebackq; parsebackq_psreturn:;}
12340#define PARSEARITH()    {goto parsearith; parsearith_return:;}
12341static int
12342readtoken1(int c, int syntax, char *eofmark, int striptabs)
12343{
12344        /* NB: syntax parameter fits into smallint */
12345        /* c parameter is an unsigned char or PEOF or PEOA */
12346        char *out;
12347        size_t len;
12348        struct nodelist *bqlist;
12349        smallint quotef;
12350        smallint style;
12351        enum { OLD, NEW, PSUB };
12352#define oldstyle (style == OLD)
12353        smallint pssyntax;   /* we are expanding a prompt string */
12354        IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
12355        /* syntax stack */
12356        struct synstack synbase = { };
12357        struct synstack *synstack = &synbase;
12358
12359#if ENABLE_ASH_EXPAND_PRMT
12360        pssyntax = (syntax == PSSYNTAX);
12361        if (pssyntax)
12362                syntax = DQSYNTAX;
12363#else
12364        pssyntax = 0; /* constant */
12365#endif
12366        synstack->syntax = syntax;
12367
12368        if (syntax == DQSYNTAX)
12369                synstack->dblquote = 1;
12370        quotef = 0;
12371        bqlist = NULL;
12372
12373        STARTSTACKSTR(out);
12374 loop:
12375        /* For each line, until end of word */
12376        CHECKEND();     /* set c to PEOF if at end of here document */
12377        for (;;) {      /* until end of line or end of word */
12378                CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
12379                switch (SIT(c, synstack->syntax)) {
12380                case CNL:       /* '\n' */
12381                        if (synstack->syntax == BASESYNTAX
12382                         && !synstack->varnest
12383                        ) {
12384                                goto endword;   /* exit outer loop */
12385                        }
12386                        USTPUTC(c, out);
12387                        nlprompt();
12388                        c = pgetc_top(synstack);
12389                        goto loop;              /* continue outer loop */
12390                case CWORD:
12391                        USTPUTC(c, out);
12392                        break;
12393                case CCTL:
12394#if BASH_DOLLAR_SQUOTE
12395                        if (c == '\\' && bash_dollar_squote) {
12396                                c = decode_dollar_squote();
12397                                if (c == '\0') {
12398                                        /* skip $'\000', $'\x00' (like bash) */
12399                                        break;
12400                                }
12401                                if (c & 0x100) {
12402                                        /* Unknown escape. Encode as '\z' */
12403                                        c = (unsigned char)c;
12404                                        if (eofmark == NULL || synstack->dblquote)
12405                                                USTPUTC(CTLESC, out);
12406                                        USTPUTC('\\', out);
12407                                }
12408                        }
12409#endif
12410                        if (!eofmark || synstack->dblquote || synstack->varnest)
12411                                USTPUTC(CTLESC, out);
12412                        USTPUTC(c, out);
12413                        break;
12414                case CBACK:     /* backslash */
12415                        c = pgetc_without_PEOA();
12416                        if (c == PEOF) {
12417                                USTPUTC(CTLESC, out);
12418                                USTPUTC('\\', out);
12419                                pungetc();
12420                        } else {
12421                                if (pssyntax && c == '$') {
12422                                        USTPUTC(CTLESC, out);
12423                                        USTPUTC('\\', out);
12424                                }
12425                                /* Backslash is retained if we are in "str"
12426                                 * and next char isn't dquote-special.
12427                                 */
12428                                if (synstack->dblquote
12429                                 && c != '\\'
12430                                 && c != '`'
12431                                 && c != '$'
12432                                 && (c != '"' || (eofmark != NULL && !synstack->varnest))
12433                                 && (c != '}' || !synstack->varnest)
12434                                ) {
12435                                        USTPUTC(CTLESC, out); /* protect '\' from glob */
12436                                        USTPUTC('\\', out);
12437                                }
12438                                USTPUTC(CTLESC, out);
12439                                USTPUTC(c, out);
12440                                quotef = 1;
12441                        }
12442                        break;
12443                case CSQUOTE:
12444                        synstack->syntax = SQSYNTAX;
12445 quotemark:
12446                        if (eofmark == NULL) {
12447                                USTPUTC(CTLQUOTEMARK, out);
12448                        }
12449                        break;
12450                case CDQUOTE:
12451                        synstack->syntax = DQSYNTAX;
12452                        synstack->dblquote = 1;
12453 toggledq:
12454                        if (synstack->varnest)
12455                                synstack->innerdq ^= 1;
12456                        goto quotemark;
12457                case CENDQUOTE:
12458                        IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
12459                        if (eofmark != NULL && synstack->varnest == 0) {
12460                                USTPUTC(c, out);
12461                                break;
12462                        }
12463
12464                        if (synstack->dqvarnest == 0) {
12465                                synstack->syntax = BASESYNTAX;
12466                                synstack->dblquote = 0;
12467                        }
12468
12469                        quotef = 1;
12470
12471                        if (c == '"')
12472                                goto toggledq;
12473
12474                        goto quotemark;
12475                case CVAR:      /* '$' */
12476                        PARSESUB();             /* parse substitution */
12477                        break;
12478                case CENDVAR:   /* '}' */
12479                        if (!synstack->innerdq && synstack->varnest > 0) {
12480                                if (!--synstack->varnest && synstack->varpushed)
12481                                        synstack_pop(&synstack);
12482                                else if (synstack->dqvarnest > 0)
12483                                        synstack->dqvarnest--;
12484                                c = CTLENDVAR;
12485                        }
12486                        USTPUTC(c, out);
12487                        break;
12488#if ENABLE_FEATURE_SH_MATH
12489                case CLP:       /* '(' in arithmetic */
12490                        synstack->parenlevel++;
12491                        USTPUTC(c, out);
12492                        break;
12493                case CRP:       /* ')' in arithmetic */
12494                        if (synstack->parenlevel > 0) {
12495                                synstack->parenlevel--;
12496                        } else {
12497                                if (pgetc_eatbnl() == ')') {
12498                                        c = CTLENDARI;
12499                                        synstack_pop(&synstack);
12500                                } else {
12501                                        /*
12502                                         * unbalanced parens
12503                                         * (don't 2nd guess - no error)
12504                                         */
12505                                        pungetc();
12506                                }
12507                        }
12508                        USTPUTC(c, out);
12509                        break;
12510#endif
12511                case CBQUOTE:   /* '`' */
12512                        if (checkkwd & CHKEOFMARK) {
12513                                quotef = 1;
12514                                USTPUTC('`', out);
12515                                break;
12516                        }
12517
12518                        PARSEBACKQOLD();
12519                        break;
12520                case CENDFILE:
12521                        goto endword;           /* exit outer loop */
12522                case CIGN:
12523                        break;
12524                default:
12525                        if (synstack->varnest == 0) {
12526#if BASH_REDIR_OUTPUT
12527                                if (c == '&') {
12528//Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
12529                                        if (pgetc() == '>')
12530                                                c = 0x100 + '>'; /* flag &> */
12531                                        pungetc();
12532                                }
12533#endif
12534#if BASH_PROCESS_SUBST
12535                                if (c == '<' || c == '>') {
12536                                        if (pgetc() == '(') {
12537                                                PARSEPROCSUB();
12538                                                break;
12539                                        }
12540                                        pungetc();
12541                                }
12542#endif
12543                                goto endword;   /* exit outer loop */
12544                        }
12545                        IF_ASH_ALIAS(if (c != PEOA))
12546                                USTPUTC(c, out);
12547                }
12548                c = pgetc_top(synstack);
12549        } /* for (;;) */
12550 endword:
12551
12552#if ENABLE_FEATURE_SH_MATH
12553        if (synstack->syntax == ARISYNTAX)
12554                raise_error_syntax("missing '))'");
12555#endif
12556        if (synstack->syntax != BASESYNTAX && eofmark == NULL)
12557                raise_error_syntax("unterminated quoted string");
12558        if (synstack->varnest != 0) {
12559                /* { */
12560                raise_error_syntax("missing '}'");
12561        }
12562        USTPUTC('\0', out);
12563        len = out - (char *)stackblock();
12564        out = stackblock();
12565        if (eofmark == NULL) {
12566                if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
12567                 && quotef == 0
12568                ) {
12569                        if (isdigit_str9(out)) {
12570                                PARSEREDIR(); /* passed as params: out, c */
12571                                lasttoken = TREDIR;
12572                                return lasttoken;
12573                        }
12574                        /* else: non-number X seen, interpret it
12575                         * as "NNNX>file" = "NNNX >file" */
12576                }
12577                pungetc();
12578        }
12579        quoteflag = quotef;
12580        backquotelist = bqlist;
12581        grabstackblock(len);
12582        wordtext = out;
12583        lasttoken = TWORD;
12584        return lasttoken;
12585/* end of readtoken routine */
12586
12587/*
12588 * Check to see whether we are at the end of the here document.  When this
12589 * is called, c is set to the first character of the next input line.  If
12590 * we are at the end of the here document, this routine sets the c to PEOF.
12591 */
12592checkend: {
12593        if (realeofmark(eofmark)) {
12594                int markloc;
12595                char *p;
12596
12597#if ENABLE_ASH_ALIAS
12598                if (c == PEOA)
12599                        c = pgetc_without_PEOA();
12600#endif
12601                if (striptabs) {
12602                        while (c == '\t') {
12603                                c = pgetc_without_PEOA();
12604                        }
12605                }
12606
12607                markloc = out - (char *)stackblock();
12608                for (p = eofmark; STPUTC(c, out), *p; p++) {
12609                        if (c != *p)
12610                                goto more_heredoc;
12611                        /* FIXME: fails for backslash-newlined terminator:
12612                         * cat <<EOF
12613                         * ...
12614                         * EO\
12615                         * F
12616                         * (see heredoc_bkslash_newline2.tests)
12617                         */
12618                        c = pgetc_without_PEOA();
12619                }
12620
12621                if (c == '\n' || c == PEOF) {
12622                        c = PEOF;
12623                        g_parsefile->linno++;
12624                        needprompt = doprompt;
12625                } else {
12626                        int len_here;
12627
12628 more_heredoc:
12629                        p = (char *)stackblock() + markloc + 1;
12630                        len_here = out - p;
12631
12632                        if (len_here) {
12633                                len_here -= (c >= PEOF);
12634                                c = p[-1];
12635
12636                                if (len_here) {
12637                                        char *str;
12638
12639                                        str = alloca(len_here + 1);
12640                                        *(char *)mempcpy(str, p, len_here) = '\0';
12641
12642                                        pushstring(str, NULL);
12643                                }
12644                        }
12645                }
12646
12647                STADJUST((char *)stackblock() + markloc - out, out);
12648        }
12649        goto checkend_return;
12650}
12651
12652/*
12653 * Parse a redirection operator.  The variable "out" points to a string
12654 * specifying the fd to be redirected.  The variable "c" contains the
12655 * first character of the redirection operator.
12656 */
12657parseredir: {
12658        /* out is already checked to be a valid number or "" */
12659        int fd = (*out == '\0' ? -1 : atoi(out));
12660        union node *np;
12661
12662        np = stzalloc(sizeof(struct nfile));
12663        if (c == '>') {
12664                np->nfile.fd = 1;
12665                c = pgetc_eatbnl();
12666                if (c == '>')
12667                        np->type = NAPPEND;
12668                else if (c == '|')
12669                        np->type = NCLOBBER;
12670                else if (c == '&')
12671                        np->type = NTOFD;
12672                        /* it also can be NTO2 (>&file), but we can't figure it out yet */
12673                else {
12674                        np->type = NTO;
12675                        pungetc();
12676                }
12677        }
12678#if BASH_REDIR_OUTPUT
12679        else if (c == 0x100 + '>') { /* this flags &> redirection */
12680                np->nfile.fd = 1;
12681                pgetc(); /* this is '>', no need to check */
12682                np->type = NTO2;
12683        }
12684#endif
12685        else { /* c == '<' */
12686                /*np->nfile.fd = 0; - stzalloc did it */
12687                c = pgetc_eatbnl();
12688                switch (c) {
12689                case '<':
12690                        if (sizeof(struct nfile) != sizeof(struct nhere)) {
12691                                np = stzalloc(sizeof(struct nhere));
12692                                /*np->nfile.fd = 0; - stzalloc did it */
12693                        }
12694                        np->type = NHERE;
12695                        heredoc = stzalloc(sizeof(struct heredoc));
12696                        heredoc->here = np;
12697                        c = pgetc_eatbnl();
12698                        if (c == '-') {
12699                                heredoc->striptabs = 1;
12700                        } else {
12701                                /*heredoc->striptabs = 0; - stzalloc did it */
12702                                pungetc();
12703                        }
12704                        break;
12705
12706                case '&':
12707                        np->type = NFROMFD;
12708                        break;
12709
12710                case '>':
12711                        np->type = NFROMTO;
12712                        break;
12713
12714                default:
12715                        np->type = NFROM;
12716                        pungetc();
12717                        break;
12718                }
12719        }
12720        if (fd >= 0)
12721                np->nfile.fd = fd;
12722        redirnode = np;
12723        goto parseredir_return;
12724}
12725
12726/*
12727 * Parse a substitution.  At this point, we have read the dollar sign
12728 * and nothing else.
12729 */
12730
12731/* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12732 * (assuming ascii char codes, as the original implementation did) */
12733#define is_special(c) \
12734        (((unsigned)(c) - 33 < 32) \
12735                        && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12736parsesub: {
12737        unsigned char subtype;
12738        int typeloc;
12739
12740        c = pgetc_eatbnl();
12741        if ((checkkwd & CHKEOFMARK)
12742         || c > 255 /* PEOA or PEOF */
12743         || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12744        ) {
12745#if BASH_DOLLAR_SQUOTE
12746                if (synstack->syntax != DQSYNTAX && c == '\'')
12747                        bash_dollar_squote = 1;
12748                else
12749#endif
12750                        USTPUTC('$', out);
12751                pungetc();
12752        } else if (c == '(') {
12753                /* $(command) or $((arith)) */
12754                if (pgetc_eatbnl() == '(') {
12755#if ENABLE_FEATURE_SH_MATH
12756                        PARSEARITH();
12757#else
12758                        raise_error_syntax("support for $((arith)) is disabled");
12759#endif
12760                } else {
12761                        pungetc();
12762                        PARSEBACKQNEW();
12763                }
12764        } else {
12765                /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12766                smalluint newsyn = synstack->syntax;
12767
12768                USTPUTC(CTLVAR, out);
12769                typeloc = out - (char *)stackblock();
12770                STADJUST(1, out);
12771                subtype = VSNORMAL;
12772                if (c == '{') {
12773                        c = pgetc_eatbnl();
12774                        subtype = 0;
12775                }
12776 varname:
12777                if (is_name(c)) {
12778                        /* $[{[#]]NAME[}] */
12779                        do {
12780                                STPUTC(c, out);
12781                                c = pgetc_eatbnl();
12782                        } while (is_in_name(c));
12783                } else if (isdigit(c)) {
12784                        /* $[{[#]]NUM[}] */
12785                        do {
12786                                STPUTC(c, out);
12787                                c = pgetc_eatbnl();
12788                        } while ((subtype == 0 || subtype == VSLENGTH) && isdigit(c));
12789                } else if (c != '}') {
12790                        /* $[{[#]]<specialchar>[}] */
12791                        int cc = c;
12792
12793                        c = pgetc_eatbnl();
12794                        if (!subtype && cc == '#') {
12795                                subtype = VSLENGTH;
12796                                if (c == '_' || isalnum(c))
12797                                        goto varname;
12798                                cc = c;
12799                                c = pgetc_eatbnl();
12800                                if (cc == '}' || c != '}') {
12801                                        pungetc();
12802                                        subtype = 0;
12803                                        c = cc;
12804                                        cc = '#';
12805                                }
12806                        }
12807
12808                        if (!is_special(cc)) {
12809                                if (subtype == VSLENGTH)
12810                                        subtype = 0;
12811                                goto badsub;
12812                        }
12813
12814                        USTPUTC(cc, out);
12815                } else
12816                        goto badsub;
12817
12818                if (subtype == 0) {
12819                        static const char types[] ALIGN1 = "}-+?=";
12820                        /* ${VAR...} but not $VAR or ${#VAR} */
12821                        /* c == first char after VAR */
12822                        int cc = c;
12823
12824                        switch (c) {
12825                        case ':':
12826                                c = pgetc_eatbnl();
12827#if BASH_SUBSTR
12828                                /* This check is only needed to not misinterpret
12829                                 * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12830                                 * constructs.
12831                                 */
12832                                if (!strchr(types, c)) {
12833                                        subtype = VSSUBSTR;
12834                                        pungetc();
12835                                        break; /* "goto badsub" is bigger (!) */
12836                                }
12837#endif
12838                                subtype = VSNUL;
12839                                /*FALLTHROUGH*/
12840                        default: {
12841                                const char *p = strchr(types, c);
12842                                if (p == NULL)
12843                                        break;
12844                                subtype |= p - types + VSNORMAL;
12845                                break;
12846                        }
12847                        case '%':
12848                        case '#':
12849                                subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12850                                c = pgetc_eatbnl();
12851                                if (c == cc)
12852                                        subtype++;
12853                                else
12854                                        pungetc();
12855
12856                                newsyn = BASESYNTAX;
12857                                break;
12858#if BASH_PATTERN_SUBST
12859                        case '/':
12860                                /* ${v/[/]pattern/repl} */
12861//TODO: encode pattern and repl separately.
12862// Currently cases like: v=1;echo ${v/$((1/1))/ONE}
12863// are broken (should print "ONE")
12864                                subtype = VSREPLACE;
12865                                newsyn = BASESYNTAX;
12866                                c = pgetc_eatbnl();
12867                                if (c != '/')
12868                                        goto badsub;
12869                                subtype++; /* VSREPLACEALL */
12870                                break;
12871#endif
12872                        }
12873                } else {
12874                        if (subtype == VSLENGTH && c != '}')
12875                                subtype = 0;
12876 badsub:
12877                        pungetc();
12878                }
12879
12880                if (newsyn == ARISYNTAX)
12881                        newsyn = DQSYNTAX;
12882
12883                if ((newsyn != synstack->syntax || synstack->innerdq)
12884                 && subtype != VSNORMAL
12885                ) {
12886                        synstack_push(&synstack,
12887                                synstack->prev ?: alloca(sizeof(*synstack)),
12888                                newsyn);
12889
12890                        synstack->varpushed = 1;
12891                        synstack->dblquote = newsyn != BASESYNTAX;
12892                }
12893
12894                ((unsigned char *)stackblock())[typeloc] = subtype;
12895                if (subtype != VSNORMAL) {
12896                        synstack->varnest++;
12897                        if (synstack->dblquote)
12898                                synstack->dqvarnest++;
12899                }
12900                STPUTC('=', out);
12901        }
12902        goto parsesub_return;
12903}
12904
12905/*
12906 * Called to parse command substitutions.  Newstyle is set if the command
12907 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12908 * list of commands (passed by reference), and savelen is the number of
12909 * characters on the top of the stack which must be preserved.
12910 */
12911parsebackq: {
12912        struct nodelist **nlpp;
12913        union node *n;
12914        char *str;
12915        size_t savelen;
12916        struct heredoc *saveheredoclist;
12917        smallint saveprompt = 0;
12918
12919        str = NULL;
12920        savelen = out - (char *)stackblock();
12921        if (savelen > 0) {
12922                /*
12923                 * FIXME: this can allocate very large block on stack and SEGV.
12924                 * Example:
12925                 * echo "..<100kbytes>..`true` $(true) `true` ..."
12926                 * allocates 100kb for every command subst. With about
12927                 * a hundred command substitutions stack overflows.
12928                 * With larger prepended string, SEGV happens sooner.
12929                 */
12930                str = alloca(savelen);
12931                memcpy(str, stackblock(), savelen);
12932        }
12933
12934        if (oldstyle) {
12935                /* We must read until the closing backquote, giving special
12936                 * treatment to some slashes, and then push the string and
12937                 * reread it as input, interpreting it normally.
12938                 */
12939                char *pout;
12940                size_t psavelen;
12941                char *pstr;
12942
12943                STARTSTACKSTR(pout);
12944                for (;;) {
12945                        int pc;
12946
12947                        setprompt_if(needprompt, 2);
12948                        pc = pgetc_eatbnl();
12949                        switch (pc) {
12950                        case '`':
12951                                goto done;
12952
12953                        case '\\':
12954                                pc = pgetc(); /* not pgetc_eatbnl! */
12955                                if (pc != '\\' && pc != '`' && pc != '$'
12956                                 && (!synstack->dblquote || pc != '"')
12957                                ) {
12958                                        STPUTC('\\', pout);
12959                                }
12960                                if (pc <= 255 /* not PEOA or PEOF */) {
12961                                        break;
12962                                }
12963                                /* fall through */
12964
12965                        case PEOF:
12966                        IF_ASH_ALIAS(case PEOA:)
12967                                raise_error_syntax("EOF in backquote substitution");
12968
12969                        case '\n':
12970                                nlnoprompt();
12971                                break;
12972
12973                        default:
12974                                break;
12975                        }
12976                        STPUTC(pc, pout);
12977                }
12978 done:
12979                STPUTC('\0', pout);
12980                psavelen = pout - (char *)stackblock();
12981                if (psavelen > 0) {
12982                        pstr = grabstackstr(pout);
12983                        setinputstring(pstr);
12984                }
12985        }
12986        nlpp = &bqlist;
12987        while (*nlpp)
12988                nlpp = &(*nlpp)->next;
12989        *nlpp = stzalloc(sizeof(**nlpp));
12990        /* (*nlpp)->next = NULL; - stzalloc did it */
12991
12992        saveheredoclist = heredoclist;
12993        heredoclist = NULL;
12994
12995        if (oldstyle) {
12996                saveprompt = doprompt;
12997                doprompt = 0;
12998        }
12999
13000        n = list(2);
13001
13002        if (oldstyle)
13003                doprompt = saveprompt;
13004        else {
13005                if (readtoken() != TRP)
13006                        raise_error_unexpected_syntax(TRP);
13007                setinputstring(nullstr);
13008        }
13009
13010        parseheredoc();
13011        heredoclist = saveheredoclist;
13012
13013        (*nlpp)->n = n;
13014        /* Start reading from old file again. */
13015        popfile();
13016        /* Ignore any pushed back tokens left from the backquote parsing. */
13017        if (oldstyle)
13018                tokpushback = 0;
13019        out = growstackto(savelen + 1);
13020        if (str) {
13021                memcpy(out, str, savelen);
13022                STADJUST(savelen, out);
13023        }
13024#if BASH_PROCESS_SUBST
13025        if (style == PSUB)
13026                USTPUTC(c == '<' ? CTLFROMPROC : CTLTOPROC, out);
13027        else
13028#endif
13029                USTPUTC(CTLBACKQ, out);
13030        if (oldstyle)
13031                goto parsebackq_oldreturn;
13032#if BASH_PROCESS_SUBST
13033        else if (style == PSUB)
13034                goto parsebackq_psreturn;
13035#endif
13036        goto parsebackq_newreturn;
13037}
13038
13039#if ENABLE_FEATURE_SH_MATH
13040/*
13041 * Parse an arithmetic expansion (indicate start of one and set state)
13042 */
13043parsearith: {
13044
13045        synstack_push(&synstack,
13046                        synstack->prev ?: alloca(sizeof(*synstack)),
13047                        ARISYNTAX);
13048        synstack->dblquote = 1;
13049        USTPUTC(CTLARI, out);
13050        goto parsearith_return;
13051}
13052#endif
13053} /* end of readtoken */
13054
13055/*
13056 * Read the next input token.
13057 * If the token is a word, we set backquotelist to the list of cmds in
13058 *      backquotes.  We set quoteflag to true if any part of the word was
13059 *      quoted.
13060 * If the token is TREDIR, then we set redirnode to a structure containing
13061 *      the redirection.
13062 *
13063 * [Change comment:  here documents and internal procedures]
13064 * [Readtoken shouldn't have any arguments.  Perhaps we should make the
13065 *  word parsing code into a separate routine.  In this case, readtoken
13066 *  doesn't need to have any internal procedures, but parseword does.
13067 *  We could also make parseoperator in essence the main routine, and
13068 *  have parseword (readtoken1?) handle both words and redirection.]
13069 */
13070#define NEW_xxreadtoken
13071#ifdef NEW_xxreadtoken
13072/* singles must be first! */
13073static const char xxreadtoken_chars[7] ALIGN1 = {
13074        '\n', '(', ')', /* singles */
13075        '&', '|', ';',  /* doubles */
13076        0
13077};
13078
13079#define xxreadtoken_singles 3
13080#define xxreadtoken_doubles 3
13081
13082static const char xxreadtoken_tokens[] ALIGN1 = {
13083        TNL, TLP, TRP,          /* only single occurrence allowed */
13084        TBACKGND, TPIPE, TSEMI, /* if single occurrence */
13085        TEOF,                   /* corresponds to trailing nul */
13086        TAND, TOR, TENDCASE     /* if double occurrence */
13087};
13088
13089static int
13090xxreadtoken(void)
13091{
13092        int c;
13093
13094        if (tokpushback) {
13095                tokpushback = 0;
13096                return lasttoken;
13097        }
13098        setprompt_if(needprompt, 2);
13099        for (;;) {                      /* until token or start of word found */
13100                c = pgetc_eatbnl();
13101                if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
13102                        continue;
13103
13104                if (c == '#') {
13105                        while ((c = pgetc()) != '\n' && c != PEOF)
13106                                continue;
13107                        pungetc();
13108                } else if (c == '\\') {
13109                        break; /* return readtoken1(...) */
13110                } else {
13111                        const char *p;
13112
13113                        p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
13114                        if (c != PEOF) {
13115                                if (c == '\n') {
13116                                        nlnoprompt();
13117                                }
13118
13119                                p = strchr(xxreadtoken_chars, c);
13120                                if (p == NULL)
13121                                        break; /* return readtoken1(...) */
13122
13123                                if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
13124                                        int cc = pgetc_eatbnl();
13125                                        if (cc == c) {    /* double occurrence? */
13126                                                p += xxreadtoken_doubles + 1;
13127                                        } else {
13128                                                pungetc();
13129#if BASH_REDIR_OUTPUT
13130                                                if (c == '&' && cc == '>') /* &> */
13131                                                        break; /* return readtoken1(...) */
13132#endif
13133                                        }
13134                                }
13135                        }
13136                        lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
13137                        return lasttoken;
13138                }
13139        } /* for (;;) */
13140
13141        return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
13142}
13143#else /* old xxreadtoken */
13144#define RETURN(token)   return lasttoken = token
13145static int
13146xxreadtoken(void)
13147{
13148        int c;
13149
13150        if (tokpushback) {
13151                tokpushback = 0;
13152                return lasttoken;
13153        }
13154        setprompt_if(needprompt, 2);
13155        for (;;) {      /* until token or start of word found */
13156                c = pgetc_eatbnl();
13157                switch (c) {
13158                case ' ': case '\t':
13159                IF_ASH_ALIAS(case PEOA:)
13160                        continue;
13161                case '#':
13162                        while ((c = pgetc()) != '\n' && c != PEOF)
13163                                continue;
13164                        pungetc();
13165                        continue;
13166                case '\n':
13167                        nlnoprompt();
13168                        RETURN(TNL);
13169                case PEOF:
13170                        RETURN(TEOF);
13171                case '&':
13172                        if (pgetc_eatbnl() == '&')
13173                                RETURN(TAND);
13174                        pungetc();
13175                        RETURN(TBACKGND);
13176                case '|':
13177                        if (pgetc_eatbnl() == '|')
13178                                RETURN(TOR);
13179                        pungetc();
13180                        RETURN(TPIPE);
13181                case ';':
13182                        if (pgetc_eatbnl() == ';')
13183                                RETURN(TENDCASE);
13184                        pungetc();
13185                        RETURN(TSEMI);
13186                case '(':
13187                        RETURN(TLP);
13188                case ')':
13189                        RETURN(TRP);
13190                }
13191                break;
13192        }
13193        return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
13194#undef RETURN
13195}
13196#endif /* old xxreadtoken */
13197
13198static int
13199readtoken(void)
13200{
13201        int t;
13202        int kwd = checkkwd;
13203#if DEBUG
13204        smallint alreadyseen = tokpushback;
13205#endif
13206
13207#if ENABLE_ASH_ALIAS
13208 top:
13209#endif
13210
13211        t = xxreadtoken();
13212
13213        /*
13214         * eat newlines
13215         */
13216        if (kwd & CHKNL) {
13217                while (t == TNL) {
13218                        parseheredoc();
13219                        t = xxreadtoken();
13220                }
13221        }
13222
13223        if (t != TWORD || quoteflag) {
13224                goto out;
13225        }
13226
13227        /*
13228         * check for keywords
13229         */
13230        if (kwd & CHKKWD) {
13231                const char *const *pp;
13232
13233                pp = findkwd(wordtext);
13234                if (pp) {
13235                        lasttoken = t = pp - tokname_array;
13236                        TRACE(("keyword '%s' recognized\n", tokname_array[t]));
13237                        goto out;
13238                }
13239        }
13240
13241        if (checkkwd & CHKALIAS) {
13242#if ENABLE_ASH_ALIAS
13243                struct alias *ap;
13244                ap = lookupalias(wordtext, 1);
13245                if (ap != NULL) {
13246                        if (*ap->val) {
13247                                pushstring(ap->val, ap);
13248                        }
13249                        goto top;
13250                }
13251#endif
13252        }
13253 out:
13254        checkkwd = 0;
13255#if DEBUG
13256        if (!alreadyseen)
13257                TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
13258        else
13259                TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
13260#endif
13261        return t;
13262}
13263
13264static int
13265peektoken(void)
13266{
13267        int t;
13268
13269        t = readtoken();
13270        tokpushback = 1;
13271        return t;
13272}
13273
13274/*
13275 * Read and parse a command.  Returns NODE_EOF on end of file.
13276 * (NULL is a valid parse tree indicating a blank line.)
13277 */
13278static union node *
13279parsecmd(int interact)
13280{
13281        tokpushback = 0;
13282        checkkwd = 0;
13283        heredoclist = 0;
13284        doprompt = interact;
13285        setprompt_if(doprompt, doprompt);
13286        needprompt = 0;
13287        return list(1);
13288}
13289
13290/*
13291 * Input any here documents.
13292 */
13293static void
13294parseheredoc(void)
13295{
13296        struct heredoc *here;
13297        union node *n;
13298
13299        here = heredoclist;
13300        heredoclist = NULL;
13301
13302        while (here) {
13303                tokpushback = 0;
13304                setprompt_if(needprompt, 2);
13305                if (here->here->type == NHERE)
13306                        readtoken1(pgetc(), SQSYNTAX, here->eofmark, here->striptabs);
13307                else
13308                        readtoken1(pgetc_eatbnl(), DQSYNTAX, here->eofmark, here->striptabs);
13309                n = stzalloc(sizeof(struct narg));
13310                n->narg.type = NARG;
13311                /*n->narg.next = NULL; - stzalloc did it */
13312                n->narg.text = wordtext;
13313                n->narg.backquote = backquotelist;
13314                here->here->nhere.doc = n;
13315                here = here->next;
13316        }
13317}
13318
13319
13320static const char *
13321expandstr(const char *ps, int syntax_type)
13322{
13323        union node n;
13324        int saveprompt;
13325        struct parsefile *file_stop = g_parsefile;
13326        volatile int saveint;
13327        struct jmploc *volatile savehandler = exception_handler;
13328        struct jmploc jmploc;
13329        const char *volatile result;
13330        int err;
13331
13332        /* XXX Fix (char *) cast. */
13333        setinputstring((char *)ps);
13334
13335        saveprompt = doprompt;
13336        doprompt = 0;
13337        result = ps;
13338
13339        SAVE_INT(saveint);
13340        err = setjmp(jmploc.loc);
13341        if (err)
13342                goto out;
13343
13344        /* readtoken1() might die horribly.
13345         * Try a prompt with syntactically wrong command:
13346         * PS1='$(date "+%H:%M:%S) > '
13347         */
13348        exception_handler = &jmploc;
13349        readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
13350
13351        n.narg.type = NARG;
13352        n.narg.next = NULL;
13353        n.narg.text = wordtext;
13354        n.narg.backquote = backquotelist;
13355
13356        /* expandarg() might fail too:
13357         * PS1='$((123+))'
13358         */
13359        expandarg(&n, NULL, EXP_QUOTED);
13360        result = stackblock();
13361
13362out:
13363        exception_handler = savehandler;
13364        if (err && exception_type != EXERROR)
13365                longjmp(exception_handler->loc, 1);
13366        RESTORE_INT(saveint);
13367
13368        doprompt = saveprompt;
13369        /* Try: PS1='`xxx(`' */
13370        unwindfiles(file_stop);
13371
13372        return result;
13373}
13374
13375static inline int
13376parser_eof(void)
13377{
13378        return tokpushback && lasttoken == TEOF;
13379}
13380
13381/*
13382 * Execute a command or commands contained in a string.
13383 */
13384static int
13385evalstring(char *s, int flags)
13386{
13387        struct jmploc *volatile savehandler;
13388        struct jmploc jmploc;
13389        int ex;
13390
13391        union node *n;
13392        struct stackmark smark;
13393        int status;
13394
13395        s = sstrdup(s);
13396        setinputstring(s);
13397        setstackmark(&smark);
13398
13399        status = 0;
13400        /* On exception inside execution loop, we must popfile().
13401         * Try interactively:
13402         *      readonly a=a
13403         *      command eval "a=b"  # throws "is read only" error
13404         * "command BLTIN" is not supposed to abort (even in non-interactive use).
13405         * But if we skip popfile(), we hit EOF in eval's string, and exit.
13406         */
13407        savehandler = exception_handler;
13408        ex = setjmp(jmploc.loc);
13409        if (ex)
13410                goto out;
13411        exception_handler = &jmploc;
13412
13413        while ((n = parsecmd(0)) != NODE_EOF) {
13414                int i;
13415
13416                i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
13417                if (n)
13418                        status = i;
13419                popstackmark(&smark);
13420                if (evalskip)
13421                        break;
13422        }
13423 out:
13424        popstackmark(&smark);
13425        popfile();
13426        stunalloc(s);
13427
13428        exception_handler = savehandler;
13429        if (ex)
13430                longjmp(exception_handler->loc, ex);
13431
13432        return status;
13433}
13434
13435/*
13436 * The eval command.
13437 */
13438static int FAST_FUNC
13439evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
13440{
13441        char *p;
13442        char *concat;
13443
13444        if (argv[1]) {
13445                p = argv[1];
13446                argv += 2;
13447                if (argv[0]) {
13448                        STARTSTACKSTR(concat);
13449                        for (;;) {
13450                                concat = stack_putstr(p, concat);
13451                                p = *argv++;
13452                                if (p == NULL)
13453                                        break;
13454                                STPUTC(' ', concat);
13455                        }
13456                        STPUTC('\0', concat);
13457                        p = grabstackstr(concat);
13458                }
13459                return evalstring(p, flags & EV_TESTED);
13460        }
13461        return 0;
13462}
13463
13464/*
13465 * Read and execute commands.
13466 * "Top" is nonzero for the top level command loop;
13467 * it turns on prompting if the shell is interactive.
13468 */
13469static int
13470cmdloop(int top)
13471{
13472        union node *n;
13473        struct stackmark smark;
13474        int inter;
13475        int status = 0;
13476        int numeof = 0;
13477
13478        TRACE(("cmdloop(%d) called\n", top));
13479        for (;;) {
13480                int skip;
13481
13482                setstackmark(&smark);
13483#if JOBS
13484                if (doing_jobctl)
13485                        showjobs(SHOW_CHANGED|SHOW_STDERR);
13486#endif
13487                inter = 0;
13488                if (iflag && top) {
13489                        inter++;
13490                        chkmail();
13491                }
13492                n = parsecmd(inter);
13493#if DEBUG
13494                if (DEBUG > 2 && debug && (n != NODE_EOF))
13495                        showtree(n);
13496#endif
13497                if (n == NODE_EOF) {
13498                        if (!top || numeof >= 50)
13499                                break;
13500                        if (!stoppedjobs()) {
13501                                if (!Iflag) {
13502                                        if (iflag) {
13503                                                newline_and_flush(stderr);
13504                                        }
13505                                        break;
13506                                }
13507                                out2str("\nUse \"exit\" to leave shell.\n");
13508                        }
13509                        numeof++;
13510                } else if (nflag == 0) {
13511                        int i;
13512
13513                        /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
13514                        job_warning >>= 1;
13515                        numeof = 0;
13516                        i = evaltree(n, 0);
13517                        if (n)
13518                                status = i;
13519                }
13520                popstackmark(&smark);
13521                skip = evalskip;
13522
13523                if (skip) {
13524                        evalskip &= ~(SKIPFUNC | SKIPFUNCDEF);
13525                        break;
13526                }
13527        }
13528        return status;
13529}
13530
13531/*
13532 * Take commands from a file.  To be compatible we should do a path
13533 * search for the file, which is necessary to find sub-commands.
13534 */
13535static char *
13536find_dot_file(char *basename)
13537{
13538        char *fullname;
13539        const char *path = pathval();
13540        struct stat statb;
13541        int len;
13542
13543        /* don't try this for absolute or relative paths */
13544        if (strchr(basename, '/'))
13545                return basename;
13546
13547        while ((len = padvance(&path, basename)) >= 0) {
13548                fullname = stackblock();
13549                if ((!pathopt || *pathopt == 'f')
13550                 && !stat(fullname, &statb) && S_ISREG(statb.st_mode)
13551                ) {
13552                        /* This will be freed by the caller. */
13553                        return stalloc(len);
13554                }
13555        }
13556        /* not found in PATH */
13557
13558#if ENABLE_ASH_BASH_SOURCE_CURDIR
13559        return basename;
13560#else
13561        ash_msg_and_raise_error("%s: not found", basename);
13562        /* NOTREACHED */
13563#endif
13564}
13565
13566static int FAST_FUNC
13567dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
13568{
13569        /* "false; . empty_file; echo $?" should print 0, not 1: */
13570        int status = 0;
13571        char *fullname;
13572        char **argv;
13573        char *args_need_save;
13574        volatile struct shparam saveparam;
13575
13576//???
13577//      struct strlist *sp;
13578//      for (sp = cmdenviron; sp; sp = sp->next)
13579//              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
13580
13581        nextopt(nullstr); /* handle possible "--" */
13582        argv = argptr;
13583
13584        if (!argv[0]) {
13585                /* bash says: "bash: .: filename argument required" */
13586                return 2; /* bash compat */
13587        }
13588
13589        /* This aborts if file isn't found, which is POSIXly correct.
13590         * bash returns exitcode 1 instead.
13591         */
13592        fullname = find_dot_file(argv[0]);
13593        argv++;
13594        args_need_save = argv[0];
13595        if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
13596                int argc;
13597                saveparam = shellparam;
13598                shellparam.malloced = 0;
13599                argc = 1;
13600                while (argv[argc])
13601                        argc++;
13602                shellparam.nparam = argc;
13603                shellparam.p = argv;
13604        };
13605
13606        /* This aborts if file can't be opened, which is POSIXly correct.
13607         * bash returns exitcode 1 instead.
13608         */
13609        setinputfile(fullname, INPUT_PUSH_FILE);
13610        commandname = fullname;
13611        status = cmdloop(0);
13612        popfile();
13613
13614        if (args_need_save) {
13615                freeparam(&shellparam);
13616                shellparam = saveparam;
13617        };
13618
13619        return status;
13620}
13621
13622static int FAST_FUNC
13623exitcmd(int argc UNUSED_PARAM, char **argv)
13624{
13625        if (stoppedjobs())
13626                return 0;
13627
13628        if (argv[1])
13629                savestatus = number(argv[1]);
13630
13631        raise_exception(EXEXIT);
13632        /* NOTREACHED */
13633}
13634
13635/*
13636 * Read a file containing shell functions.
13637 */
13638static void
13639readcmdfile(char *name)
13640{
13641        setinputfile(name, INPUT_PUSH_FILE);
13642        cmdloop(0);
13643        popfile();
13644}
13645
13646
13647/* ============ find_command inplementation */
13648
13649/*
13650 * Resolve a command name.  If you change this routine, you may have to
13651 * change the shellexec routine as well.
13652 */
13653static void
13654find_command(char *name, struct cmdentry *entry, int act, const char *path)
13655{
13656        struct tblentry *cmdp;
13657        int idx;
13658        int prev;
13659        char *fullname;
13660        struct stat statb;
13661        int e;
13662        int updatetbl;
13663        struct builtincmd *bcmd;
13664        int len;
13665
13666        /* If name contains a slash, don't use PATH or hash table */
13667        if (strchr(name, '/') != NULL) {
13668                entry->u.index = -1;
13669                if (act & DO_ABS) {
13670                        while (stat(name, &statb) < 0) {
13671#ifdef SYSV
13672                                if (errno == EINTR)
13673                                        continue;
13674#endif
13675                                entry->cmdtype = CMDUNKNOWN;
13676                                return;
13677                        }
13678                }
13679                entry->cmdtype = CMDNORMAL;
13680                return;
13681        }
13682
13683/* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
13684
13685        updatetbl = (path == pathval());
13686        if (!updatetbl)
13687                act |= DO_ALTPATH;
13688
13689        /* If name is in the table, check answer will be ok */
13690        cmdp = cmdlookup(name, 0);
13691        if (cmdp != NULL) {
13692                int bit;
13693
13694                switch (cmdp->cmdtype) {
13695                default:
13696#if DEBUG
13697                        abort();
13698#endif
13699                case CMDNORMAL:
13700                        bit = DO_ALTPATH | DO_REGBLTIN;
13701                        break;
13702                case CMDFUNCTION:
13703                        bit = DO_NOFUNC;
13704                        break;
13705                case CMDBUILTIN:
13706                        bit = IS_BUILTIN_REGULAR(cmdp->param.cmd) ? 0 : DO_REGBLTIN;
13707                        break;
13708                }
13709                if (act & bit) {
13710                        if (act & bit & DO_REGBLTIN)
13711                                goto fail;
13712
13713                        updatetbl = 0;
13714                        cmdp = NULL;
13715                } else if (cmdp->rehash == 0)
13716                        /* if not invalidated by cd, we're done */
13717                        goto success;
13718        }
13719
13720        /* If %builtin not in path, check for builtin next */
13721        bcmd = find_builtin(name);
13722        if (bcmd) {
13723                if (IS_BUILTIN_REGULAR(bcmd))
13724                        goto builtin_success;
13725                if (act & DO_ALTPATH)
13726                        goto builtin_success;
13727                if (builtinloc <= 0)
13728                        goto builtin_success;
13729        }
13730
13731        if (act & DO_REGBLTIN)
13732                goto fail;
13733
13734#if ENABLE_FEATURE_SH_STANDALONE
13735        {
13736                int applet_no = find_applet_by_name(name);
13737                if (applet_no >= 0) {
13738                        entry->cmdtype = CMDNORMAL;
13739                        entry->u.index = -2 - applet_no;
13740                        return;
13741                }
13742        }
13743#endif
13744
13745        /* We have to search path. */
13746        prev = -1;              /* where to start */
13747        if (cmdp && cmdp->rehash) {     /* doing a rehash */
13748                if (cmdp->cmdtype == CMDBUILTIN)
13749                        prev = builtinloc;
13750                else
13751                        prev = cmdp->param.index;
13752        }
13753
13754        e = ENOENT;
13755        idx = -1;
13756 loop:
13757        while ((len = padvance(&path, name)) >= 0) {
13758                const char *lpathopt = pathopt;
13759
13760                fullname = stackblock();
13761                idx++;
13762                if (lpathopt) {
13763                        if (*lpathopt == 'b') {
13764                                if (bcmd)
13765                                        goto builtin_success;
13766                                continue;
13767                        } else if (!(act & DO_NOFUNC)) {
13768                                /* handled below */
13769                        } else {
13770                                /* ignore unimplemented options */
13771                                continue;
13772                        }
13773                }
13774                /* if rehash, don't redo absolute path names */
13775                if (fullname[0] == '/' && idx <= prev) {
13776                        if (idx < prev)
13777                                continue;
13778                        TRACE(("searchexec \"%s\": no change\n", name));
13779                        goto success;
13780                }
13781                while (stat(fullname, &statb) < 0) {
13782#ifdef SYSV
13783                        if (errno == EINTR)
13784                                continue;
13785#endif
13786                        if (errno != ENOENT && errno != ENOTDIR)
13787                                e = errno;
13788                        goto loop;
13789                }
13790                e = EACCES;     /* if we fail, this will be the error */
13791                if (!S_ISREG(statb.st_mode))
13792                        continue;
13793                if (lpathopt) {          /* this is a %func directory */
13794                        stalloc(len);
13795                        /* NB: stalloc will return space pointed by fullname
13796                         * (because we don't have any intervening allocations
13797                         * between stunalloc above and this stalloc) */
13798                        readcmdfile(fullname);
13799                        cmdp = cmdlookup(name, 0);
13800                        if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13801                                ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13802                        stunalloc(fullname);
13803                        goto success;
13804                }
13805                TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13806                if (!updatetbl) {
13807                        entry->cmdtype = CMDNORMAL;
13808                        entry->u.index = idx;
13809                        return;
13810                }
13811                INT_OFF;
13812                cmdp = cmdlookup(name, 1);
13813                cmdp->cmdtype = CMDNORMAL;
13814                cmdp->param.index = idx;
13815                INT_ON;
13816                goto success;
13817        }
13818
13819        /* We failed.  If there was an entry for this command, delete it */
13820        if (cmdp && updatetbl)
13821                delete_cmd_entry();
13822        if (act & DO_ERR) {
13823#if ENABLE_ASH_BASH_NOT_FOUND_HOOK
13824                struct tblentry *hookp = cmdlookup("command_not_found_handle", 0);
13825                if (hookp && hookp->cmdtype == CMDFUNCTION) {
13826                        char *argv[3];
13827                        argv[0] = (char*) "command_not_found_handle";
13828                        argv[1] = name;
13829                        argv[2] = NULL;
13830                        evalfun(hookp->param.func, 2, argv, 0);
13831                        entry->cmdtype = CMDUNKNOWN;
13832                        return;
13833                }
13834#endif
13835                ash_msg("%s: %s", name, errmsg(e, "not found"));
13836        }
13837 fail:
13838        entry->cmdtype = CMDUNKNOWN;
13839        return;
13840
13841 builtin_success:
13842        if (!updatetbl) {
13843                entry->cmdtype = CMDBUILTIN;
13844                entry->u.cmd = bcmd;
13845                return;
13846        }
13847        INT_OFF;
13848        cmdp = cmdlookup(name, 1);
13849        cmdp->cmdtype = CMDBUILTIN;
13850        cmdp->param.cmd = bcmd;
13851        INT_ON;
13852 success:
13853        cmdp->rehash = 0;
13854        entry->cmdtype = cmdp->cmdtype;
13855        entry->u = cmdp->param;
13856}
13857
13858
13859/*
13860 * The trap builtin.
13861 */
13862static int FAST_FUNC
13863trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13864{
13865        char *action;
13866        char **ap;
13867        int signo, exitcode;
13868
13869        nextopt(nullstr);
13870        ap = argptr;
13871        if (!*ap) {
13872                for (signo = 0; signo < NSIG; signo++) {
13873                        char *tr = trap_ptr[signo];
13874                        if (tr) {
13875                                /* note: bash adds "SIG", but only if invoked
13876                                 * as "bash". If called as "sh", or if set -o posix,
13877                                 * then it prints short signal names.
13878                                 * We are printing short names: */
13879                                out1fmt("trap -- %s %s\n",
13880                                                single_quote(tr),
13881                                                get_signame(signo));
13882                /* trap_ptr != trap only if we are in special-cased `trap` code.
13883                 * In this case, we will exit very soon, no need to free(). */
13884                                /* if (trap_ptr != trap && tp[0]) */
13885                                /*      free(tr); */
13886                        }
13887                }
13888                /*
13889                if (trap_ptr != trap) {
13890                        free(trap_ptr);
13891                        trap_ptr = trap;
13892                }
13893                */
13894                return 0;
13895        }
13896
13897        /* Why the second check?
13898         * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13899         * In this case, NUM is signal no, not an action.
13900         */
13901        action = NULL;
13902        if (ap[1] && !is_number(ap[0]))
13903                action = *ap++;
13904
13905        exitcode = 0;
13906        while (*ap) {
13907                signo = get_signum(*ap);
13908                if (signo < 0) {
13909                        /* Mimic bash message exactly */
13910                        ash_msg("%s: invalid signal specification", *ap);
13911                        exitcode = 1;
13912                        goto next;
13913                }
13914                INT_OFF;
13915                if (action) {
13916                        if (LONE_DASH(action))
13917                                action = NULL;
13918                        else {
13919                                if (action[0]) /* not NULL and not "" and not "-" */
13920                                        may_have_traps = 1;
13921                                action = ckstrdup(action);
13922                        }
13923                }
13924                free(trap[signo]);
13925                trap[signo] = action;
13926                if (signo != 0)
13927                        setsignal(signo);
13928                INT_ON;
13929 next:
13930                ap++;
13931        }
13932        return exitcode;
13933}
13934
13935
13936/* ============ Builtins */
13937
13938#if ENABLE_ASH_HELP
13939static int FAST_FUNC
13940helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13941{
13942        unsigned col;
13943        unsigned i;
13944
13945        out1fmt(
13946                "Built-in commands:\n"
13947                "------------------\n");
13948        for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13949                col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13950                                        builtintab[i].name + 1);
13951                if (col > 60) {
13952                        out1fmt("\n");
13953                        col = 0;
13954                }
13955        }
13956# if ENABLE_FEATURE_SH_STANDALONE
13957        {
13958                const char *a = applet_names;
13959                while (*a) {
13960                        col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13961                        if (col > 60) {
13962                                out1fmt("\n");
13963                                col = 0;
13964                        }
13965                        while (*a++ != '\0')
13966                                continue;
13967                }
13968        }
13969# endif
13970        newline_and_flush(stdout);
13971        return EXIT_SUCCESS;
13972}
13973#endif
13974
13975#if MAX_HISTORY
13976static int FAST_FUNC
13977historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13978{
13979        show_history(line_input_state);
13980        return EXIT_SUCCESS;
13981}
13982#endif
13983
13984/*
13985 * The export and readonly commands.
13986 */
13987static int FAST_FUNC
13988exportcmd(int argc UNUSED_PARAM, char **argv)
13989{
13990        struct var *vp;
13991        char *name;
13992        const char *p;
13993        char **aptr;
13994        char opt;
13995        int flag;
13996        int flag_off;
13997
13998        /* "readonly" in bash accepts, but ignores -n.
13999         * We do the same: it saves a conditional in nextopt's param.
14000         */
14001        flag_off = 0;
14002        while ((opt = nextopt("np")) != '\0') {
14003                if (opt == 'n')
14004                        flag_off = VEXPORT;
14005        }
14006        flag = VEXPORT;
14007        if (argv[0][0] == 'r') {
14008                flag = VREADONLY;
14009                flag_off = 0; /* readonly ignores -n */
14010        }
14011        flag_off = ~flag_off;
14012
14013        /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
14014        {
14015                aptr = argptr;
14016                name = *aptr;
14017                if (name) {
14018                        do {
14019                                p = strchr(name, '=');
14020                                if (p != NULL) {
14021                                        p++;
14022                                } else {
14023                                        vp = *findvar(hashvar(name), name);
14024                                        if (vp) {
14025                                                vp->flags = ((vp->flags | flag) & flag_off);
14026                                                continue;
14027                                        }
14028                                }
14029                                setvar(name, p, (flag & flag_off));
14030                        } while ((name = *++aptr) != NULL);
14031                        return 0;
14032                }
14033        }
14034
14035        /* No arguments. Show the list of exported or readonly vars.
14036         * -n is ignored.
14037         */
14038        showvars(argv[0], flag, 0);
14039        return 0;
14040}
14041
14042/*
14043 * Delete a function if it exists.
14044 */
14045static void
14046unsetfunc(const char *name)
14047{
14048        struct tblentry *cmdp;
14049
14050        cmdp = cmdlookup(name, 0);
14051        if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
14052                delete_cmd_entry();
14053}
14054
14055/*
14056 * The unset builtin command.  We unset the function before we unset the
14057 * variable to allow a function to be unset when there is a readonly variable
14058 * with the same name.
14059 */
14060static int FAST_FUNC
14061unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
14062{
14063        char **ap;
14064        int i;
14065        int flag = 0;
14066
14067        while ((i = nextopt("vf")) != 0) {
14068                flag = i;
14069        }
14070
14071        for (ap = argptr; *ap; ap++) {
14072                if (flag != 'f') {
14073                        unsetvar(*ap);
14074                        continue;
14075                }
14076                if (flag != 'v')
14077                        unsetfunc(*ap);
14078        }
14079        return 0;
14080}
14081
14082static const unsigned char timescmd_str[] ALIGN1 = {
14083        ' ',  offsetof(struct tms, tms_utime),
14084        '\n', offsetof(struct tms, tms_stime),
14085        ' ',  offsetof(struct tms, tms_cutime),
14086        '\n', offsetof(struct tms, tms_cstime),
14087        0
14088};
14089static int FAST_FUNC
14090timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
14091{
14092        unsigned clk_tck;
14093        const unsigned char *p;
14094        struct tms buf;
14095
14096        clk_tck = bb_clk_tck();
14097
14098        times(&buf);
14099        p = timescmd_str;
14100        do {
14101                unsigned sec, frac;
14102                unsigned long t;
14103                t = *(clock_t *)(((char *) &buf) + p[1]);
14104                sec = t / clk_tck;
14105                frac = t % clk_tck;
14106                out1fmt("%um%u.%03us%c",
14107                        sec / 60, sec % 60,
14108                        (frac * 1000) / clk_tck,
14109                        p[0]);
14110                p += 2;
14111        } while (*p);
14112
14113        return 0;
14114}
14115
14116#if ENABLE_FEATURE_SH_MATH
14117/*
14118 * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
14119 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
14120 *
14121 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
14122 */
14123static int FAST_FUNC
14124letcmd(int argc UNUSED_PARAM, char **argv)
14125{
14126        arith_t i;
14127
14128        argv++;
14129        if (!*argv)
14130                ash_msg_and_raise_error("expression expected");
14131        do {
14132                i = ash_arith(*argv);
14133        } while (*++argv);
14134
14135        return !i;
14136}
14137#endif
14138
14139/*
14140 * The read builtin. Options:
14141 *      -r              Do not interpret '\' specially
14142 *      -s              Turn off echo (tty only)
14143 *      -n NCHARS       Read NCHARS max
14144 *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
14145 *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
14146 *      -u FD           Read from given FD instead of fd 0
14147 *      -d DELIM        End on DELIM char, not newline
14148 * This uses unbuffered input, which may be avoidable in some cases.
14149 * TODO: bash also has:
14150 *      -a ARRAY        Read into array[0],[1],etc
14151 *      -e              Use line editing (tty only)
14152 */
14153static int FAST_FUNC
14154readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
14155{
14156        struct builtin_read_params params;
14157        const char *r;
14158        int i;
14159
14160        memset(&params, 0, sizeof(params));
14161
14162        while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
14163                switch (i) {
14164                case 'p':
14165                        params.opt_p = optionarg;
14166                        break;
14167                case 'n':
14168                        params.opt_n = optionarg;
14169                        break;
14170                case 's':
14171                        params.read_flags |= BUILTIN_READ_SILENT;
14172                        break;
14173                case 't':
14174                        params.opt_t = optionarg;
14175                        break;
14176                case 'r':
14177                        params.read_flags |= BUILTIN_READ_RAW;
14178                        break;
14179                case 'u':
14180                        params.opt_u = optionarg;
14181                        break;
14182#if BASH_READ_D
14183                case 'd':
14184                        params.opt_d = optionarg;
14185                        break;
14186#endif
14187                default:
14188                        break;
14189                }
14190        }
14191
14192        if (!ENABLE_ASH_BASH_COMPAT && !argptr) {
14193                bb_simple_error_msg("read: need variable name");
14194                return 1;
14195        }
14196        params.argv = argptr;
14197        params.setvar = setvar0;
14198        params.ifs = bltinlookup("IFS"); /* can be NULL */
14199
14200        /* "read -s" needs to save/restore termios, can't allow ^C
14201         * to jump out of it.
14202         */
14203 again:
14204        INT_OFF;
14205        r = shell_builtin_read(&params);
14206        INT_ON;
14207
14208        if ((uintptr_t)r == 1 && errno == EINTR) {
14209                /* To get SIGCHLD: sleep 1 & read x; echo $x
14210                 * Correct behavior is to not exit "read"
14211                 */
14212                if (pending_sig == 0)
14213                        goto again;
14214        }
14215
14216        if ((uintptr_t)r > 1)
14217                ash_msg_and_raise_error(r);
14218
14219        return (uintptr_t)r;
14220}
14221
14222static int FAST_FUNC
14223umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
14224{
14225        static const char permuser[3] ALIGN1 = "ogu";
14226
14227        mode_t mask;
14228        int symbolic_mode = 0;
14229
14230        while (nextopt("S") != '\0') {
14231                symbolic_mode = 1;
14232        }
14233
14234        INT_OFF;
14235        mask = umask(0);
14236        umask(mask);
14237        INT_ON;
14238
14239        if (*argptr == NULL) {
14240                if (symbolic_mode) {
14241                        char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
14242                        char *p = buf;
14243                        int i;
14244
14245                        i = 2;
14246                        for (;;) {
14247                                *p++ = ',';
14248                                *p++ = permuser[i];
14249                                *p++ = '=';
14250                                /* mask is 0..0uuugggooo. i=2 selects uuu bits */
14251                                if (!(mask & 0400)) *p++ = 'r';
14252                                if (!(mask & 0200)) *p++ = 'w';
14253                                if (!(mask & 0100)) *p++ = 'x';
14254                                mask <<= 3;
14255                                if (--i < 0)
14256                                        break;
14257                        }
14258                        *p = '\0';
14259                        puts(buf + 1);
14260                } else {
14261                        out1fmt("%04o\n", mask);
14262                }
14263        } else {
14264                char *modestr = *argptr;
14265                /* numeric umasks are taken as-is */
14266                /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
14267                if (!isdigit(modestr[0]))
14268                        mask ^= 0777;
14269                mask = bb_parse_mode(modestr, mask);
14270                if ((unsigned)mask > 0777) {
14271                        ash_msg_and_raise_error("illegal mode: %s", modestr);
14272                }
14273                if (!isdigit(modestr[0]))
14274                        mask ^= 0777;
14275                umask(mask);
14276        }
14277        return 0;
14278}
14279
14280static int FAST_FUNC
14281ulimitcmd(int argc UNUSED_PARAM, char **argv)
14282{
14283        return shell_builtin_ulimit(argv);
14284}
14285
14286/* ============ main() and helpers */
14287
14288/*
14289 * This routine is called when an error or an interrupt occurs in an
14290 * interactive shell and control is returned to the main command loop
14291 * but prior to exitshell.
14292 */
14293static void
14294exitreset(void)
14295{
14296        /* from eval.c: */
14297        if (savestatus >= 0) {
14298                if (exception_type == EXEXIT || evalskip == SKIPFUNCDEF)
14299                        exitstatus = savestatus;
14300                savestatus = -1;
14301        }
14302        evalskip = 0;
14303        loopnest = 0;
14304
14305        /* from expand.c: */
14306        ifsfree();
14307
14308        /* from redir.c: */
14309        unwindredir(NULL);
14310}
14311
14312/*
14313 * This routine is called when an error or an interrupt occurs in an
14314 * interactive shell and control is returned to the main command loop.
14315 * (In dash, this function is auto-generated by build machinery).
14316 */
14317static void
14318reset(void)
14319{
14320        /* from input.c: */
14321        g_parsefile->left_in_buffer = 0;
14322        g_parsefile->left_in_line = 0;      /* clear input buffer */
14323        g_parsefile->unget = 0;
14324        popallfiles();
14325
14326        /* from var.c: */
14327        unwindlocalvars(NULL);
14328}
14329
14330/*
14331 * Called to exit the shell.
14332 */
14333static void
14334exitshell(void)
14335{
14336        struct jmploc loc;
14337        char *p;
14338
14339#if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
14340        save_history(line_input_state); /* may be NULL */
14341#endif
14342        savestatus = exitstatus;
14343        TRACE(("pid %d, exitshell(%d)\n", getpid(), savestatus));
14344        if (setjmp(loc.loc))
14345                goto out;
14346        exception_handler = &loc;
14347        p = trap[0];
14348        if (p) {
14349                trap[0] = NULL;
14350                evalskip = 0;
14351                evalstring(p, 0);
14352                evalskip = SKIPFUNCDEF;
14353                /*free(p); - we'll exit soon */
14354        }
14355 out:
14356        exitreset();
14357        /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
14358         * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
14359         */
14360        setjobctl(0);
14361        flush_stdout_stderr();
14362        _exit(exitstatus);
14363        /* NOTREACHED */
14364}
14365
14366/* Don't inline: conserve stack of caller from having our locals too */
14367static NOINLINE void
14368init(void)
14369{
14370        /* we will never free this */
14371        basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
14372        basepf.linno = 1;
14373
14374        sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
14375        setsignal(SIGCHLD);
14376
14377        {
14378                char **envp;
14379                const char *p;
14380
14381                initvar();
14382                for (envp = environ; envp && *envp; envp++) {
14383/* Used to have
14384 *                      p = endofname(*envp);
14385 *                      if (p != *envp && *p == '=') {
14386 * here to weed out badly-named variables, but this breaks
14387 * scenarios where people do want them passed to children:
14388 * import os
14389 * os.environ["test-test"]="test"
14390 * if os.fork() == 0:
14391 *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
14392 * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])  # breaks this
14393 */
14394                        if (strchr(*envp, '=')) {
14395                                setvareq(*envp, VEXPORT|VTEXTFIXED);
14396                        }
14397                }
14398
14399                setvareq((char*)defifsvar, VTEXTFIXED);
14400                setvareq((char*)defoptindvar, VTEXTFIXED);
14401
14402                setvar0("PPID", utoa(getppid()));
14403#if BASH_SHLVL_VAR
14404                p = lookupvar("SHLVL");
14405                setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
14406#endif
14407#if BASH_HOSTNAME_VAR
14408                if (!lookupvar("HOSTNAME")) {
14409                        struct utsname uts;
14410                        uname(&uts);
14411                        setvar0("HOSTNAME", uts.nodename);
14412                }
14413#endif
14414                p = lookupvar("PWD");
14415                if (p) {
14416                        struct stat st1, st2;
14417                        if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
14418                         || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
14419                        ) {
14420                                p = NULL;
14421                        }
14422                }
14423                setpwd(p, 0);
14424        }
14425}
14426
14427
14428//usage:#define ash_trivial_usage
14429//usage:        "[-il] [-|+Cabefmnuvx] [-|+o OPT]... [-c 'SCRIPT' [ARG0 ARGS] | FILE [ARGS] | -s [ARGS]]"
14430////////        comes from ^^^^^^^^^^optletters
14431//usage:#define ash_full_usage "\n\n"
14432//usage:        "Unix shell interpreter"
14433
14434/*
14435 * Process the shell command line arguments.
14436 */
14437static int
14438procargs(char **argv)
14439{
14440        int i;
14441        const char *xminusc;
14442        char **xargv;
14443        int login_sh;
14444
14445        xargv = argv;
14446        login_sh = xargv[0] && xargv[0][0] == '-';
14447#if NUM_SCRIPTS > 0
14448        if (minusc)
14449                goto setarg0;
14450#endif
14451        arg0 = xargv[0];
14452        /* if (xargv[0]) - mmm, this is always true! */
14453                xargv++;
14454        argptr = xargv;
14455        for (i = 0; i < NOPTS; i++)
14456                optlist[i] = 2;
14457        if (options(&login_sh)) {
14458                /* it already printed err message */
14459                raise_exception(EXERROR);
14460        }
14461        xargv = argptr;
14462        xminusc = minusc;
14463        if (*xargv == NULL) {
14464                if (xminusc)
14465                        ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
14466                sflag = 1;
14467        }
14468        if (iflag == 2 /* no explicit -i given */
14469         && sflag == 1 /* -s given (or implied) */
14470         && !minusc /* bash compat: ash -sc 'echo $-' is not interactive (dash is) */
14471         && isatty(0) && isatty(1) /* we are on tty */
14472        ) {
14473                iflag = 1;
14474        }
14475        if (mflag == 2)
14476                mflag = iflag;
14477        /* Unset options which weren't explicitly set or unset */
14478        for (i = 0; i < NOPTS; i++)
14479                optlist[i] &= 1; /* same effect as "if (optlist[i] == 2) optlist[i] = 0;" */
14480#if DEBUG == 2
14481        debug = 1;
14482#endif
14483        /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
14484        if (xminusc) {
14485                minusc = *xargv++;
14486                if (*xargv)
14487                        goto setarg0;
14488        } else if (!sflag) {
14489                setinputfile(*xargv, 0);
14490 setarg0:
14491                arg0 = *xargv++;
14492                commandname = arg0;
14493        }
14494
14495        shellparam.p = xargv;
14496#if ENABLE_ASH_GETOPTS
14497        shellparam.optind = 1;
14498        shellparam.optoff = -1;
14499#endif
14500        /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
14501        while (*xargv) {
14502                shellparam.nparam++;
14503                xargv++;
14504        }
14505
14506        /* Interactive bash re-enables SIGHUP which is SIG_IGNed on entry.
14507         * Try:
14508         * trap '' hup; bash; echo RET  # type "kill -hup $$", see SIGHUP having effect
14509         * trap '' hup; bash -c 'kill -hup $$; echo ALIVE'  # here SIGHUP is SIG_IGNed
14510         * NB: must do it before setting up signals (in optschanged())
14511         * and reading .profile etc (after we return from here):
14512         */
14513        if (iflag)
14514                signal(SIGHUP, SIG_DFL);
14515
14516        optschanged();
14517
14518        return login_sh;
14519}
14520
14521/*
14522 * Read /etc/profile, ~/.profile, $ENV.
14523 */
14524static void
14525read_profile(const char *name)
14526{
14527        name = expandstr(name, DQSYNTAX);
14528        if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
14529                return;
14530        cmdloop(0);
14531        popfile();
14532}
14533
14534#if PROFILE
14535static short profile_buf[16384];
14536extern int etext();
14537#endif
14538
14539/*
14540 * Main routine.  We initialize things, parse the arguments, execute
14541 * profiles if we're a login shell, and then call cmdloop to execute
14542 * commands.  The setjmp call sets up the location to jump to when an
14543 * exception occurs.  When an exception occurs the variable "state"
14544 * is used to figure out how far we had gotten.
14545 */
14546int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
14547#if NUM_SCRIPTS > 0
14548int ash_main(int argc, char **argv)
14549#else
14550int ash_main(int argc UNUSED_PARAM, char **argv)
14551#endif
14552/* note: 'argc' is used only if embedded scripts are enabled */
14553{
14554        volatile smallint state;
14555        struct jmploc jmploc;
14556        struct stackmark smark;
14557        int login_sh;
14558
14559        /* Initialize global data */
14560        INIT_G_misc();
14561        INIT_G_memstack();
14562        INIT_G_var();
14563#if ENABLE_ASH_ALIAS
14564        INIT_G_alias();
14565#endif
14566        INIT_G_cmdtable();
14567
14568#if PROFILE
14569        monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
14570#endif
14571
14572        state = 0;
14573        if (setjmp(jmploc.loc)) {
14574                smallint e;
14575                smallint s;
14576
14577                exitreset();
14578
14579                e = exception_type;
14580                s = state;
14581                if (e == EXEND || e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
14582                        exitshell();
14583                }
14584
14585                reset();
14586
14587                if (e == EXINT) {
14588                        newline_and_flush(stderr);
14589                }
14590
14591                popstackmark(&smark);
14592                FORCE_INT_ON; /* enable interrupts */
14593                if (s == 1)
14594                        goto state1;
14595                if (s == 2)
14596                        goto state2;
14597                if (s == 3)
14598                        goto state3;
14599                goto state4;
14600        }
14601        exception_handler = &jmploc;
14602        rootpid = getpid();
14603
14604        init();
14605        setstackmark(&smark);
14606
14607#if NUM_SCRIPTS > 0
14608        if (argc < 0)
14609                /* Non-NULL minusc tells procargs that an embedded script is being run */
14610                minusc = get_script_content(-argc - 1);
14611#endif
14612        login_sh = procargs(argv);
14613#if DEBUG
14614        TRACE(("Shell args: "));
14615        trace_puts_args(argv);
14616#endif
14617
14618        if (login_sh) {
14619                const char *hp;
14620
14621                state = 1;
14622                read_profile("/etc/profile");
14623 state1:
14624                state = 2;
14625                hp = lookupvar("HOME");
14626                if (hp)
14627                        read_profile("$HOME/.profile");
14628        }
14629 state2:
14630        state = 3;
14631        if (
14632#ifndef linux
14633         getuid() == geteuid() && getgid() == getegid() &&
14634#endif
14635         iflag
14636        ) {
14637                const char *shinit = lookupvar("ENV");
14638                if (shinit != NULL && *shinit != '\0')
14639                        read_profile(shinit);
14640        }
14641        popstackmark(&smark);
14642 state3:
14643        state = 4;
14644        if (minusc) {
14645                /* evalstring pushes parsefile stack.
14646                 * Ensure we don't falsely claim that 0 (stdin)
14647                 * is one of stacked source fds.
14648                 * Testcase: ash -c 'exec 1>&0' must not complain. */
14649
14650                // if (!sflag) g_parsefile->pf_fd = -1;
14651                // ^^ not necessary since now we special-case fd 0
14652                // in save_fd_on_redirect()
14653
14654                // dash: evalstring(minusc, sflag ? 0 : EV_EXIT);
14655                // The above makes
14656                //  ash -sc 'echo $-'
14657                // continue reading input from stdin after running 'echo'.
14658                // bash does not do this: it prints "hBcs" and exits.
14659                evalstring(minusc, EV_EXIT);
14660        }
14661
14662        if (sflag || minusc == NULL) {
14663#if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
14664                if (line_input_state) {
14665                        const char *hp = lookupvar("HISTFILE");
14666                        if (!hp) {
14667                                hp = lookupvar("HOME");
14668                                if (hp) {
14669                                        INT_OFF;
14670                                        hp = concat_path_file(hp, ".ash_history");
14671                                        setvar0("HISTFILE", hp);
14672                                        free((char*)hp);
14673                                        INT_ON;
14674                                        hp = lookupvar("HISTFILE");
14675                                }
14676                        }
14677                        if (hp)
14678                                line_input_state->hist_file = xstrdup(hp);
14679# if ENABLE_FEATURE_SH_HISTFILESIZE
14680                        hp = lookupvar("HISTFILESIZE");
14681                        line_input_state->max_history = size_from_HISTFILESIZE(hp);
14682# endif
14683                }
14684#endif
14685 state4: /* XXX ??? - why isn't this before the "if" statement */
14686                cmdloop(1);
14687        }
14688#if PROFILE
14689        monitor(0);
14690#endif
14691#ifdef GPROF
14692        {
14693                extern void _mcleanup(void);
14694                _mcleanup();
14695        }
14696#endif
14697        TRACE(("End of main reached\n"));
14698        exitshell();
14699        /* NOTREACHED */
14700}
14701
14702
14703/*-
14704 * Copyright (c) 1989, 1991, 1993, 1994
14705 *      The Regents of the University of California.  All rights reserved.
14706 *
14707 * This code is derived from software contributed to Berkeley by
14708 * Kenneth Almquist.
14709 *
14710 * Redistribution and use in source and binary forms, with or without
14711 * modification, are permitted provided that the following conditions
14712 * are met:
14713 * 1. Redistributions of source code must retain the above copyright
14714 *    notice, this list of conditions and the following disclaimer.
14715 * 2. Redistributions in binary form must reproduce the above copyright
14716 *    notice, this list of conditions and the following disclaimer in the
14717 *    documentation and/or other materials provided with the distribution.
14718 * 3. Neither the name of the University nor the names of its contributors
14719 *    may be used to endorse or promote products derived from this software
14720 *    without specific prior written permission.
14721 *
14722 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
14723 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14724 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14725 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
14726 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14727 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14728 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14729 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14730 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14731 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14732 * SUCH DAMAGE.
14733 */
14734