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        file_stop = g_parsefile;
10282        back_exitstatus = 0;
10283
10284        cmdentry.cmdtype = CMDBUILTIN;
10285        cmdentry.u.cmd = &null_bltin;
10286        varlist.lastp = &varlist.list;
10287        *varlist.lastp = NULL;
10288        arglist.lastp = &arglist.list;
10289        *arglist.lastp = NULL;
10290
10291        cmd_flag = 0;
10292        cmd_is_exec = 0;
10293        spclbltin = -1;
10294        vflags = 0;
10295        vlocal = 0;
10296        path = NULL;
10297
10298        argc = 0;
10299        argp = cmd->ncmd.args;
10300        osp = fill_arglist(&arglist, &argp);
10301        if (osp) {
10302                int pseudovarflag = 0;
10303
10304                for (;;) {
10305                        find_command(arglist.list->text, &cmdentry,
10306                                        cmd_flag | DO_REGBLTIN, pathval());
10307
10308                        vlocal++;
10309
10310                        /* implement bltin and command here */
10311                        if (cmdentry.cmdtype != CMDBUILTIN)
10312                                break;
10313
10314                        pseudovarflag = IS_BUILTIN_ASSIGN(cmdentry.u.cmd);
10315                        if (spclbltin < 0) {
10316                                spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
10317                                vlocal = !spclbltin;
10318                        }
10319                        cmd_is_exec = cmdentry.u.cmd == EXECCMD;
10320#if ENABLE_ASH_CMDCMD
10321                        if (cmdentry.u.cmd != COMMANDCMD)
10322                                break;
10323
10324                        cmd_flag = parse_command_args(&arglist, &argp, &path);
10325                        if (!cmd_flag)
10326#endif
10327                                break;
10328                }
10329
10330                for (; argp; argp = argp->narg.next)
10331                        expandarg(argp, &arglist,
10332                                        pseudovarflag &&
10333                                        isassignment(argp->narg.text) ?
10334                                        EXP_VARTILDE : EXP_FULL | EXP_TILDE);
10335
10336                for (sp = arglist.list; sp; sp = sp->next)
10337                        argc++;
10338
10339                if (cmd_is_exec && argc > 1)
10340                        vflags = VEXPORT;
10341        }
10342
10343        localvar_stop = pushlocalvars(vlocal);
10344
10345        /* Reserve one extra spot at the front for shellexec. */
10346        nargv = stalloc(sizeof(char *) * (argc + 2));
10347        argv = ++nargv;
10348        for (sp = arglist.list; sp; sp = sp->next) {
10349                TRACE(("evalcommand arg: %s\n", sp->text));
10350                *nargv++ = sp->text;
10351        }
10352        *nargv = NULL;
10353
10354        lastarg = NULL;
10355        if (iflag && funcline == 0 && argc > 0)
10356                lastarg = nargv[-1];
10357
10358        expredir(cmd->ncmd.redirect);
10359        redir_stop = pushredir(cmd->ncmd.redirect);
10360        preverrout_fd = 2;
10361        if (BASH_XTRACEFD && xflag) {
10362                /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
10363                 * we do not emulate this. We only use its value.
10364                 */
10365                const char *xtracefd = lookupvar("BASH_XTRACEFD");
10366                if (xtracefd && is_number(xtracefd))
10367                        preverrout_fd = atoi(xtracefd);
10368
10369        }
10370        status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
10371
10372        if (status) {
10373 bail:
10374                exitstatus = status;
10375
10376                /* We have a redirection error. */
10377                if (spclbltin > 0)
10378                        raise_exception(EXERROR);
10379
10380                goto out;
10381        }
10382
10383        for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
10384                struct strlist **spp;
10385
10386                spp = varlist.lastp;
10387                expandarg(argp, &varlist, EXP_VARTILDE);
10388
10389                if (vlocal)
10390                        mklocal((*spp)->text, VEXPORT);
10391                else
10392                        setvareq((*spp)->text, vflags);
10393        }
10394
10395        /* Print the command if xflag is set. */
10396        if (xflag) {
10397                const char *pfx = "";
10398
10399                fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
10400
10401                sp = varlist.list;
10402                while (sp) {
10403                        char *varval = sp->text;
10404                        char *eq = strchrnul(varval, '=');
10405                        if (*eq)
10406                                eq++;
10407                        fdprintf(preverrout_fd, "%s%.*s%s",
10408                                pfx,
10409                                (int)(eq - varval), varval,
10410                                maybe_single_quote(eq)
10411                        );
10412                        sp = sp->next;
10413                        pfx = " ";
10414                }
10415
10416                sp = arglist.list;
10417                while (sp) {
10418                        fdprintf(preverrout_fd, "%s%s",
10419                                pfx,
10420                                /* always quote if matches reserved word: */
10421                                findkwd(sp->text)
10422                                ? single_quote(sp->text)
10423                                : maybe_single_quote(sp->text)
10424                        );
10425                        sp = sp->next;
10426                        pfx = " ";
10427                }
10428                safe_write(preverrout_fd, "\n", 1);
10429        }
10430
10431        /* Now locate the command. */
10432        if (cmdentry.cmdtype != CMDBUILTIN
10433         || !(IS_BUILTIN_REGULAR(cmdentry.u.cmd))
10434        ) {
10435                path = path ? path : pathval();
10436                find_command(argv[0], &cmdentry, cmd_flag | DO_ERR, path);
10437        }
10438
10439        jp = NULL;
10440
10441        /* Execute the command. */
10442        switch (cmdentry.cmdtype) {
10443        case CMDUNKNOWN:
10444                status = 127;
10445                flush_stdout_stderr();
10446                goto bail;
10447
10448        default: {
10449
10450#if ENABLE_FEATURE_SH_STANDALONE \
10451 && ENABLE_FEATURE_SH_NOFORK \
10452 && NUM_APPLETS > 1
10453/* (1) BUG: if variables are set, we need to fork, or save/restore them
10454 *     around run_nofork_applet() call.
10455 * (2) Should this check also be done in forkshell()?
10456 *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
10457 */
10458                /* find_command() encodes applet_no as (-2 - applet_no) */
10459                int applet_no = (- cmdentry.u.index - 2);
10460                if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
10461                        char **sv_environ;
10462
10463                        INT_OFF;
10464                        sv_environ = environ;
10465                        environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
10466                        /*
10467                         * Run <applet>_main().
10468                         * Signals (^C) can't interrupt here.
10469                         * Otherwise we can mangle stdio or malloc internal state.
10470                         * This makes applets which can run for a long time
10471                         * and/or wait for user input ineligible for NOFORK:
10472                         * for example, "yes" or "rm" (rm -i waits for input).
10473                         */
10474                        exitstatus = run_nofork_applet(applet_no, argv);
10475                        environ = sv_environ;
10476                        /*
10477                         * Try enabling NOFORK for "yes" applet.
10478                         * ^C _will_ stop it (write returns EINTR),
10479                         * but this causes stdout FILE to be stuck
10480                         * and needing clearerr(). What if other applets
10481                         * also can get EINTRs? Do we need to switch
10482                         * our signals to SA_RESTART?
10483                         */
10484                        /*clearerr(stdout);*/
10485                        INT_ON;
10486                        break;
10487                }
10488#endif
10489                /* Can we avoid forking? For example, very last command
10490                 * in a script or a subshell does not need forking,
10491                 * we can just exec it.
10492                 */
10493                if (!(flags & EV_EXIT) || may_have_traps) {
10494                        /* No, forking off a child is necessary */
10495                        INT_OFF;
10496                        get_tty_state();
10497                        jp = makejob(/*cmd,*/ 1);
10498                        if (forkshell(jp, cmd, FORK_FG) != 0) {
10499                                /* parent */
10500                                break;
10501                        }
10502                        /* child */
10503                        FORCE_INT_ON;
10504                        /* fall through to exec'ing external program */
10505                }
10506                shellexec(argv[0], argv, path, cmdentry.u.index);
10507                /* NOTREACHED */
10508        } /* default */
10509        case CMDBUILTIN:
10510                if (evalbltin(cmdentry.u.cmd, argc, argv, flags)
10511                 && !(exception_type == EXERROR && spclbltin <= 0)
10512                ) {
10513 raise:
10514                        longjmp(exception_handler->loc, 1);
10515                }
10516                break;
10517
10518        case CMDFUNCTION:
10519                if (evalfun(cmdentry.u.func, argc, argv, flags))
10520                        goto raise;
10521                break;
10522        } /* switch */
10523
10524        status = waitforjob(jp);
10525        if (jp)
10526                TRACE(("forked child exited with %d\n", status));
10527        FORCE_INT_ON;
10528
10529 out:
10530        if (cmd->ncmd.redirect)
10531                popredir(/*drop:*/ cmd_is_exec);
10532        unwindredir(redir_stop);
10533        unwindfiles(file_stop);
10534        unwindlocalvars(localvar_stop);
10535        if (lastarg) {
10536                /* dsl: I think this is intended to be used to support
10537                 * '_' in 'vi' command mode during line editing...
10538                 * However I implemented that within libedit itself.
10539                 */
10540                setvar0("_", lastarg);
10541        }
10542
10543        return status;
10544}
10545
10546static int
10547evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10548{
10549        char *volatile savecmdname;
10550        struct jmploc *volatile savehandler;
10551        struct jmploc jmploc;
10552        int status;
10553        int i;
10554
10555        savecmdname = commandname;
10556        savehandler = exception_handler;
10557        i = setjmp(jmploc.loc);
10558        if (i)
10559                goto cmddone;
10560        exception_handler = &jmploc;
10561        commandname = argv[0];
10562        argptr = argv + 1;
10563        optptr = NULL;                  /* initialize nextopt */
10564        if (cmd == EVALCMD)
10565                status = evalcmd(argc, argv, flags);
10566        else
10567                status = (*cmd->builtin)(argc, argv);
10568        flush_stdout_stderr();
10569        status |= ferror(stdout);
10570        exitstatus = status;
10571 cmddone:
10572        clearerr(stdout);
10573        commandname = savecmdname;
10574        exception_handler = savehandler;
10575
10576        return i;
10577}
10578
10579static int
10580goodname(const char *p)
10581{
10582        return endofname(p)[0] == '\0';
10583}
10584
10585
10586/*
10587 * Search for a command.  This is called before we fork so that the
10588 * location of the command will be available in the parent as well as
10589 * the child.  The check for "goodname" is an overly conservative
10590 * check that the name will not be subject to expansion.
10591 */
10592static void
10593prehash(union node *n)
10594{
10595        struct cmdentry entry;
10596
10597        if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10598                find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10599}
10600
10601
10602/* ============ Builtin commands
10603 *
10604 * Builtin commands whose functions are closely tied to evaluation
10605 * are implemented here.
10606 */
10607
10608/*
10609 * Handle break and continue commands.  Break, continue, and return are
10610 * all handled by setting the evalskip flag.  The evaluation routines
10611 * above all check this flag, and if it is set they start skipping
10612 * commands rather than executing them.  The variable skipcount is
10613 * the number of loops to break/continue, or the number of function
10614 * levels to return.  (The latter is always 1.)  It should probably
10615 * be an error to break out of more loops than exist, but it isn't
10616 * in the standard shell so we don't make it one here.
10617 */
10618static int FAST_FUNC
10619breakcmd(int argc UNUSED_PARAM, char **argv)
10620{
10621        int n = argv[1] ? number(argv[1]) : 1;
10622
10623        if (n <= 0)
10624                ash_msg_and_raise_error(msg_illnum, argv[1]);
10625        if (n > loopnest)
10626                n = loopnest;
10627        if (n > 0) {
10628                evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10629                skipcount = n;
10630        }
10631        return 0;
10632}
10633
10634
10635/*
10636 * This implements the input routines used by the parser.
10637 */
10638
10639enum {
10640        INPUT_PUSH_FILE = 1,
10641        INPUT_NOFILE_OK = 2,
10642};
10643
10644static smallint checkkwd;
10645/* values of checkkwd variable */
10646#define CHKALIAS        0x1
10647#define CHKKWD          0x2
10648#define CHKNL           0x4
10649#define CHKEOFMARK      0x8
10650
10651/*
10652 * Push a string back onto the input at this current parsefile level.
10653 * We handle aliases this way.
10654 */
10655#if !ENABLE_ASH_ALIAS
10656#define pushstring(s, ap) pushstring(s)
10657#endif
10658static void
10659pushstring(char *s, struct alias *ap)
10660{
10661        struct strpush *sp;
10662        int len;
10663
10664        len = strlen(s);
10665        INT_OFF;
10666        if (g_parsefile->strpush) {
10667                sp = ckzalloc(sizeof(*sp));
10668                sp->prev = g_parsefile->strpush;
10669        } else {
10670                sp = &(g_parsefile->basestrpush);
10671        }
10672        g_parsefile->strpush = sp;
10673        sp->prev_string = g_parsefile->next_to_pgetc;
10674        sp->prev_left_in_line = g_parsefile->left_in_line;
10675        sp->unget = g_parsefile->unget;
10676        memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10677#if ENABLE_ASH_ALIAS
10678        sp->ap = ap;
10679        if (ap) {
10680                ap->flag |= ALIASINUSE;
10681                sp->string = s;
10682        }
10683#endif
10684        g_parsefile->next_to_pgetc = s;
10685        g_parsefile->left_in_line = len;
10686        g_parsefile->unget = 0;
10687        INT_ON;
10688}
10689
10690static void
10691popstring(void)
10692{
10693        struct strpush *sp = g_parsefile->strpush;
10694
10695        INT_OFF;
10696#if ENABLE_ASH_ALIAS
10697        if (sp->ap) {
10698                if (g_parsefile->next_to_pgetc[-1] == ' '
10699                 || g_parsefile->next_to_pgetc[-1] == '\t'
10700                ) {
10701                        checkkwd |= CHKALIAS;
10702                }
10703                if (sp->string != sp->ap->val) {
10704                        free(sp->string);
10705                }
10706                sp->ap->flag &= ~ALIASINUSE;
10707                if (sp->ap->flag & ALIASDEAD) {
10708                        unalias(sp->ap->name);
10709                }
10710        }
10711#endif
10712        g_parsefile->next_to_pgetc = sp->prev_string;
10713        g_parsefile->left_in_line = sp->prev_left_in_line;
10714        g_parsefile->unget = sp->unget;
10715        memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10716        g_parsefile->strpush = sp->prev;
10717        if (sp != &(g_parsefile->basestrpush))
10718                free(sp);
10719        INT_ON;
10720}
10721
10722static int
10723preadfd(void)
10724{
10725        int nr;
10726        char *buf = g_parsefile->buf;
10727
10728        g_parsefile->next_to_pgetc = buf;
10729#if ENABLE_FEATURE_EDITING
10730 /* retry: */
10731        if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10732                nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10733        else {
10734# if ENABLE_ASH_IDLE_TIMEOUT
10735                int timeout = -1;
10736                const char *tmout_var = lookupvar("TMOUT");
10737                if (tmout_var) {
10738                        timeout = atoi(tmout_var) * 1000;
10739                        if (timeout <= 0)
10740                                timeout = -1;
10741                }
10742                line_input_state->timeout = timeout;
10743# endif
10744# if ENABLE_FEATURE_TAB_COMPLETION
10745                line_input_state->path_lookup = pathval();
10746# endif
10747                reinit_unicode_for_ash();
10748                nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10749                if (nr == 0) {
10750                        /* ^C pressed, "convert" to SIGINT */
10751                        write(STDOUT_FILENO, "^C", 2);
10752                        raise(SIGINT);
10753                        if (trap[SIGINT]) {
10754                                buf[0] = '\n';
10755                                buf[1] = '\0';
10756                                return 1;
10757                        }
10758                        exitstatus = 128 + SIGINT;
10759                        return -1;
10760                }
10761                if (nr < 0) {
10762                        if (errno == 0) {
10763                                /* Ctrl+D pressed */
10764                                nr = 0;
10765                        }
10766# if ENABLE_ASH_IDLE_TIMEOUT
10767                        else if (errno == EAGAIN && timeout > 0) {
10768                                puts("\007timed out waiting for input: auto-logout");
10769                                exitshell();
10770                        }
10771# endif
10772                }
10773        }
10774#else
10775        nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10776#endif
10777
10778#if 0 /* disabled: nonblock_immune_read() handles this problem */
10779        if (nr < 0) {
10780                if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10781                        int flags = fcntl(0, F_GETFL);
10782                        if (flags >= 0 && (flags & O_NONBLOCK)) {
10783                                flags &= ~O_NONBLOCK;
10784                                if (fcntl(0, F_SETFL, flags) >= 0) {
10785                                        out2str("sh: turning off NDELAY mode\n");
10786                                        goto retry;
10787                                }
10788                        }
10789                }
10790        }
10791#endif
10792        return nr;
10793}
10794
10795/*
10796 * Refill the input buffer and return the next input character:
10797 *
10798 * 1) If a string was pushed back on the input, pop it;
10799 * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10800 *    or we are reading from a string so we can't refill the buffer,
10801 *    return EOF.
10802 * 3) If there is more stuff in this buffer, use it else call read to fill it.
10803 * 4) Process input up to the next newline, deleting nul characters.
10804 */
10805//#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10806#define pgetc_debug(...) ((void)0)
10807static int pgetc(void);
10808static int
10809preadbuffer(void)
10810{
10811        char *q;
10812        int more;
10813
10814        if (g_parsefile->strpush) {
10815#if ENABLE_ASH_ALIAS
10816                if (g_parsefile->left_in_line == -1
10817                 && g_parsefile->strpush->ap
10818                 && g_parsefile->next_to_pgetc[-1] != ' '
10819                 && g_parsefile->next_to_pgetc[-1] != '\t'
10820                ) {
10821                        pgetc_debug("preadbuffer PEOA");
10822                        return PEOA;
10823                }
10824#endif
10825                popstring();
10826                return pgetc();
10827        }
10828        /* on both branches above g_parsefile->left_in_line < 0.
10829         * "pgetc" needs refilling.
10830         */
10831
10832        /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10833         * pungetc() may increment it a few times.
10834         * Assuming it won't increment it to less than -90.
10835         */
10836        if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10837                pgetc_debug("preadbuffer PEOF1");
10838                /* even in failure keep left_in_line and next_to_pgetc
10839                 * in lock step, for correct multi-layer pungetc.
10840                 * left_in_line was decremented before preadbuffer(),
10841                 * must inc next_to_pgetc: */
10842                g_parsefile->next_to_pgetc++;
10843                return PEOF;
10844        }
10845
10846        more = g_parsefile->left_in_buffer;
10847        if (more <= 0) {
10848                flush_stdout_stderr();
10849 again:
10850                more = preadfd();
10851                if (more <= 0) {
10852                        /* don't try reading again */
10853                        g_parsefile->left_in_line = -99;
10854                        pgetc_debug("preadbuffer PEOF2");
10855                        g_parsefile->next_to_pgetc++;
10856                        return PEOF;
10857                }
10858        }
10859
10860        /* Find out where's the end of line.
10861         * Set g_parsefile->left_in_line
10862         * and g_parsefile->left_in_buffer acordingly.
10863         * NUL chars are deleted.
10864         */
10865        q = g_parsefile->next_to_pgetc;
10866        for (;;) {
10867                char c;
10868
10869                more--;
10870
10871                c = *q;
10872                if (c == '\0') {
10873                        memmove(q, q + 1, more);
10874                } else {
10875                        q++;
10876                        if (c == '\n') {
10877                                g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10878                                break;
10879                        }
10880                }
10881
10882                if (more <= 0) {
10883                        g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10884                        if (g_parsefile->left_in_line < 0)
10885                                goto again;
10886                        break;
10887                }
10888        }
10889        g_parsefile->left_in_buffer = more;
10890
10891        if (vflag) {
10892                char save = *q;
10893                *q = '\0';
10894                out2str(g_parsefile->next_to_pgetc);
10895                *q = save;
10896        }
10897
10898        pgetc_debug("preadbuffer at %d:%p'%s'",
10899                        g_parsefile->left_in_line,
10900                        g_parsefile->next_to_pgetc,
10901                        g_parsefile->next_to_pgetc);
10902        return (unsigned char)*g_parsefile->next_to_pgetc++;
10903}
10904
10905static void
10906nlprompt(void)
10907{
10908        g_parsefile->linno++;
10909        setprompt_if(doprompt, 2);
10910}
10911static void
10912nlnoprompt(void)
10913{
10914        g_parsefile->linno++;
10915        needprompt = doprompt;
10916}
10917
10918static int
10919pgetc(void)
10920{
10921        int c;
10922
10923        pgetc_debug("pgetc at %d:%p'%s'",
10924                        g_parsefile->left_in_line,
10925                        g_parsefile->next_to_pgetc,
10926                        g_parsefile->next_to_pgetc);
10927        if (g_parsefile->unget)
10928                return g_parsefile->lastc[--g_parsefile->unget];
10929
10930        if (--g_parsefile->left_in_line >= 0)
10931                c = (unsigned char)*g_parsefile->next_to_pgetc++;
10932        else
10933                c = preadbuffer();
10934
10935        g_parsefile->lastc[1] = g_parsefile->lastc[0];
10936        g_parsefile->lastc[0] = c;
10937
10938        return c;
10939}
10940
10941#if ENABLE_ASH_ALIAS
10942static int
10943pgetc_without_PEOA(void)
10944{
10945        int c;
10946        do {
10947                pgetc_debug("pgetc at %d:%p'%s'",
10948                                g_parsefile->left_in_line,
10949                                g_parsefile->next_to_pgetc,
10950                                g_parsefile->next_to_pgetc);
10951                c = pgetc();
10952        } while (c == PEOA);
10953        return c;
10954}
10955#else
10956# define pgetc_without_PEOA() pgetc()
10957#endif
10958
10959/*
10960 * Undo a call to pgetc.  Only two characters may be pushed back.
10961 * PEOF may be pushed back.
10962 */
10963static void
10964pungetc(void)
10965{
10966        g_parsefile->unget++;
10967}
10968
10969/* This one eats backslash+newline */
10970static int
10971pgetc_eatbnl(void)
10972{
10973        int c;
10974
10975        while ((c = pgetc()) == '\\') {
10976                if (pgetc() != '\n') {
10977                        pungetc();
10978                        break;
10979                }
10980
10981                nlprompt();
10982        }
10983
10984        return c;
10985}
10986
10987struct synstack {
10988        smalluint syntax;
10989        uint8_t innerdq   :1;
10990        uint8_t varpushed :1;
10991        uint8_t dblquote  :1;
10992        int varnest;            /* levels of variables expansion */
10993        int dqvarnest;          /* levels of variables expansion within double quotes */
10994        int parenlevel;         /* levels of parens in arithmetic */
10995        struct synstack *prev;
10996        struct synstack *next;
10997};
10998
10999static int
11000pgetc_top(struct synstack *stack)
11001{
11002        return stack->syntax == SQSYNTAX ? pgetc() : pgetc_eatbnl();
11003}
11004
11005static void
11006synstack_push(struct synstack **stack, struct synstack *next, int syntax)
11007{
11008        memset(next, 0, sizeof(*next));
11009        next->syntax = syntax;
11010        next->next = *stack;
11011        (*stack)->prev = next;
11012        *stack = next;
11013}
11014
11015static ALWAYS_INLINE void
11016synstack_pop(struct synstack **stack)
11017{
11018        *stack = (*stack)->next;
11019}
11020
11021/*
11022 * To handle the "." command, a stack of input files is used.  Pushfile
11023 * adds a new entry to the stack and popfile restores the previous level.
11024 */
11025static void
11026pushfile(void)
11027{
11028        struct parsefile *pf;
11029
11030        pf = ckzalloc(sizeof(*pf));
11031        pf->prev = g_parsefile;
11032        pf->pf_fd = -1;
11033        /*pf->strpush = NULL; - ckzalloc did it */
11034        /*pf->basestrpush.prev = NULL;*/
11035        /*pf->unget = 0;*/
11036        g_parsefile = pf;
11037}
11038
11039static void
11040popfile(void)
11041{
11042        struct parsefile *pf = g_parsefile;
11043
11044        if (pf == &basepf)
11045                return;
11046
11047        INT_OFF;
11048        if (pf->pf_fd >= 0)
11049                close(pf->pf_fd);
11050        free(pf->buf);
11051        while (pf->strpush)
11052                popstring();
11053        g_parsefile = pf->prev;
11054        free(pf);
11055        INT_ON;
11056}
11057
11058static void
11059unwindfiles(struct parsefile *stop)
11060{
11061        while (g_parsefile != stop)
11062                popfile();
11063}
11064
11065/*
11066 * Return to top level.
11067 */
11068static void
11069popallfiles(void)
11070{
11071        unwindfiles(&basepf);
11072}
11073
11074/*
11075 * Close the file(s) that the shell is reading commands from.  Called
11076 * after a fork is done.
11077 */
11078static void
11079closescript(void)
11080{
11081        popallfiles();
11082        if (g_parsefile->pf_fd > 0) {
11083                close(g_parsefile->pf_fd);
11084                g_parsefile->pf_fd = 0;
11085        }
11086}
11087
11088/*
11089 * Like setinputfile, but takes an open file descriptor.  Call this with
11090 * interrupts off.
11091 */
11092static void
11093setinputfd(int fd, int push)
11094{
11095        if (push) {
11096                pushfile();
11097                g_parsefile->buf = NULL;
11098        }
11099        g_parsefile->pf_fd = fd;
11100        if (g_parsefile->buf == NULL)
11101                g_parsefile->buf = ckmalloc(IBUFSIZ);
11102        g_parsefile->left_in_buffer = 0;
11103        g_parsefile->left_in_line = 0;
11104        g_parsefile->linno = 1;
11105}
11106
11107/*
11108 * Set the input to take input from a file.  If push is set, push the
11109 * old input onto the stack first.
11110 */
11111static int
11112setinputfile(const char *fname, int flags)
11113{
11114        int fd;
11115
11116        INT_OFF;
11117        fd = open(fname, O_RDONLY | O_CLOEXEC);
11118        if (fd < 0) {
11119                if (flags & INPUT_NOFILE_OK)
11120                        goto out;
11121                exitstatus = 127;
11122                ash_msg_and_raise_perror("can't open '%s'", fname);
11123        }
11124        if (fd < 10)
11125                fd = savefd(fd);
11126        else if (O_CLOEXEC == 0) /* old libc */
11127                close_on_exec_on(fd);
11128
11129        setinputfd(fd, flags & INPUT_PUSH_FILE);
11130 out:
11131        INT_ON;
11132        return fd;
11133}
11134
11135/*
11136 * Like setinputfile, but takes input from a string.
11137 */
11138static void
11139setinputstring(char *string)
11140{
11141        INT_OFF;
11142        pushfile();
11143        g_parsefile->next_to_pgetc = string;
11144        g_parsefile->left_in_line = strlen(string);
11145        g_parsefile->buf = NULL;
11146        g_parsefile->linno = 1;
11147        INT_ON;
11148}
11149
11150
11151/*
11152 * Routines to check for mail.
11153 */
11154
11155#if ENABLE_ASH_MAIL
11156
11157/* Hash of mtimes of mailboxes */
11158static unsigned mailtime_hash;
11159/* Set if MAIL or MAILPATH is changed. */
11160static smallint mail_var_path_changed;
11161
11162/*
11163 * Print appropriate message(s) if mail has arrived.
11164 * If mail_var_path_changed is set,
11165 * then the value of MAIL has mail_var_path_changed,
11166 * so we just update the values.
11167 */
11168static void
11169chkmail(void)
11170{
11171        const char *mpath;
11172        char *p;
11173        char *q;
11174        unsigned new_hash;
11175        struct stackmark smark;
11176        struct stat statb;
11177
11178        setstackmark(&smark);
11179        mpath = mpathset() ? mpathval() : mailval();
11180        new_hash = 0;
11181        for (;;) {
11182                int len;
11183
11184                len = padvance_magic(&mpath, nullstr, 2);
11185                if (!len)
11186                        break;
11187                p = stackblock();
11188                        break;
11189                if (*p == '\0')
11190                        continue;
11191                for (q = p; *q; q++)
11192                        continue;
11193#if DEBUG
11194                if (q[-1] != '/')
11195                        abort();
11196#endif
11197                q[-1] = '\0';                   /* delete trailing '/' */
11198                if (stat(p, &statb) < 0) {
11199                        continue;
11200                }
11201                /* Very simplistic "hash": just a sum of all mtimes */
11202                new_hash += (unsigned)statb.st_mtime;
11203        }
11204        if (!mail_var_path_changed && mailtime_hash != new_hash) {
11205                if (mailtime_hash != 0)
11206                        out2str("you have mail\n");
11207                mailtime_hash = new_hash;
11208        }
11209        mail_var_path_changed = 0;
11210        popstackmark(&smark);
11211}
11212
11213static void FAST_FUNC
11214changemail(const char *val UNUSED_PARAM)
11215{
11216        mail_var_path_changed = 1;
11217}
11218
11219#endif /* ASH_MAIL */
11220
11221
11222/* ============ ??? */
11223
11224/*
11225 * Set the shell parameters.
11226 */
11227static void
11228setparam(char **argv)
11229{
11230        char **newparam;
11231        char **ap;
11232        int nparam;
11233
11234        for (nparam = 0; argv[nparam]; nparam++)
11235                continue;
11236        ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
11237        while (*argv) {
11238                *ap++ = ckstrdup(*argv++);
11239        }
11240        *ap = NULL;
11241        freeparam(&shellparam);
11242        shellparam.malloced = 1;
11243        shellparam.nparam = nparam;
11244        shellparam.p = newparam;
11245#if ENABLE_ASH_GETOPTS
11246        shellparam.optind = 1;
11247        shellparam.optoff = -1;
11248#endif
11249}
11250
11251/*
11252 * Process shell options.  The global variable argptr contains a pointer
11253 * to the argument list; we advance it past the options.
11254 *
11255 * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
11256 * For a non-interactive shell, an error condition encountered
11257 * by a special built-in ... shall cause the shell to write a diagnostic message
11258 * to standard error and exit as shown in the following table:
11259 * Error                                           Special Built-In
11260 * ...
11261 * Utility syntax error (option or operand error)  Shall exit
11262 * ...
11263 * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
11264 * we see that bash does not do that (set "finishes" with error code 1 instead,
11265 * and shell continues), and people rely on this behavior!
11266 * Testcase:
11267 * set -o barfoo 2>/dev/null
11268 * echo $?
11269 *
11270 * Oh well. Let's mimic that.
11271 */
11272static int
11273plus_minus_o(char *name, int val)
11274{
11275        int i;
11276
11277        if (name) {
11278                for (i = 0; i < NOPTS; i++) {
11279                        if (strcmp(name, optnames(i)) == 0) {
11280                                optlist[i] = val;
11281                                return 0;
11282                        }
11283                }
11284                ash_msg("illegal option %co %s", val ? '-' : '+', name);
11285                return 1;
11286        }
11287        for (i = 0; i < NOPTS; i++) {
11288                if (optnames(i)[0] == '\0')
11289                        continue;
11290                if (val) {
11291                        out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
11292                } else {
11293                        out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
11294                }
11295        }
11296        return 0;
11297}
11298static void
11299setoption(int flag, int val)
11300{
11301        int i;
11302
11303        for (i = 0; i < NOPTS; i++) {
11304                if (optletters(i) == flag && optnames(i)[0] != '\0') {
11305                        optlist[i] = val;
11306                        return;
11307                }
11308        }
11309        ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
11310        /* NOTREACHED */
11311}
11312/* If login_sh is not NULL, we are called to parse command line opts,
11313 * not "set -opts"
11314 */
11315static int
11316options(int *login_sh)
11317{
11318        char *p;
11319        int val;
11320        int c;
11321
11322        if (login_sh)
11323                minusc = NULL;
11324        while ((p = *argptr) != NULL) {
11325                c = *p++;
11326                if (c != '-' && c != '+')
11327                        break;
11328                argptr++;
11329                val = 0; /* val = 0 if c == '+' */
11330                if (c == '-') {
11331                        val = 1;
11332                        if (p[0] == '\0' || LONE_DASH(p)) {
11333                                if (!login_sh) {
11334                                        /* "-" means turn off -x and -v */
11335                                        if (p[0] == '\0')
11336                                                xflag = vflag = 0;
11337                                        /* "--" means reset params */
11338                                        else if (*argptr == NULL)
11339                                                setparam(argptr);
11340                                }
11341                                break;    /* "-" or "--" terminates options */
11342                        }
11343                }
11344                /* first char was + or - */
11345                while ((c = *p++) != '\0') {
11346                        if (login_sh) {
11347                                /* bash 3.2 indeed handles -c CMD and +c CMD the same */
11348                                if (c == 'c') {
11349                                        minusc = p; /* command is after shell args */
11350                                        cflag = 1;
11351                                        continue;
11352                                }
11353                                if (c == 's') { /* -s, +s */
11354                                        sflag = 1;
11355                                        continue;
11356                                }
11357                                if (c == 'i') { /* -i, +i */
11358                                        iflag = 1;
11359                                        continue;
11360                                }
11361                                if (c == 'l') {
11362                                        *login_sh = 1; /* -l or +l == --login */
11363                                        continue;
11364                                }
11365                                /* bash does not accept +-login, we also won't */
11366                                if (val && (c == '-')) { /* long options */
11367                                        if (strcmp(p, "login") == 0) {
11368                                                *login_sh = 1;
11369                                        }
11370                                        break;
11371                                }
11372                        }
11373                        if (c == 'o') {
11374                                if (plus_minus_o(*argptr, val)) {
11375                                        /* it already printed err message */
11376                                        return 1; /* error */
11377                                }
11378                                if (*argptr)
11379                                        argptr++;
11380                        } else {
11381                                setoption(c, val);
11382                        }
11383                }
11384        }
11385        return 0;
11386}
11387
11388/*
11389 * The shift builtin command.
11390 */
11391static int FAST_FUNC
11392shiftcmd(int argc UNUSED_PARAM, char **argv)
11393{
11394        int n;
11395        char **ap1, **ap2;
11396
11397        n = 1;
11398        if (argv[1])
11399                n = number(argv[1]);
11400        if (n > shellparam.nparam)
11401                return 1;
11402        INT_OFF;
11403        shellparam.nparam -= n;
11404        for (ap1 = shellparam.p; --n >= 0; ap1++) {
11405                if (shellparam.malloced)
11406                        free(*ap1);
11407        }
11408        ap2 = shellparam.p;
11409        while ((*ap2++ = *ap1++) != NULL)
11410                continue;
11411#if ENABLE_ASH_GETOPTS
11412        shellparam.optind = 1;
11413        shellparam.optoff = -1;
11414#endif
11415        INT_ON;
11416        return 0;
11417}
11418
11419/*
11420 * POSIX requires that 'set' (but not export or readonly) output the
11421 * variables in lexicographic order - by the locale's collating order (sigh).
11422 * Maybe we could keep them in an ordered balanced binary tree
11423 * instead of hashed lists.
11424 * For now just roll 'em through qsort for printing...
11425 */
11426static int
11427showvars(const char *sep_prefix, int on, int off)
11428{
11429        const char *sep;
11430        char **ep, **epend;
11431
11432        ep = listvars(on, off, /*strlist:*/ NULL, &epend);
11433        qsort(ep, epend - ep, sizeof(char *), vpcmp);
11434
11435        sep = *sep_prefix ? " " : sep_prefix;
11436
11437        for (; ep < epend; ep++) {
11438                const char *p;
11439                const char *q;
11440
11441                p = endofname(*ep);
11442/* Used to have simple "p = strchrnul(*ep, '=')" here instead, but this
11443 * makes "export -p" to have output not suitable for "eval":
11444 * import os
11445 * os.environ["test-test"]="test"
11446 * if os.fork() == 0:
11447 *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
11448 * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])
11449 */
11450                q = nullstr;
11451                if (*p == '=')
11452                        q = single_quote(++p);
11453                out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
11454        }
11455        return 0;
11456}
11457
11458/*
11459 * The set command builtin.
11460 */
11461static int FAST_FUNC
11462setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11463{
11464        int retval;
11465
11466        if (!argv[1])
11467                return showvars(nullstr, 0, VUNSET);
11468
11469        INT_OFF;
11470        retval = options(/*login_sh:*/ NULL);
11471        if (retval == 0) { /* if no parse error... */
11472                optschanged();
11473                if (*argptr != NULL) {
11474                        setparam(argptr);
11475                }
11476        }
11477        INT_ON;
11478        return retval;
11479}
11480
11481#if ENABLE_ASH_RANDOM_SUPPORT
11482static void FAST_FUNC
11483change_random(const char *value)
11484{
11485        uint32_t t;
11486
11487        if (value == NULL) {
11488                /* "get", generate */
11489                t = next_random(&random_gen);
11490                /* set without recursion */
11491                setvar(vrandom.var_text, utoa(t), VNOFUNC);
11492                vrandom.flags &= ~VNOFUNC;
11493        } else {
11494                /* set/reset */
11495                t = strtoul(value, NULL, 10);
11496                INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
11497        }
11498}
11499#endif
11500
11501#if BASH_EPOCH_VARS
11502static void FAST_FUNC
11503change_epoch(struct var *vepoch, const char *fmt)
11504{
11505        struct timeval tv;
11506        char buffer[sizeof("%llu.nnnnnn") + sizeof(long long)*3];
11507
11508        xgettimeofday(&tv);
11509        sprintf(buffer, fmt, (unsigned long long)tv.tv_sec, (unsigned)tv.tv_usec);
11510        setvar(vepoch->var_text, buffer, VNOFUNC);
11511        vepoch->flags &= ~VNOFUNC;
11512}
11513
11514static void FAST_FUNC
11515change_seconds(const char *value UNUSED_PARAM)
11516{
11517        change_epoch(&vepochs, "%llu");
11518}
11519
11520static void FAST_FUNC
11521change_realtime(const char *value UNUSED_PARAM)
11522{
11523        change_epoch(&vepochr, "%llu.%06u");
11524}
11525#endif
11526
11527#if ENABLE_ASH_GETOPTS
11528static int
11529getopts(char *optstr, char *optvar, char **optfirst)
11530{
11531        char *p, *q;
11532        char c = '?';
11533        int done = 0;
11534        char sbuf[2];
11535        char **optnext;
11536        int ind = shellparam.optind;
11537        int off = shellparam.optoff;
11538
11539        sbuf[1] = '\0';
11540
11541        shellparam.optind = -1;
11542        optnext = optfirst + ind - 1;
11543
11544        if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
11545                p = NULL;
11546        else
11547                p = optnext[-1] + off;
11548        if (p == NULL || *p == '\0') {
11549                /* Current word is done, advance */
11550                p = *optnext;
11551                if (p == NULL || *p != '-' || *++p == '\0') {
11552 atend:
11553                        unsetvar("OPTARG");
11554                        p = NULL;
11555                        done = 1;
11556                        goto out;
11557                }
11558                optnext++;
11559                if (LONE_DASH(p))        /* check for "--" */
11560                        goto atend;
11561        }
11562
11563        c = *p++;
11564        for (q = optstr; *q != c;) {
11565                if (*q == '\0') {
11566                        /* OPTERR is a bashism */
11567                        const char *cp = lookupvar("OPTERR");
11568                        if ((cp && LONE_CHAR(cp, '0'))
11569                         || (optstr[0] == ':')
11570                        ) {
11571                                sbuf[0] = c;
11572                                /*sbuf[1] = '\0'; - already is */
11573                                setvar0("OPTARG", sbuf);
11574                        } else {
11575                                fprintf(stderr, "Illegal option -%c\n", c);
11576                                unsetvar("OPTARG");
11577                        }
11578                        c = '?';
11579                        goto out;
11580                }
11581                if (*++q == ':')
11582                        q++;
11583        }
11584
11585        if (*++q == ':') {
11586                if (*p == '\0' && (p = *optnext) == NULL) {
11587                        /* OPTERR is a bashism */
11588                        const char *cp = lookupvar("OPTERR");
11589                        if ((cp && LONE_CHAR(cp, '0'))
11590                         || (optstr[0] == ':')
11591                        ) {
11592                                sbuf[0] = c;
11593                                /*sbuf[1] = '\0'; - already is */
11594                                setvar0("OPTARG", sbuf);
11595                                c = ':';
11596                        } else {
11597                                fprintf(stderr, "No arg for -%c option\n", c);
11598                                unsetvar("OPTARG");
11599                                c = '?';
11600                        }
11601                        goto out;
11602                }
11603
11604                if (p == *optnext)
11605                        optnext++;
11606                setvar0("OPTARG", p);
11607                p = NULL;
11608        } else
11609                setvar0("OPTARG", nullstr);
11610 out:
11611        ind = optnext - optfirst + 1;
11612        setvar("OPTIND", itoa(ind), VNOFUNC);
11613        sbuf[0] = c;
11614        /*sbuf[1] = '\0'; - already is */
11615        setvar0(optvar, sbuf);
11616
11617        shellparam.optoff = p ? p - *(optnext - 1) : -1;
11618        shellparam.optind = ind;
11619
11620        return done;
11621}
11622
11623/*
11624 * The getopts builtin.  Shellparam.optnext points to the next argument
11625 * to be processed.  Shellparam.optptr points to the next character to
11626 * be processed in the current argument.  If shellparam.optnext is NULL,
11627 * then it's the first time getopts has been called.
11628 */
11629static int FAST_FUNC
11630getoptscmd(int argc, char **argv)
11631{
11632        char **optbase;
11633
11634        if (argc < 3)
11635                ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11636        if (argc == 3) {
11637                optbase = shellparam.p;
11638                if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11639                        shellparam.optind = 1;
11640                        shellparam.optoff = -1;
11641                }
11642        } else {
11643                optbase = &argv[3];
11644                if ((unsigned)shellparam.optind > argc - 2) {
11645                        shellparam.optind = 1;
11646                        shellparam.optoff = -1;
11647                }
11648        }
11649
11650        return getopts(argv[1], argv[2], optbase);
11651}
11652#endif /* ASH_GETOPTS */
11653
11654
11655/* ============ Shell parser */
11656
11657struct heredoc {
11658        struct heredoc *next;   /* next here document in list */
11659        union node *here;       /* redirection node */
11660        char *eofmark;          /* string indicating end of input */
11661        smallint striptabs;     /* if set, strip leading tabs */
11662};
11663
11664static smallint tokpushback;           /* last token pushed back */
11665static smallint quoteflag;             /* set if (part of) last token was quoted */
11666static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11667static struct heredoc *heredoclist;    /* list of here documents to read */
11668static char *wordtext;                 /* text of last word returned by readtoken */
11669static struct nodelist *backquotelist;
11670static union node *redirnode;
11671static struct heredoc *heredoc;
11672
11673static const char *
11674tokname(char *buf, int tok)
11675{
11676        if (tok < TSEMI)
11677                return tokname_array[tok];
11678        sprintf(buf, "\"%s\"", tokname_array[tok]);
11679        return buf;
11680}
11681
11682/* raise_error_unexpected_syntax:
11683 * Called when an unexpected token is read during the parse.  The argument
11684 * is the token that is expected, or -1 if more than one type of token can
11685 * occur at this point.
11686 */
11687static void raise_error_unexpected_syntax(int) NORETURN;
11688static void
11689raise_error_unexpected_syntax(int token)
11690{
11691        char msg[64];
11692        char buf[16];
11693        int l;
11694
11695        l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11696        if (token >= 0)
11697                sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11698        raise_error_syntax(msg);
11699        /* NOTREACHED */
11700}
11701
11702/* parsing is heavily cross-recursive, need these forward decls */
11703static union node *andor(void);
11704static union node *pipeline(void);
11705static union node *parse_command(void);
11706static void parseheredoc(void);
11707static int peektoken(void);
11708static int readtoken(void);
11709
11710static union node *
11711list(int nlflag)
11712{
11713        union node *n1, *n2, *n3;
11714        int tok;
11715
11716        n1 = NULL;
11717        for (;;) {
11718                switch (readtoken()) {
11719                case TNL:
11720                        if (!(nlflag & 1))
11721                                break;
11722                        parseheredoc();
11723                        return n1;
11724
11725                case TEOF:
11726                        if (!n1 && (nlflag & 1))
11727                                n1 = NODE_EOF;
11728                        parseheredoc();
11729                        tokpushback++;
11730                        lasttoken = TEOF;
11731                        return n1;
11732                }
11733
11734                tokpushback++;
11735                checkkwd = CHKNL | CHKKWD | CHKALIAS;
11736                if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11737                        return n1;
11738                nlflag |= 2;
11739
11740                n2 = andor();
11741                tok = readtoken();
11742                if (tok == TBACKGND) {
11743                        if (n2->type == NPIPE) {
11744                                n2->npipe.pipe_backgnd = 1;
11745                        } else {
11746                                if (n2->type != NREDIR) {
11747                                        n3 = stzalloc(sizeof(struct nredir));
11748                                        n3->nredir.n = n2;
11749                                        /*n3->nredir.redirect = NULL; - stzalloc did it */
11750                                        n2 = n3;
11751                                }
11752                                n2->type = NBACKGND;
11753                        }
11754                }
11755                if (n1 == NULL) {
11756                        n1 = n2;
11757                } else {
11758                        n3 = stzalloc(sizeof(struct nbinary));
11759                        n3->type = NSEMI;
11760                        n3->nbinary.ch1 = n1;
11761                        n3->nbinary.ch2 = n2;
11762                        n1 = n3;
11763                }
11764                switch (tok) {
11765                case TNL:
11766                case TEOF:
11767                        tokpushback = 1;
11768                        /* fall through */
11769                case TBACKGND:
11770                case TSEMI:
11771                        break;
11772                default:
11773                        if ((nlflag & 1))
11774                                raise_error_unexpected_syntax(-1);
11775                        tokpushback = 1;
11776                        return n1;
11777                }
11778        }
11779}
11780
11781static union node *
11782andor(void)
11783{
11784        union node *n1, *n2, *n3;
11785        int t;
11786
11787        n1 = pipeline();
11788        for (;;) {
11789                t = readtoken();
11790                if (t == TAND) {
11791                        t = NAND;
11792                } else if (t == TOR) {
11793                        t = NOR;
11794                } else {
11795                        tokpushback = 1;
11796                        return n1;
11797                }
11798                checkkwd = CHKNL | CHKKWD | CHKALIAS;
11799                n2 = pipeline();
11800                n3 = stzalloc(sizeof(struct nbinary));
11801                n3->type = t;
11802                n3->nbinary.ch1 = n1;
11803                n3->nbinary.ch2 = n2;
11804                n1 = n3;
11805        }
11806}
11807
11808static union node *
11809pipeline(void)
11810{
11811        union node *n1, *n2, *pipenode;
11812        struct nodelist *lp, *prev;
11813        int negate;
11814
11815        negate = 0;
11816        TRACE(("pipeline: entered\n"));
11817        if (readtoken() == TNOT) {
11818                negate = !negate;
11819                checkkwd = CHKKWD | CHKALIAS;
11820        } else
11821                tokpushback = 1;
11822        n1 = parse_command();
11823        if (readtoken() == TPIPE) {
11824                pipenode = stzalloc(sizeof(struct npipe));
11825                pipenode->type = NPIPE;
11826                /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11827                lp = stzalloc(sizeof(struct nodelist));
11828                pipenode->npipe.cmdlist = lp;
11829                lp->n = n1;
11830                do {
11831                        prev = lp;
11832                        lp = stzalloc(sizeof(struct nodelist));
11833                        checkkwd = CHKNL | CHKKWD | CHKALIAS;
11834                        lp->n = parse_command();
11835                        prev->next = lp;
11836                } while (readtoken() == TPIPE);
11837                lp->next = NULL;
11838                n1 = pipenode;
11839        }
11840        tokpushback = 1;
11841        if (negate) {
11842                n2 = stzalloc(sizeof(struct nnot));
11843                n2->type = NNOT;
11844                n2->nnot.com = n1;
11845                return n2;
11846        }
11847        return n1;
11848}
11849
11850static union node *
11851makename(void)
11852{
11853        union node *n;
11854
11855        n = stzalloc(sizeof(struct narg));
11856        n->type = NARG;
11857        /*n->narg.next = NULL; - stzalloc did it */
11858        n->narg.text = wordtext;
11859        n->narg.backquote = backquotelist;
11860        return n;
11861}
11862
11863static void
11864fixredir(union node *n, const char *text, int err)
11865{
11866        int fd;
11867
11868        TRACE(("Fix redir %s %d\n", text, err));
11869        if (!err)
11870                n->ndup.vname = NULL;
11871
11872        fd = bb_strtou(text, NULL, 10);
11873        if (!errno && fd >= 0)
11874                n->ndup.dupfd = fd;
11875        else if (LONE_DASH(text))
11876                n->ndup.dupfd = -1;
11877        else {
11878                if (err)
11879                        raise_error_syntax("bad fd number");
11880                n->ndup.vname = makename();
11881        }
11882}
11883
11884static void
11885parsefname(void)
11886{
11887        union node *n = redirnode;
11888
11889        if (n->type == NHERE)
11890                checkkwd = CHKEOFMARK;
11891        if (readtoken() != TWORD)
11892                raise_error_unexpected_syntax(-1);
11893        if (n->type == NHERE) {
11894                struct heredoc *here = heredoc;
11895                struct heredoc *p;
11896
11897                if (quoteflag == 0)
11898                        n->type = NXHERE;
11899                TRACE(("Here document %d\n", n->type));
11900                rmescapes(wordtext, 0, NULL);
11901                here->eofmark = wordtext;
11902                here->next = NULL;
11903                if (heredoclist == NULL)
11904                        heredoclist = here;
11905                else {
11906                        for (p = heredoclist; p->next; p = p->next)
11907                                continue;
11908                        p->next = here;
11909                }
11910        } else if (n->type == NTOFD || n->type == NFROMFD) {
11911                fixredir(n, wordtext, 0);
11912        } else {
11913                n->nfile.fname = makename();
11914        }
11915}
11916
11917static union node *
11918simplecmd(void)
11919{
11920        union node *args, **app;
11921        union node *n = NULL;
11922        union node *vars, **vpp;
11923        union node **rpp, *redir;
11924        int savecheckkwd;
11925        int savelinno;
11926#if BASH_TEST2
11927        smallint double_brackets_flag = 0;
11928#endif
11929        IF_BASH_FUNCTION(smallint function_flag = 0;)
11930
11931        args = NULL;
11932        app = &args;
11933        vars = NULL;
11934        vpp = &vars;
11935        redir = NULL;
11936        rpp = &redir;
11937
11938        savecheckkwd = CHKALIAS;
11939        savelinno = g_parsefile->linno;
11940        for (;;) {
11941                int t;
11942                checkkwd = savecheckkwd;
11943                t = readtoken();
11944                switch (t) {
11945#if BASH_FUNCTION
11946                case TFUNCTION:
11947                        if (peektoken() != TWORD)
11948                                raise_error_unexpected_syntax(TWORD);
11949                        function_flag = 1;
11950                        break;
11951#endif
11952#if BASH_TEST2
11953                case TAND: /* "&&" */
11954                case TOR: /* "||" */
11955                        if (!double_brackets_flag) {
11956                                tokpushback = 1;
11957                                goto out;
11958                        }
11959                        /* pass "&&" or "||" to [[ ]] as literal args */
11960                        wordtext = (char *) (t == TAND ? "&&" : "||");
11961#endif
11962                case TWORD:
11963                        n = stzalloc(sizeof(struct narg));
11964                        n->type = NARG;
11965                        /*n->narg.next = NULL; - stzalloc did it */
11966                        n->narg.text = wordtext;
11967#if BASH_TEST2
11968                        if (strcmp("[[", wordtext) == 0)
11969                                double_brackets_flag = 1;
11970                        else if (strcmp("]]", wordtext) == 0)
11971                                double_brackets_flag = 0;
11972#endif
11973                        n->narg.backquote = backquotelist;
11974                        if (savecheckkwd && isassignment(wordtext)) {
11975                                *vpp = n;
11976                                vpp = &n->narg.next;
11977                        } else {
11978                                *app = n;
11979                                app = &n->narg.next;
11980                                savecheckkwd = 0;
11981                        }
11982#if BASH_FUNCTION
11983                        if (function_flag) {
11984                                checkkwd = CHKNL | CHKKWD;
11985                                switch (peektoken()) {
11986                                case TBEGIN:
11987                                case TIF:
11988                                case TCASE:
11989                                case TUNTIL:
11990                                case TWHILE:
11991                                case TFOR:
11992                                        goto do_func;
11993                                case TLP:
11994                                        function_flag = 0;
11995                                        break;
11996# if BASH_TEST2
11997                                case TWORD:
11998                                        if (strcmp("[[", wordtext) == 0)
11999                                                goto do_func;
12000                                        /* fall through */
12001# endif
12002                                default:
12003                                        raise_error_unexpected_syntax(-1);
12004                                }
12005                        }
12006#endif
12007                        break;
12008                case TREDIR:
12009                        *rpp = n = redirnode;
12010                        rpp = &n->nfile.next;
12011                        parsefname();   /* read name of redirection file */
12012                        break;
12013                case TLP:
12014 IF_BASH_FUNCTION(do_func:)
12015                        if (args && app == &args->narg.next
12016                         && !vars && !redir
12017                        ) {
12018                                struct builtincmd *bcmd;
12019                                const char *name;
12020
12021                                /* We have a function */
12022                                if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
12023                                        raise_error_unexpected_syntax(TRP);
12024                                name = n->narg.text;
12025                                if (!goodname(name)
12026                                 || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
12027                                ) {
12028                                        raise_error_syntax("bad function name");
12029                                }
12030                                n->type = NDEFUN;
12031                                checkkwd = CHKNL | CHKKWD | CHKALIAS;
12032                                n->ndefun.text = n->narg.text;
12033                                n->ndefun.linno = g_parsefile->linno;
12034                                n->ndefun.body = parse_command();
12035                                return n;
12036                        }
12037                        IF_BASH_FUNCTION(function_flag = 0;)
12038                        /* fall through */
12039                default:
12040                        tokpushback = 1;
12041                        goto out;
12042                }
12043        }
12044 out:
12045        *app = NULL;
12046        *vpp = NULL;
12047        *rpp = NULL;
12048        n = stzalloc(sizeof(struct ncmd));
12049        if (NCMD != 0)
12050                n->type = NCMD;
12051        n->ncmd.linno = savelinno;
12052        n->ncmd.args = args;
12053        n->ncmd.assign = vars;
12054        n->ncmd.redirect = redir;
12055        return n;
12056}
12057
12058static union node *
12059parse_command(void)
12060{
12061        union node *n1, *n2;
12062        union node *ap, **app;
12063        union node *cp, **cpp;
12064        union node *redir, **rpp;
12065        union node **rpp2;
12066        int t;
12067        int savelinno;
12068
12069        redir = NULL;
12070        rpp2 = &redir;
12071
12072        savelinno = g_parsefile->linno;
12073
12074        switch (readtoken()) {
12075        default:
12076                raise_error_unexpected_syntax(-1);
12077                /* NOTREACHED */
12078        case TIF:
12079                n1 = stzalloc(sizeof(struct nif));
12080                n1->type = NIF;
12081                n1->nif.test = list(0);
12082                if (readtoken() != TTHEN)
12083                        raise_error_unexpected_syntax(TTHEN);
12084                n1->nif.ifpart = list(0);
12085                n2 = n1;
12086                while (readtoken() == TELIF) {
12087                        n2->nif.elsepart = stzalloc(sizeof(struct nif));
12088                        n2 = n2->nif.elsepart;
12089                        n2->type = NIF;
12090                        n2->nif.test = list(0);
12091                        if (readtoken() != TTHEN)
12092                                raise_error_unexpected_syntax(TTHEN);
12093                        n2->nif.ifpart = list(0);
12094                }
12095                if (lasttoken == TELSE)
12096                        n2->nif.elsepart = list(0);
12097                else {
12098                        n2->nif.elsepart = NULL;
12099                        tokpushback = 1;
12100                }
12101                t = TFI;
12102                break;
12103        case TWHILE:
12104        case TUNTIL: {
12105                int got;
12106                n1 = stzalloc(sizeof(struct nbinary));
12107                n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
12108                n1->nbinary.ch1 = list(0);
12109                got = readtoken();
12110                if (got != TDO) {
12111                        TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
12112                                        got == TWORD ? wordtext : ""));
12113                        raise_error_unexpected_syntax(TDO);
12114                }
12115                n1->nbinary.ch2 = list(0);
12116                t = TDONE;
12117                break;
12118        }
12119        case TFOR:
12120                if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
12121                        raise_error_syntax("bad for loop variable");
12122                n1 = stzalloc(sizeof(struct nfor));
12123                n1->type = NFOR;
12124                n1->nfor.linno = savelinno;
12125                n1->nfor.var = wordtext;
12126                checkkwd = CHKNL | CHKKWD | CHKALIAS;
12127                if (readtoken() == TIN) {
12128                        app = &ap;
12129                        while (readtoken() == TWORD) {
12130                                n2 = stzalloc(sizeof(struct narg));
12131                                n2->type = NARG;
12132                                /*n2->narg.next = NULL; - stzalloc did it */
12133                                n2->narg.text = wordtext;
12134                                n2->narg.backquote = backquotelist;
12135                                *app = n2;
12136                                app = &n2->narg.next;
12137                        }
12138                        *app = NULL;
12139                        n1->nfor.args = ap;
12140                        if (lasttoken != TNL && lasttoken != TSEMI)
12141                                raise_error_unexpected_syntax(-1);
12142                } else {
12143                        n2 = stzalloc(sizeof(struct narg));
12144                        n2->type = NARG;
12145                        /*n2->narg.next = NULL; - stzalloc did it */
12146                        n2->narg.text = (char *)dolatstr;
12147                        /*n2->narg.backquote = NULL;*/
12148                        n1->nfor.args = n2;
12149                        /*
12150                         * Newline or semicolon here is optional (but note
12151                         * that the original Bourne shell only allowed NL).
12152                         */
12153                        if (lasttoken != TSEMI)
12154                                tokpushback = 1;
12155                }
12156                checkkwd = CHKNL | CHKKWD | CHKALIAS;
12157                if (readtoken() != TDO)
12158                        raise_error_unexpected_syntax(TDO);
12159                n1->nfor.body = list(0);
12160                t = TDONE;
12161                break;
12162        case TCASE:
12163                n1 = stzalloc(sizeof(struct ncase));
12164                n1->type = NCASE;
12165                n1->ncase.linno = savelinno;
12166                if (readtoken() != TWORD)
12167                        raise_error_unexpected_syntax(TWORD);
12168                n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
12169                n2->type = NARG;
12170                /*n2->narg.next = NULL; - stzalloc did it */
12171                n2->narg.text = wordtext;
12172                n2->narg.backquote = backquotelist;
12173                checkkwd = CHKNL | CHKKWD | CHKALIAS;
12174                if (readtoken() != TIN)
12175                        raise_error_unexpected_syntax(TIN);
12176                cpp = &n1->ncase.cases;
12177 next_case:
12178                checkkwd = CHKNL | CHKKWD;
12179                t = readtoken();
12180                while (t != TESAC) {
12181                        if (lasttoken == TLP)
12182                                readtoken();
12183                        *cpp = cp = stzalloc(sizeof(struct nclist));
12184                        cp->type = NCLIST;
12185                        app = &cp->nclist.pattern;
12186                        for (;;) {
12187                                *app = ap = stzalloc(sizeof(struct narg));
12188                                ap->type = NARG;
12189                                /*ap->narg.next = NULL; - stzalloc did it */
12190                                ap->narg.text = wordtext;
12191                                ap->narg.backquote = backquotelist;
12192                                if (readtoken() != TPIPE)
12193                                        break;
12194                                app = &ap->narg.next;
12195                                readtoken();
12196                        }
12197                        //ap->narg.next = NULL;
12198                        if (lasttoken != TRP)
12199                                raise_error_unexpected_syntax(TRP);
12200                        cp->nclist.body = list(2);
12201
12202                        cpp = &cp->nclist.next;
12203
12204                        checkkwd = CHKNL | CHKKWD;
12205                        t = readtoken();
12206                        if (t != TESAC) {
12207                                if (t != TENDCASE)
12208                                        raise_error_unexpected_syntax(TENDCASE);
12209                                goto next_case;
12210                        }
12211                }
12212                *cpp = NULL;
12213                goto redir;
12214        case TLP:
12215                n1 = stzalloc(sizeof(struct nredir));
12216                n1->type = NSUBSHELL;
12217                n1->nredir.linno = savelinno;
12218                n1->nredir.n = list(0);
12219                /*n1->nredir.redirect = NULL; - stzalloc did it */
12220                t = TRP;
12221                break;
12222        case TBEGIN:
12223                n1 = list(0);
12224                t = TEND;
12225                break;
12226        IF_BASH_FUNCTION(case TFUNCTION:)
12227        case TWORD:
12228        case TREDIR:
12229                tokpushback = 1;
12230                return simplecmd();
12231        }
12232
12233        if (readtoken() != t)
12234                raise_error_unexpected_syntax(t);
12235
12236 redir:
12237        /* Now check for redirection which may follow command */
12238        checkkwd = CHKKWD | CHKALIAS;
12239        rpp = rpp2;
12240        while (readtoken() == TREDIR) {
12241                *rpp = n2 = redirnode;
12242                rpp = &n2->nfile.next;
12243                parsefname();
12244        }
12245        tokpushback = 1;
12246        *rpp = NULL;
12247        if (redir) {
12248                if (n1->type != NSUBSHELL) {
12249                        n2 = stzalloc(sizeof(struct nredir));
12250                        n2->type = NREDIR;
12251                        n2->nredir.linno = savelinno;
12252                        n2->nredir.n = n1;
12253                        n1 = n2;
12254                }
12255                n1->nredir.redirect = redir;
12256        }
12257        return n1;
12258}
12259
12260#if BASH_DOLLAR_SQUOTE
12261static int
12262decode_dollar_squote(void)
12263{
12264        static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
12265        int c, cnt;
12266        char *p;
12267        char buf[4];
12268
12269        c = pgetc();
12270        p = strchr(C_escapes, c);
12271        if (p) {
12272                buf[0] = c;
12273                p = buf;
12274                cnt = 3;
12275                if ((unsigned char)(c - '0') <= 7) { /* \ooo */
12276                        do {
12277                                c = pgetc();
12278                                *++p = c;
12279                        } while ((unsigned char)(c - '0') <= 7 && --cnt);
12280                        pungetc();
12281                } else if (c == 'x') { /* \xHH */
12282                        do {
12283                                c = pgetc();
12284                                *++p = c;
12285                        } while (isxdigit(c) && --cnt);
12286                        pungetc();
12287                        if (cnt == 3) { /* \x but next char is "bad" */
12288                                c = 'x';
12289                                goto unrecognized;
12290                        }
12291                } else { /* simple seq like \\ or \t */
12292                        p++;
12293                }
12294                *p = '\0';
12295                p = buf;
12296                c = bb_process_escape_sequence((void*)&p);
12297        } else { /* unrecognized "\z": print both chars unless ' or " */
12298                if (c != '\'' && c != '"') {
12299 unrecognized:
12300                        c |= 0x100; /* "please encode \, then me" */
12301                }
12302        }
12303        return c;
12304}
12305#endif
12306
12307/* Used by expandstr to get here-doc like behaviour. */
12308#define FAKEEOFMARK ((char*)(uintptr_t)1)
12309
12310static ALWAYS_INLINE int
12311realeofmark(const char *eofmark)
12312{
12313        return eofmark && eofmark != FAKEEOFMARK;
12314}
12315
12316/*
12317 * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
12318 * is not NULL, read a here document.  In the latter case, eofmark is the
12319 * word which marks the end of the document and striptabs is true if
12320 * leading tabs should be stripped from the document.  The argument c
12321 * is the first character of the input token or document.
12322 *
12323 * Because C does not have internal subroutines, I have simulated them
12324 * using goto's to implement the subroutine linkage.  The following macros
12325 * will run code that appears at the end of readtoken1.
12326 */
12327#define CHECKEND()      {goto checkend; checkend_return:;}
12328#define PARSEREDIR()    {goto parseredir; parseredir_return:;}
12329#define PARSESUB()      {goto parsesub; parsesub_return:;}
12330#define PARSEBACKQOLD() {style = OLD; goto parsebackq; parsebackq_oldreturn:;}
12331#define PARSEBACKQNEW() {style = NEW; goto parsebackq; parsebackq_newreturn:;}
12332#define PARSEPROCSUB()  {style = PSUB; goto parsebackq; parsebackq_psreturn:;}
12333#define PARSEARITH()    {goto parsearith; parsearith_return:;}
12334static int
12335readtoken1(int c, int syntax, char *eofmark, int striptabs)
12336{
12337        /* NB: syntax parameter fits into smallint */
12338        /* c parameter is an unsigned char or PEOF or PEOA */
12339        char *out;
12340        size_t len;
12341        struct nodelist *bqlist;
12342        smallint quotef;
12343        smallint style;
12344        enum { OLD, NEW, PSUB };
12345#define oldstyle (style == OLD)
12346        smallint pssyntax;   /* we are expanding a prompt string */
12347        IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
12348        /* syntax stack */
12349        struct synstack synbase = { };
12350        struct synstack *synstack = &synbase;
12351
12352#if ENABLE_ASH_EXPAND_PRMT
12353        pssyntax = (syntax == PSSYNTAX);
12354        if (pssyntax)
12355                syntax = DQSYNTAX;
12356#else
12357        pssyntax = 0; /* constant */
12358#endif
12359        synstack->syntax = syntax;
12360
12361        if (syntax == DQSYNTAX)
12362                synstack->dblquote = 1;
12363        quotef = 0;
12364        bqlist = NULL;
12365
12366        STARTSTACKSTR(out);
12367 loop:
12368        /* For each line, until end of word */
12369        CHECKEND();     /* set c to PEOF if at end of here document */
12370        for (;;) {      /* until end of line or end of word */
12371                CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
12372                switch (SIT(c, synstack->syntax)) {
12373                case CNL:       /* '\n' */
12374                        if (synstack->syntax == BASESYNTAX
12375                         && !synstack->varnest
12376                        ) {
12377                                goto endword;   /* exit outer loop */
12378                        }
12379                        USTPUTC(c, out);
12380                        nlprompt();
12381                        c = pgetc_top(synstack);
12382                        goto loop;              /* continue outer loop */
12383                case CWORD:
12384                        USTPUTC(c, out);
12385                        break;
12386                case CCTL:
12387#if BASH_DOLLAR_SQUOTE
12388                        if (c == '\\' && bash_dollar_squote) {
12389                                c = decode_dollar_squote();
12390                                if (c == '\0') {
12391                                        /* skip $'\000', $'\x00' (like bash) */
12392                                        break;
12393                                }
12394                                if (c & 0x100) {
12395                                        /* Unknown escape. Encode as '\z' */
12396                                        c = (unsigned char)c;
12397                                        if (eofmark == NULL || synstack->dblquote)
12398                                                USTPUTC(CTLESC, out);
12399                                        USTPUTC('\\', out);
12400                                }
12401                        }
12402#endif
12403                        if (!eofmark || synstack->dblquote || synstack->varnest)
12404                                USTPUTC(CTLESC, out);
12405                        USTPUTC(c, out);
12406                        break;
12407                case CBACK:     /* backslash */
12408                        c = pgetc_without_PEOA();
12409                        if (c == PEOF) {
12410                                USTPUTC(CTLESC, out);
12411                                USTPUTC('\\', out);
12412                                pungetc();
12413                        } else {
12414                                if (pssyntax && c == '$') {
12415                                        USTPUTC(CTLESC, out);
12416                                        USTPUTC('\\', out);
12417                                }
12418                                /* Backslash is retained if we are in "str"
12419                                 * and next char isn't dquote-special.
12420                                 */
12421                                if (synstack->dblquote
12422                                 && c != '\\'
12423                                 && c != '`'
12424                                 && c != '$'
12425                                 && (c != '"' || (eofmark != NULL && !synstack->varnest))
12426                                 && (c != '}' || !synstack->varnest)
12427                                ) {
12428                                        USTPUTC(CTLESC, out); /* protect '\' from glob */
12429                                        USTPUTC('\\', out);
12430                                }
12431                                USTPUTC(CTLESC, out);
12432                                USTPUTC(c, out);
12433                                quotef = 1;
12434                        }
12435                        break;
12436                case CSQUOTE:
12437                        synstack->syntax = SQSYNTAX;
12438 quotemark:
12439                        if (eofmark == NULL) {
12440                                USTPUTC(CTLQUOTEMARK, out);
12441                        }
12442                        break;
12443                case CDQUOTE:
12444                        synstack->syntax = DQSYNTAX;
12445                        synstack->dblquote = 1;
12446 toggledq:
12447                        if (synstack->varnest)
12448                                synstack->innerdq ^= 1;
12449                        goto quotemark;
12450                case CENDQUOTE:
12451                        IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
12452                        if (eofmark != NULL && synstack->varnest == 0) {
12453                                USTPUTC(c, out);
12454                                break;
12455                        }
12456
12457                        if (synstack->dqvarnest == 0) {
12458                                synstack->syntax = BASESYNTAX;
12459                                synstack->dblquote = 0;
12460                        }
12461
12462                        quotef = 1;
12463
12464                        if (c == '"')
12465                                goto toggledq;
12466
12467                        goto quotemark;
12468                case CVAR:      /* '$' */
12469                        PARSESUB();             /* parse substitution */
12470                        break;
12471                case CENDVAR:   /* '}' */
12472                        if (!synstack->innerdq && synstack->varnest > 0) {
12473                                if (!--synstack->varnest && synstack->varpushed)
12474                                        synstack_pop(&synstack);
12475                                else if (synstack->dqvarnest > 0)
12476                                        synstack->dqvarnest--;
12477                                c = CTLENDVAR;
12478                        }
12479                        USTPUTC(c, out);
12480                        break;
12481#if ENABLE_FEATURE_SH_MATH
12482                case CLP:       /* '(' in arithmetic */
12483                        synstack->parenlevel++;
12484                        USTPUTC(c, out);
12485                        break;
12486                case CRP:       /* ')' in arithmetic */
12487                        if (synstack->parenlevel > 0) {
12488                                synstack->parenlevel--;
12489                        } else {
12490                                if (pgetc_eatbnl() == ')') {
12491                                        c = CTLENDARI;
12492                                        synstack_pop(&synstack);
12493                                } else {
12494                                        /*
12495                                         * unbalanced parens
12496                                         * (don't 2nd guess - no error)
12497                                         */
12498                                        pungetc();
12499                                }
12500                        }
12501                        USTPUTC(c, out);
12502                        break;
12503#endif
12504                case CBQUOTE:   /* '`' */
12505                        if (checkkwd & CHKEOFMARK) {
12506                                quotef = 1;
12507                                USTPUTC('`', out);
12508                                break;
12509                        }
12510
12511                        PARSEBACKQOLD();
12512                        break;
12513                case CENDFILE:
12514                        goto endword;           /* exit outer loop */
12515                case CIGN:
12516                        break;
12517                default:
12518                        if (synstack->varnest == 0) {
12519#if BASH_REDIR_OUTPUT
12520                                if (c == '&') {
12521//Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
12522                                        if (pgetc() == '>')
12523                                                c = 0x100 + '>'; /* flag &> */
12524                                        pungetc();
12525                                }
12526#endif
12527#if BASH_PROCESS_SUBST
12528                                if (c == '<' || c == '>') {
12529                                        if (pgetc() == '(') {
12530                                                PARSEPROCSUB();
12531                                                break;
12532                                        }
12533                                        pungetc();
12534                                }
12535#endif
12536                                goto endword;   /* exit outer loop */
12537                        }
12538                        IF_ASH_ALIAS(if (c != PEOA))
12539                                USTPUTC(c, out);
12540                }
12541                c = pgetc_top(synstack);
12542        } /* for (;;) */
12543 endword:
12544
12545#if ENABLE_FEATURE_SH_MATH
12546        if (synstack->syntax == ARISYNTAX)
12547                raise_error_syntax("missing '))'");
12548#endif
12549        if (synstack->syntax != BASESYNTAX && eofmark == NULL)
12550                raise_error_syntax("unterminated quoted string");
12551        if (synstack->varnest != 0) {
12552                /* { */
12553                raise_error_syntax("missing '}'");
12554        }
12555        USTPUTC('\0', out);
12556        len = out - (char *)stackblock();
12557        out = stackblock();
12558        if (eofmark == NULL) {
12559                if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
12560                 && quotef == 0
12561                ) {
12562                        if (isdigit_str9(out)) {
12563                                PARSEREDIR(); /* passed as params: out, c */
12564                                lasttoken = TREDIR;
12565                                return lasttoken;
12566                        }
12567                        /* else: non-number X seen, interpret it
12568                         * as "NNNX>file" = "NNNX >file" */
12569                }
12570                pungetc();
12571        }
12572        quoteflag = quotef;
12573        backquotelist = bqlist;
12574        grabstackblock(len);
12575        wordtext = out;
12576        lasttoken = TWORD;
12577        return lasttoken;
12578/* end of readtoken routine */
12579
12580/*
12581 * Check to see whether we are at the end of the here document.  When this
12582 * is called, c is set to the first character of the next input line.  If
12583 * we are at the end of the here document, this routine sets the c to PEOF.
12584 */
12585checkend: {
12586        if (realeofmark(eofmark)) {
12587                int markloc;
12588                char *p;
12589
12590#if ENABLE_ASH_ALIAS
12591                if (c == PEOA)
12592                        c = pgetc_without_PEOA();
12593#endif
12594                if (striptabs) {
12595                        while (c == '\t') {
12596                                c = pgetc_without_PEOA();
12597                        }
12598                }
12599
12600                markloc = out - (char *)stackblock();
12601                for (p = eofmark; STPUTC(c, out), *p; p++) {
12602                        if (c != *p)
12603                                goto more_heredoc;
12604                        /* FIXME: fails for backslash-newlined terminator:
12605                         * cat <<EOF
12606                         * ...
12607                         * EO\
12608                         * F
12609                         * (see heredoc_bkslash_newline2.tests)
12610                         */
12611                        c = pgetc_without_PEOA();
12612                }
12613
12614                if (c == '\n' || c == PEOF) {
12615                        c = PEOF;
12616                        g_parsefile->linno++;
12617                        needprompt = doprompt;
12618                } else {
12619                        int len_here;
12620
12621 more_heredoc:
12622                        p = (char *)stackblock() + markloc + 1;
12623                        len_here = out - p;
12624
12625                        if (len_here) {
12626                                len_here -= (c >= PEOF);
12627                                c = p[-1];
12628
12629                                if (len_here) {
12630                                        char *str;
12631
12632                                        str = alloca(len_here + 1);
12633                                        *(char *)mempcpy(str, p, len_here) = '\0';
12634
12635                                        pushstring(str, NULL);
12636                                }
12637                        }
12638                }
12639
12640                STADJUST((char *)stackblock() + markloc - out, out);
12641        }
12642        goto checkend_return;
12643}
12644
12645/*
12646 * Parse a redirection operator.  The variable "out" points to a string
12647 * specifying the fd to be redirected.  The variable "c" contains the
12648 * first character of the redirection operator.
12649 */
12650parseredir: {
12651        /* out is already checked to be a valid number or "" */
12652        int fd = (*out == '\0' ? -1 : atoi(out));
12653        union node *np;
12654
12655        np = stzalloc(sizeof(struct nfile));
12656        if (c == '>') {
12657                np->nfile.fd = 1;
12658                c = pgetc_eatbnl();
12659                if (c == '>')
12660                        np->type = NAPPEND;
12661                else if (c == '|')
12662                        np->type = NCLOBBER;
12663                else if (c == '&')
12664                        np->type = NTOFD;
12665                        /* it also can be NTO2 (>&file), but we can't figure it out yet */
12666                else {
12667                        np->type = NTO;
12668                        pungetc();
12669                }
12670        }
12671#if BASH_REDIR_OUTPUT
12672        else if (c == 0x100 + '>') { /* this flags &> redirection */
12673                np->nfile.fd = 1;
12674                pgetc(); /* this is '>', no need to check */
12675                np->type = NTO2;
12676        }
12677#endif
12678        else { /* c == '<' */
12679                /*np->nfile.fd = 0; - stzalloc did it */
12680                c = pgetc_eatbnl();
12681                switch (c) {
12682                case '<':
12683                        if (sizeof(struct nfile) != sizeof(struct nhere)) {
12684                                np = stzalloc(sizeof(struct nhere));
12685                                /*np->nfile.fd = 0; - stzalloc did it */
12686                        }
12687                        np->type = NHERE;
12688                        heredoc = stzalloc(sizeof(struct heredoc));
12689                        heredoc->here = np;
12690                        c = pgetc_eatbnl();
12691                        if (c == '-') {
12692                                heredoc->striptabs = 1;
12693                        } else {
12694                                /*heredoc->striptabs = 0; - stzalloc did it */
12695                                pungetc();
12696                        }
12697                        break;
12698
12699                case '&':
12700                        np->type = NFROMFD;
12701                        break;
12702
12703                case '>':
12704                        np->type = NFROMTO;
12705                        break;
12706
12707                default:
12708                        np->type = NFROM;
12709                        pungetc();
12710                        break;
12711                }
12712        }
12713        if (fd >= 0)
12714                np->nfile.fd = fd;
12715        redirnode = np;
12716        goto parseredir_return;
12717}
12718
12719/*
12720 * Parse a substitution.  At this point, we have read the dollar sign
12721 * and nothing else.
12722 */
12723
12724/* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12725 * (assuming ascii char codes, as the original implementation did) */
12726#define is_special(c) \
12727        (((unsigned)(c) - 33 < 32) \
12728                        && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12729parsesub: {
12730        unsigned char subtype;
12731        int typeloc;
12732
12733        c = pgetc_eatbnl();
12734        if ((checkkwd & CHKEOFMARK)
12735         || c > 255 /* PEOA or PEOF */
12736         || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12737        ) {
12738#if BASH_DOLLAR_SQUOTE
12739                if (synstack->syntax != DQSYNTAX && c == '\'')
12740                        bash_dollar_squote = 1;
12741                else
12742#endif
12743                        USTPUTC('$', out);
12744                pungetc();
12745        } else if (c == '(') {
12746                /* $(command) or $((arith)) */
12747                if (pgetc_eatbnl() == '(') {
12748#if ENABLE_FEATURE_SH_MATH
12749                        PARSEARITH();
12750#else
12751                        raise_error_syntax("support for $((arith)) is disabled");
12752#endif
12753                } else {
12754                        pungetc();
12755                        PARSEBACKQNEW();
12756                }
12757        } else {
12758                /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12759                smalluint newsyn = synstack->syntax;
12760
12761                USTPUTC(CTLVAR, out);
12762                typeloc = out - (char *)stackblock();
12763                STADJUST(1, out);
12764                subtype = VSNORMAL;
12765                if (c == '{') {
12766                        c = pgetc_eatbnl();
12767                        subtype = 0;
12768                }
12769 varname:
12770                if (is_name(c)) {
12771                        /* $[{[#]]NAME[}] */
12772                        do {
12773                                STPUTC(c, out);
12774                                c = pgetc_eatbnl();
12775                        } while (is_in_name(c));
12776                } else if (isdigit(c)) {
12777                        /* $[{[#]]NUM[}] */
12778                        do {
12779                                STPUTC(c, out);
12780                                c = pgetc_eatbnl();
12781                        } while ((subtype == 0 || subtype == VSLENGTH) && isdigit(c));
12782                } else if (c != '}') {
12783                        /* $[{[#]]<specialchar>[}] */
12784                        int cc = c;
12785
12786                        c = pgetc_eatbnl();
12787                        if (!subtype && cc == '#') {
12788                                subtype = VSLENGTH;
12789                                if (c == '_' || isalnum(c))
12790                                        goto varname;
12791                                cc = c;
12792                                c = pgetc_eatbnl();
12793                                if (cc == '}' || c != '}') {
12794                                        pungetc();
12795                                        subtype = 0;
12796                                        c = cc;
12797                                        cc = '#';
12798                                }
12799                        }
12800
12801                        if (!is_special(cc)) {
12802                                if (subtype == VSLENGTH)
12803                                        subtype = 0;
12804                                goto badsub;
12805                        }
12806
12807                        USTPUTC(cc, out);
12808                } else
12809                        goto badsub;
12810
12811                if (subtype == 0) {
12812                        static const char types[] ALIGN1 = "}-+?=";
12813                        /* ${VAR...} but not $VAR or ${#VAR} */
12814                        /* c == first char after VAR */
12815                        int cc = c;
12816
12817                        switch (c) {
12818                        case ':':
12819                                c = pgetc_eatbnl();
12820#if BASH_SUBSTR
12821                                /* This check is only needed to not misinterpret
12822                                 * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12823                                 * constructs.
12824                                 */
12825                                if (!strchr(types, c)) {
12826                                        subtype = VSSUBSTR;
12827                                        pungetc();
12828                                        break; /* "goto badsub" is bigger (!) */
12829                                }
12830#endif
12831                                subtype = VSNUL;
12832                                /*FALLTHROUGH*/
12833                        default: {
12834                                const char *p = strchr(types, c);
12835                                if (p == NULL)
12836                                        break;
12837                                subtype |= p - types + VSNORMAL;
12838                                break;
12839                        }
12840                        case '%':
12841                        case '#':
12842                                subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12843                                c = pgetc_eatbnl();
12844                                if (c == cc)
12845                                        subtype++;
12846                                else
12847                                        pungetc();
12848
12849                                newsyn = BASESYNTAX;
12850                                break;
12851#if BASH_PATTERN_SUBST
12852                        case '/':
12853                                /* ${v/[/]pattern/repl} */
12854//TODO: encode pattern and repl separately.
12855// Currently cases like: v=1;echo ${v/$((1/1))/ONE}
12856// are broken (should print "ONE")
12857                                subtype = VSREPLACE;
12858                                newsyn = BASESYNTAX;
12859                                c = pgetc_eatbnl();
12860                                if (c != '/')
12861                                        goto badsub;
12862                                subtype++; /* VSREPLACEALL */
12863                                break;
12864#endif
12865                        }
12866                } else {
12867                        if (subtype == VSLENGTH && c != '}')
12868                                subtype = 0;
12869 badsub:
12870                        pungetc();
12871                }
12872
12873                if (newsyn == ARISYNTAX)
12874                        newsyn = DQSYNTAX;
12875
12876                if ((newsyn != synstack->syntax || synstack->innerdq)
12877                 && subtype != VSNORMAL
12878                ) {
12879                        synstack_push(&synstack,
12880                                synstack->prev ?: alloca(sizeof(*synstack)),
12881                                newsyn);
12882
12883                        synstack->varpushed = 1;
12884                        synstack->dblquote = newsyn != BASESYNTAX;
12885                }
12886
12887                ((unsigned char *)stackblock())[typeloc] = subtype;
12888                if (subtype != VSNORMAL) {
12889                        synstack->varnest++;
12890                        if (synstack->dblquote)
12891                                synstack->dqvarnest++;
12892                }
12893                STPUTC('=', out);
12894        }
12895        goto parsesub_return;
12896}
12897
12898/*
12899 * Called to parse command substitutions.  Newstyle is set if the command
12900 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12901 * list of commands (passed by reference), and savelen is the number of
12902 * characters on the top of the stack which must be preserved.
12903 */
12904parsebackq: {
12905        struct nodelist **nlpp;
12906        union node *n;
12907        char *str;
12908        size_t savelen;
12909        struct heredoc *saveheredoclist;
12910        smallint saveprompt = 0;
12911
12912        str = NULL;
12913        savelen = out - (char *)stackblock();
12914        if (savelen > 0) {
12915                /*
12916                 * FIXME: this can allocate very large block on stack and SEGV.
12917                 * Example:
12918                 * echo "..<100kbytes>..`true` $(true) `true` ..."
12919                 * allocates 100kb for every command subst. With about
12920                 * a hundred command substitutions stack overflows.
12921                 * With larger prepended string, SEGV happens sooner.
12922                 */
12923                str = alloca(savelen);
12924                memcpy(str, stackblock(), savelen);
12925        }
12926
12927        if (oldstyle) {
12928                /* We must read until the closing backquote, giving special
12929                 * treatment to some slashes, and then push the string and
12930                 * reread it as input, interpreting it normally.
12931                 */
12932                char *pout;
12933                size_t psavelen;
12934                char *pstr;
12935
12936                STARTSTACKSTR(pout);
12937                for (;;) {
12938                        int pc;
12939
12940                        setprompt_if(needprompt, 2);
12941                        pc = pgetc_eatbnl();
12942                        switch (pc) {
12943                        case '`':
12944                                goto done;
12945
12946                        case '\\':
12947                                pc = pgetc(); /* not pgetc_eatbnl! */
12948                                if (pc != '\\' && pc != '`' && pc != '$'
12949                                 && (!synstack->dblquote || pc != '"')
12950                                ) {
12951                                        STPUTC('\\', pout);
12952                                }
12953                                if (pc <= 255 /* not PEOA or PEOF */) {
12954                                        break;
12955                                }
12956                                /* fall through */
12957
12958                        case PEOF:
12959                        IF_ASH_ALIAS(case PEOA:)
12960                                raise_error_syntax("EOF in backquote substitution");
12961
12962                        case '\n':
12963                                nlnoprompt();
12964                                break;
12965
12966                        default:
12967                                break;
12968                        }
12969                        STPUTC(pc, pout);
12970                }
12971 done:
12972                STPUTC('\0', pout);
12973                psavelen = pout - (char *)stackblock();
12974                if (psavelen > 0) {
12975                        pstr = grabstackstr(pout);
12976                        setinputstring(pstr);
12977                }
12978        }
12979        nlpp = &bqlist;
12980        while (*nlpp)
12981                nlpp = &(*nlpp)->next;
12982        *nlpp = stzalloc(sizeof(**nlpp));
12983        /* (*nlpp)->next = NULL; - stzalloc did it */
12984
12985        saveheredoclist = heredoclist;
12986        heredoclist = NULL;
12987
12988        if (oldstyle) {
12989                saveprompt = doprompt;
12990                doprompt = 0;
12991        }
12992
12993        n = list(2);
12994
12995        if (oldstyle)
12996                doprompt = saveprompt;
12997        else {
12998                if (readtoken() != TRP)
12999                        raise_error_unexpected_syntax(TRP);
13000                setinputstring(nullstr);
13001        }
13002
13003        parseheredoc();
13004        heredoclist = saveheredoclist;
13005
13006        (*nlpp)->n = n;
13007        /* Start reading from old file again. */
13008        popfile();
13009        /* Ignore any pushed back tokens left from the backquote parsing. */
13010        if (oldstyle)
13011                tokpushback = 0;
13012        out = growstackto(savelen + 1);
13013        if (str) {
13014                memcpy(out, str, savelen);
13015                STADJUST(savelen, out);
13016        }
13017#if BASH_PROCESS_SUBST
13018        if (style == PSUB)
13019                USTPUTC(c == '<' ? CTLFROMPROC : CTLTOPROC, out);
13020        else
13021#endif
13022                USTPUTC(CTLBACKQ, out);
13023        if (oldstyle)
13024                goto parsebackq_oldreturn;
13025#if BASH_PROCESS_SUBST
13026        else if (style == PSUB)
13027                goto parsebackq_psreturn;
13028#endif
13029        goto parsebackq_newreturn;
13030}
13031
13032#if ENABLE_FEATURE_SH_MATH
13033/*
13034 * Parse an arithmetic expansion (indicate start of one and set state)
13035 */
13036parsearith: {
13037
13038        synstack_push(&synstack,
13039                        synstack->prev ?: alloca(sizeof(*synstack)),
13040                        ARISYNTAX);
13041        synstack->dblquote = 1;
13042        USTPUTC(CTLARI, out);
13043        goto parsearith_return;
13044}
13045#endif
13046} /* end of readtoken */
13047
13048/*
13049 * Read the next input token.
13050 * If the token is a word, we set backquotelist to the list of cmds in
13051 *      backquotes.  We set quoteflag to true if any part of the word was
13052 *      quoted.
13053 * If the token is TREDIR, then we set redirnode to a structure containing
13054 *      the redirection.
13055 *
13056 * [Change comment:  here documents and internal procedures]
13057 * [Readtoken shouldn't have any arguments.  Perhaps we should make the
13058 *  word parsing code into a separate routine.  In this case, readtoken
13059 *  doesn't need to have any internal procedures, but parseword does.
13060 *  We could also make parseoperator in essence the main routine, and
13061 *  have parseword (readtoken1?) handle both words and redirection.]
13062 */
13063#define NEW_xxreadtoken
13064#ifdef NEW_xxreadtoken
13065/* singles must be first! */
13066static const char xxreadtoken_chars[7] ALIGN1 = {
13067        '\n', '(', ')', /* singles */
13068        '&', '|', ';',  /* doubles */
13069        0
13070};
13071
13072#define xxreadtoken_singles 3
13073#define xxreadtoken_doubles 3
13074
13075static const char xxreadtoken_tokens[] ALIGN1 = {
13076        TNL, TLP, TRP,          /* only single occurrence allowed */
13077        TBACKGND, TPIPE, TSEMI, /* if single occurrence */
13078        TEOF,                   /* corresponds to trailing nul */
13079        TAND, TOR, TENDCASE     /* if double occurrence */
13080};
13081
13082static int
13083xxreadtoken(void)
13084{
13085        int c;
13086
13087        if (tokpushback) {
13088                tokpushback = 0;
13089                return lasttoken;
13090        }
13091        setprompt_if(needprompt, 2);
13092        for (;;) {                      /* until token or start of word found */
13093                c = pgetc_eatbnl();
13094                if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
13095                        continue;
13096
13097                if (c == '#') {
13098                        while ((c = pgetc()) != '\n' && c != PEOF)
13099                                continue;
13100                        pungetc();
13101                } else if (c == '\\') {
13102                        break; /* return readtoken1(...) */
13103                } else {
13104                        const char *p;
13105
13106                        p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
13107                        if (c != PEOF) {
13108                                if (c == '\n') {
13109                                        nlnoprompt();
13110                                }
13111
13112                                p = strchr(xxreadtoken_chars, c);
13113                                if (p == NULL)
13114                                        break; /* return readtoken1(...) */
13115
13116                                if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
13117                                        int cc = pgetc_eatbnl();
13118                                        if (cc == c) {    /* double occurrence? */
13119                                                p += xxreadtoken_doubles + 1;
13120                                        } else {
13121                                                pungetc();
13122#if BASH_REDIR_OUTPUT
13123                                                if (c == '&' && cc == '>') /* &> */
13124                                                        break; /* return readtoken1(...) */
13125#endif
13126                                        }
13127                                }
13128                        }
13129                        lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
13130                        return lasttoken;
13131                }
13132        } /* for (;;) */
13133
13134        return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
13135}
13136#else /* old xxreadtoken */
13137#define RETURN(token)   return lasttoken = token
13138static int
13139xxreadtoken(void)
13140{
13141        int c;
13142
13143        if (tokpushback) {
13144                tokpushback = 0;
13145                return lasttoken;
13146        }
13147        setprompt_if(needprompt, 2);
13148        for (;;) {      /* until token or start of word found */
13149                c = pgetc_eatbnl();
13150                switch (c) {
13151                case ' ': case '\t':
13152                IF_ASH_ALIAS(case PEOA:)
13153                        continue;
13154                case '#':
13155                        while ((c = pgetc()) != '\n' && c != PEOF)
13156                                continue;
13157                        pungetc();
13158                        continue;
13159                case '\n':
13160                        nlnoprompt();
13161                        RETURN(TNL);
13162                case PEOF:
13163                        RETURN(TEOF);
13164                case '&':
13165                        if (pgetc_eatbnl() == '&')
13166                                RETURN(TAND);
13167                        pungetc();
13168                        RETURN(TBACKGND);
13169                case '|':
13170                        if (pgetc_eatbnl() == '|')
13171                                RETURN(TOR);
13172                        pungetc();
13173                        RETURN(TPIPE);
13174                case ';':
13175                        if (pgetc_eatbnl() == ';')
13176                                RETURN(TENDCASE);
13177                        pungetc();
13178                        RETURN(TSEMI);
13179                case '(':
13180                        RETURN(TLP);
13181                case ')':
13182                        RETURN(TRP);
13183                }
13184                break;
13185        }
13186        return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
13187#undef RETURN
13188}
13189#endif /* old xxreadtoken */
13190
13191static int
13192readtoken(void)
13193{
13194        int t;
13195        int kwd = checkkwd;
13196#if DEBUG
13197        smallint alreadyseen = tokpushback;
13198#endif
13199
13200#if ENABLE_ASH_ALIAS
13201 top:
13202#endif
13203
13204        t = xxreadtoken();
13205
13206        /*
13207         * eat newlines
13208         */
13209        if (kwd & CHKNL) {
13210                while (t == TNL) {
13211                        parseheredoc();
13212                        t = xxreadtoken();
13213                }
13214        }
13215
13216        if (t != TWORD || quoteflag) {
13217                goto out;
13218        }
13219
13220        /*
13221         * check for keywords
13222         */
13223        if (kwd & CHKKWD) {
13224                const char *const *pp;
13225
13226                pp = findkwd(wordtext);
13227                if (pp) {
13228                        lasttoken = t = pp - tokname_array;
13229                        TRACE(("keyword '%s' recognized\n", tokname_array[t]));
13230                        goto out;
13231                }
13232        }
13233
13234        if (checkkwd & CHKALIAS) {
13235#if ENABLE_ASH_ALIAS
13236                struct alias *ap;
13237                ap = lookupalias(wordtext, 1);
13238                if (ap != NULL) {
13239                        if (*ap->val) {
13240                                pushstring(ap->val, ap);
13241                        }
13242                        goto top;
13243                }
13244#endif
13245        }
13246 out:
13247        checkkwd = 0;
13248#if DEBUG
13249        if (!alreadyseen)
13250                TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
13251        else
13252                TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
13253#endif
13254        return t;
13255}
13256
13257static int
13258peektoken(void)
13259{
13260        int t;
13261
13262        t = readtoken();
13263        tokpushback = 1;
13264        return t;
13265}
13266
13267/*
13268 * Read and parse a command.  Returns NODE_EOF on end of file.
13269 * (NULL is a valid parse tree indicating a blank line.)
13270 */
13271static union node *
13272parsecmd(int interact)
13273{
13274        tokpushback = 0;
13275        checkkwd = 0;
13276        heredoclist = 0;
13277        doprompt = interact;
13278        setprompt_if(doprompt, doprompt);
13279        needprompt = 0;
13280        return list(1);
13281}
13282
13283/*
13284 * Input any here documents.
13285 */
13286static void
13287parseheredoc(void)
13288{
13289        struct heredoc *here;
13290        union node *n;
13291
13292        here = heredoclist;
13293        heredoclist = NULL;
13294
13295        while (here) {
13296                tokpushback = 0;
13297                setprompt_if(needprompt, 2);
13298                if (here->here->type == NHERE)
13299                        readtoken1(pgetc(), SQSYNTAX, here->eofmark, here->striptabs);
13300                else
13301                        readtoken1(pgetc_eatbnl(), DQSYNTAX, here->eofmark, here->striptabs);
13302                n = stzalloc(sizeof(struct narg));
13303                n->narg.type = NARG;
13304                /*n->narg.next = NULL; - stzalloc did it */
13305                n->narg.text = wordtext;
13306                n->narg.backquote = backquotelist;
13307                here->here->nhere.doc = n;
13308                here = here->next;
13309        }
13310}
13311
13312
13313static const char *
13314expandstr(const char *ps, int syntax_type)
13315{
13316        union node n;
13317        int saveprompt;
13318        struct parsefile *file_stop = g_parsefile;
13319        volatile int saveint;
13320        struct jmploc *volatile savehandler = exception_handler;
13321        struct jmploc jmploc;
13322        const char *volatile result;
13323        int err;
13324
13325        /* XXX Fix (char *) cast. */
13326        setinputstring((char *)ps);
13327
13328        saveprompt = doprompt;
13329        doprompt = 0;
13330        result = ps;
13331
13332        SAVE_INT(saveint);
13333        err = setjmp(jmploc.loc);
13334        if (err)
13335                goto out;
13336
13337        /* readtoken1() might die horribly.
13338         * Try a prompt with syntactically wrong command:
13339         * PS1='$(date "+%H:%M:%S) > '
13340         */
13341        exception_handler = &jmploc;
13342        readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
13343
13344        n.narg.type = NARG;
13345        n.narg.next = NULL;
13346        n.narg.text = wordtext;
13347        n.narg.backquote = backquotelist;
13348
13349        /* expandarg() might fail too:
13350         * PS1='$((123+))'
13351         */
13352        expandarg(&n, NULL, EXP_QUOTED);
13353        result = stackblock();
13354
13355out:
13356        exception_handler = savehandler;
13357        if (err && exception_type != EXERROR)
13358                longjmp(exception_handler->loc, 1);
13359        RESTORE_INT(saveint);
13360
13361        doprompt = saveprompt;
13362        /* Try: PS1='`xxx(`' */
13363        unwindfiles(file_stop);
13364
13365        return result;
13366}
13367
13368static inline int
13369parser_eof(void)
13370{
13371        return tokpushback && lasttoken == TEOF;
13372}
13373
13374/*
13375 * Execute a command or commands contained in a string.
13376 */
13377static int
13378evalstring(char *s, int flags)
13379{
13380        struct jmploc *volatile savehandler;
13381        struct jmploc jmploc;
13382        int ex;
13383
13384        union node *n;
13385        struct stackmark smark;
13386        int status;
13387
13388        s = sstrdup(s);
13389        setinputstring(s);
13390        setstackmark(&smark);
13391
13392        status = 0;
13393        /* On exception inside execution loop, we must popfile().
13394         * Try interactively:
13395         *      readonly a=a
13396         *      command eval "a=b"  # throws "is read only" error
13397         * "command BLTIN" is not supposed to abort (even in non-interactive use).
13398         * But if we skip popfile(), we hit EOF in eval's string, and exit.
13399         */
13400        savehandler = exception_handler;
13401        ex = setjmp(jmploc.loc);
13402        if (ex)
13403                goto out;
13404        exception_handler = &jmploc;
13405
13406        while ((n = parsecmd(0)) != NODE_EOF) {
13407                int i;
13408
13409                i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
13410                if (n)
13411                        status = i;
13412                popstackmark(&smark);
13413                if (evalskip)
13414                        break;
13415        }
13416 out:
13417        popstackmark(&smark);
13418        popfile();
13419        stunalloc(s);
13420
13421        exception_handler = savehandler;
13422        if (ex)
13423                longjmp(exception_handler->loc, ex);
13424
13425        return status;
13426}
13427
13428/*
13429 * The eval command.
13430 */
13431static int FAST_FUNC
13432evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
13433{
13434        char *p;
13435        char *concat;
13436
13437        if (argv[1]) {
13438                p = argv[1];
13439                argv += 2;
13440                if (argv[0]) {
13441                        STARTSTACKSTR(concat);
13442                        for (;;) {
13443                                concat = stack_putstr(p, concat);
13444                                p = *argv++;
13445                                if (p == NULL)
13446                                        break;
13447                                STPUTC(' ', concat);
13448                        }
13449                        STPUTC('\0', concat);
13450                        p = grabstackstr(concat);
13451                }
13452                return evalstring(p, flags & EV_TESTED);
13453        }
13454        return 0;
13455}
13456
13457/*
13458 * Read and execute commands.
13459 * "Top" is nonzero for the top level command loop;
13460 * it turns on prompting if the shell is interactive.
13461 */
13462static int
13463cmdloop(int top)
13464{
13465        union node *n;
13466        struct stackmark smark;
13467        int inter;
13468        int status = 0;
13469        int numeof = 0;
13470
13471        TRACE(("cmdloop(%d) called\n", top));
13472        for (;;) {
13473                int skip;
13474
13475                setstackmark(&smark);
13476#if JOBS
13477                if (doing_jobctl)
13478                        showjobs(SHOW_CHANGED|SHOW_STDERR);
13479#endif
13480#if BASH_PROCESS_SUBST
13481                unwindredir(NULL);
13482#endif
13483                inter = 0;
13484                if (iflag && top) {
13485                        inter++;
13486                        chkmail();
13487                }
13488                n = parsecmd(inter);
13489#if DEBUG
13490                if (DEBUG > 2 && debug && (n != NODE_EOF))
13491                        showtree(n);
13492#endif
13493                if (n == NODE_EOF) {
13494                        if (!top || numeof >= 50)
13495                                break;
13496                        if (!stoppedjobs()) {
13497                                if (!Iflag) {
13498                                        if (iflag) {
13499                                                newline_and_flush(stderr);
13500                                        }
13501                                        break;
13502                                }
13503                                out2str("\nUse \"exit\" to leave shell.\n");
13504                        }
13505                        numeof++;
13506                } else if (nflag == 0) {
13507                        int i;
13508
13509                        /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
13510                        job_warning >>= 1;
13511                        numeof = 0;
13512                        i = evaltree(n, 0);
13513                        if (n)
13514                                status = i;
13515                }
13516                popstackmark(&smark);
13517                skip = evalskip;
13518
13519                if (skip) {
13520                        evalskip &= ~(SKIPFUNC | SKIPFUNCDEF);
13521                        break;
13522                }
13523        }
13524        return status;
13525}
13526
13527/*
13528 * Take commands from a file.  To be compatible we should do a path
13529 * search for the file, which is necessary to find sub-commands.
13530 */
13531static char *
13532find_dot_file(char *basename)
13533{
13534        char *fullname;
13535        const char *path = pathval();
13536        struct stat statb;
13537        int len;
13538
13539        /* don't try this for absolute or relative paths */
13540        if (strchr(basename, '/'))
13541                return basename;
13542
13543        while ((len = padvance(&path, basename)) >= 0) {
13544                fullname = stackblock();
13545                if ((!pathopt || *pathopt == 'f')
13546                 && !stat(fullname, &statb) && S_ISREG(statb.st_mode)
13547                ) {
13548                        /* This will be freed by the caller. */
13549                        return stalloc(len);
13550                }
13551        }
13552        /* not found in PATH */
13553
13554#if ENABLE_ASH_BASH_SOURCE_CURDIR
13555        return basename;
13556#else
13557        ash_msg_and_raise_error("%s: not found", basename);
13558        /* NOTREACHED */
13559#endif
13560}
13561
13562static int FAST_FUNC
13563dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
13564{
13565        /* "false; . empty_file; echo $?" should print 0, not 1: */
13566        int status = 0;
13567        char *fullname;
13568        char **argv;
13569        char *args_need_save;
13570        volatile struct shparam saveparam;
13571
13572//???
13573//      struct strlist *sp;
13574//      for (sp = cmdenviron; sp; sp = sp->next)
13575//              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
13576
13577        nextopt(nullstr); /* handle possible "--" */
13578        argv = argptr;
13579
13580        if (!argv[0]) {
13581                /* bash says: "bash: .: filename argument required" */
13582                return 2; /* bash compat */
13583        }
13584
13585        /* This aborts if file isn't found, which is POSIXly correct.
13586         * bash returns exitcode 1 instead.
13587         */
13588        fullname = find_dot_file(argv[0]);
13589        argv++;
13590        args_need_save = argv[0];
13591        if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
13592                int argc;
13593                saveparam = shellparam;
13594                shellparam.malloced = 0;
13595                argc = 1;
13596                while (argv[argc])
13597                        argc++;
13598                shellparam.nparam = argc;
13599                shellparam.p = argv;
13600        };
13601
13602        /* This aborts if file can't be opened, which is POSIXly correct.
13603         * bash returns exitcode 1 instead.
13604         */
13605        setinputfile(fullname, INPUT_PUSH_FILE);
13606        commandname = fullname;
13607        status = cmdloop(0);
13608        popfile();
13609
13610        if (args_need_save) {
13611                freeparam(&shellparam);
13612                shellparam = saveparam;
13613        };
13614
13615        return status;
13616}
13617
13618static int FAST_FUNC
13619exitcmd(int argc UNUSED_PARAM, char **argv)
13620{
13621        if (stoppedjobs())
13622                return 0;
13623
13624        if (argv[1])
13625                savestatus = number(argv[1]);
13626
13627        raise_exception(EXEXIT);
13628        /* NOTREACHED */
13629}
13630
13631/*
13632 * Read a file containing shell functions.
13633 */
13634static void
13635readcmdfile(char *name)
13636{
13637        setinputfile(name, INPUT_PUSH_FILE);
13638        cmdloop(0);
13639        popfile();
13640}
13641
13642
13643/* ============ find_command inplementation */
13644
13645/*
13646 * Resolve a command name.  If you change this routine, you may have to
13647 * change the shellexec routine as well.
13648 */
13649static void
13650find_command(char *name, struct cmdentry *entry, int act, const char *path)
13651{
13652        struct tblentry *cmdp;
13653        int idx;
13654        int prev;
13655        char *fullname;
13656        struct stat statb;
13657        int e;
13658        int updatetbl;
13659        struct builtincmd *bcmd;
13660        int len;
13661
13662        /* If name contains a slash, don't use PATH or hash table */
13663        if (strchr(name, '/') != NULL) {
13664                entry->u.index = -1;
13665                if (act & DO_ABS) {
13666                        while (stat(name, &statb) < 0) {
13667#ifdef SYSV
13668                                if (errno == EINTR)
13669                                        continue;
13670#endif
13671                                entry->cmdtype = CMDUNKNOWN;
13672                                return;
13673                        }
13674                }
13675                entry->cmdtype = CMDNORMAL;
13676                return;
13677        }
13678
13679/* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
13680
13681        updatetbl = (path == pathval());
13682        if (!updatetbl)
13683                act |= DO_ALTPATH;
13684
13685        /* If name is in the table, check answer will be ok */
13686        cmdp = cmdlookup(name, 0);
13687        if (cmdp != NULL) {
13688                int bit;
13689
13690                switch (cmdp->cmdtype) {
13691                default:
13692#if DEBUG
13693                        abort();
13694#endif
13695                case CMDNORMAL:
13696                        bit = DO_ALTPATH | DO_REGBLTIN;
13697                        break;
13698                case CMDFUNCTION:
13699                        bit = DO_NOFUNC;
13700                        break;
13701                case CMDBUILTIN:
13702                        bit = IS_BUILTIN_REGULAR(cmdp->param.cmd) ? 0 : DO_REGBLTIN;
13703                        break;
13704                }
13705                if (act & bit) {
13706                        if (act & bit & DO_REGBLTIN)
13707                                goto fail;
13708
13709                        updatetbl = 0;
13710                        cmdp = NULL;
13711                } else if (cmdp->rehash == 0)
13712                        /* if not invalidated by cd, we're done */
13713                        goto success;
13714        }
13715
13716        /* If %builtin not in path, check for builtin next */
13717        bcmd = find_builtin(name);
13718        if (bcmd) {
13719                if (IS_BUILTIN_REGULAR(bcmd))
13720                        goto builtin_success;
13721                if (act & DO_ALTPATH)
13722                        goto builtin_success;
13723                if (builtinloc <= 0)
13724                        goto builtin_success;
13725        }
13726
13727        if (act & DO_REGBLTIN)
13728                goto fail;
13729
13730#if ENABLE_FEATURE_SH_STANDALONE
13731        {
13732                int applet_no = find_applet_by_name(name);
13733                if (applet_no >= 0) {
13734                        entry->cmdtype = CMDNORMAL;
13735                        entry->u.index = -2 - applet_no;
13736                        return;
13737                }
13738        }
13739#endif
13740
13741        /* We have to search path. */
13742        prev = -1;              /* where to start */
13743        if (cmdp && cmdp->rehash) {     /* doing a rehash */
13744                if (cmdp->cmdtype == CMDBUILTIN)
13745                        prev = builtinloc;
13746                else
13747                        prev = cmdp->param.index;
13748        }
13749
13750        e = ENOENT;
13751        idx = -1;
13752 loop:
13753        while ((len = padvance(&path, name)) >= 0) {
13754                const char *lpathopt = pathopt;
13755
13756                fullname = stackblock();
13757                idx++;
13758                if (lpathopt) {
13759                        if (*lpathopt == 'b') {
13760                                if (bcmd)
13761                                        goto builtin_success;
13762                                continue;
13763                        } else if (!(act & DO_NOFUNC)) {
13764                                /* handled below */
13765                        } else {
13766                                /* ignore unimplemented options */
13767                                continue;
13768                        }
13769                }
13770                /* if rehash, don't redo absolute path names */
13771                if (fullname[0] == '/' && idx <= prev) {
13772                        if (idx < prev)
13773                                continue;
13774                        TRACE(("searchexec \"%s\": no change\n", name));
13775                        goto success;
13776                }
13777                while (stat(fullname, &statb) < 0) {
13778#ifdef SYSV
13779                        if (errno == EINTR)
13780                                continue;
13781#endif
13782                        if (errno != ENOENT && errno != ENOTDIR)
13783                                e = errno;
13784                        goto loop;
13785                }
13786                e = EACCES;     /* if we fail, this will be the error */
13787                if (!S_ISREG(statb.st_mode))
13788                        continue;
13789                if (lpathopt) {          /* this is a %func directory */
13790                        stalloc(len);
13791                        /* NB: stalloc will return space pointed by fullname
13792                         * (because we don't have any intervening allocations
13793                         * between stunalloc above and this stalloc) */
13794                        readcmdfile(fullname);
13795                        cmdp = cmdlookup(name, 0);
13796                        if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13797                                ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13798                        stunalloc(fullname);
13799                        goto success;
13800                }
13801                TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13802                if (!updatetbl) {
13803                        entry->cmdtype = CMDNORMAL;
13804                        entry->u.index = idx;
13805                        return;
13806                }
13807                INT_OFF;
13808                cmdp = cmdlookup(name, 1);
13809                cmdp->cmdtype = CMDNORMAL;
13810                cmdp->param.index = idx;
13811                INT_ON;
13812                goto success;
13813        }
13814
13815        /* We failed.  If there was an entry for this command, delete it */
13816        if (cmdp && updatetbl)
13817                delete_cmd_entry();
13818        if (act & DO_ERR) {
13819#if ENABLE_ASH_BASH_NOT_FOUND_HOOK
13820                struct tblentry *hookp = cmdlookup("command_not_found_handle", 0);
13821                if (hookp && hookp->cmdtype == CMDFUNCTION) {
13822                        char *argv[3];
13823                        argv[0] = (char*) "command_not_found_handle";
13824                        argv[1] = name;
13825                        argv[2] = NULL;
13826                        evalfun(hookp->param.func, 2, argv, 0);
13827                        entry->cmdtype = CMDUNKNOWN;
13828                        return;
13829                }
13830#endif
13831                ash_msg("%s: %s", name, errmsg(e, "not found"));
13832        }
13833 fail:
13834        entry->cmdtype = CMDUNKNOWN;
13835        return;
13836
13837 builtin_success:
13838        if (!updatetbl) {
13839                entry->cmdtype = CMDBUILTIN;
13840                entry->u.cmd = bcmd;
13841                return;
13842        }
13843        INT_OFF;
13844        cmdp = cmdlookup(name, 1);
13845        cmdp->cmdtype = CMDBUILTIN;
13846        cmdp->param.cmd = bcmd;
13847        INT_ON;
13848 success:
13849        cmdp->rehash = 0;
13850        entry->cmdtype = cmdp->cmdtype;
13851        entry->u = cmdp->param;
13852}
13853
13854
13855/*
13856 * The trap builtin.
13857 */
13858static int FAST_FUNC
13859trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13860{
13861        char *action;
13862        char **ap;
13863        int signo, exitcode;
13864
13865        nextopt(nullstr);
13866        ap = argptr;
13867        if (!*ap) {
13868                for (signo = 0; signo < NSIG; signo++) {
13869                        char *tr = trap_ptr[signo];
13870                        if (tr) {
13871                                /* note: bash adds "SIG", but only if invoked
13872                                 * as "bash". If called as "sh", or if set -o posix,
13873                                 * then it prints short signal names.
13874                                 * We are printing short names: */
13875                                out1fmt("trap -- %s %s\n",
13876                                                single_quote(tr),
13877                                                get_signame(signo));
13878                /* trap_ptr != trap only if we are in special-cased `trap` code.
13879                 * In this case, we will exit very soon, no need to free(). */
13880                                /* if (trap_ptr != trap && tp[0]) */
13881                                /*      free(tr); */
13882                        }
13883                }
13884                /*
13885                if (trap_ptr != trap) {
13886                        free(trap_ptr);
13887                        trap_ptr = trap;
13888                }
13889                */
13890                return 0;
13891        }
13892
13893        /* Why the second check?
13894         * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13895         * In this case, NUM is signal no, not an action.
13896         */
13897        action = NULL;
13898        if (ap[1] && !is_number(ap[0]))
13899                action = *ap++;
13900
13901        exitcode = 0;
13902        while (*ap) {
13903                signo = get_signum(*ap);
13904                if (signo < 0) {
13905                        /* Mimic bash message exactly */
13906                        ash_msg("%s: invalid signal specification", *ap);
13907                        exitcode = 1;
13908                        goto next;
13909                }
13910                INT_OFF;
13911                if (action) {
13912                        if (LONE_DASH(action))
13913                                action = NULL;
13914                        else {
13915                                if (action[0]) /* not NULL and not "" and not "-" */
13916                                        may_have_traps = 1;
13917                                action = ckstrdup(action);
13918                        }
13919                }
13920                free(trap[signo]);
13921                trap[signo] = action;
13922                if (signo != 0)
13923                        setsignal(signo);
13924                INT_ON;
13925 next:
13926                ap++;
13927        }
13928        return exitcode;
13929}
13930
13931
13932/* ============ Builtins */
13933
13934#if ENABLE_ASH_HELP
13935static int FAST_FUNC
13936helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13937{
13938        unsigned col;
13939        unsigned i;
13940
13941        out1fmt(
13942                "Built-in commands:\n"
13943                "------------------\n");
13944        for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13945                col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13946                                        builtintab[i].name + 1);
13947                if (col > 60) {
13948                        out1fmt("\n");
13949                        col = 0;
13950                }
13951        }
13952# if ENABLE_FEATURE_SH_STANDALONE
13953        {
13954                const char *a = applet_names;
13955                while (*a) {
13956                        col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13957                        if (col > 60) {
13958                                out1fmt("\n");
13959                                col = 0;
13960                        }
13961                        while (*a++ != '\0')
13962                                continue;
13963                }
13964        }
13965# endif
13966        newline_and_flush(stdout);
13967        return EXIT_SUCCESS;
13968}
13969#endif
13970
13971#if MAX_HISTORY
13972static int FAST_FUNC
13973historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13974{
13975        show_history(line_input_state);
13976        return EXIT_SUCCESS;
13977}
13978#endif
13979
13980/*
13981 * The export and readonly commands.
13982 */
13983static int FAST_FUNC
13984exportcmd(int argc UNUSED_PARAM, char **argv)
13985{
13986        struct var *vp;
13987        char *name;
13988        const char *p;
13989        char **aptr;
13990        char opt;
13991        int flag;
13992        int flag_off;
13993
13994        /* "readonly" in bash accepts, but ignores -n.
13995         * We do the same: it saves a conditional in nextopt's param.
13996         */
13997        flag_off = 0;
13998        while ((opt = nextopt("np")) != '\0') {
13999                if (opt == 'n')
14000                        flag_off = VEXPORT;
14001        }
14002        flag = VEXPORT;
14003        if (argv[0][0] == 'r') {
14004                flag = VREADONLY;
14005                flag_off = 0; /* readonly ignores -n */
14006        }
14007        flag_off = ~flag_off;
14008
14009        /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
14010        {
14011                aptr = argptr;
14012                name = *aptr;
14013                if (name) {
14014                        do {
14015                                p = strchr(name, '=');
14016                                if (p != NULL) {
14017                                        p++;
14018                                } else {
14019                                        vp = *findvar(hashvar(name), name);
14020                                        if (vp) {
14021                                                vp->flags = ((vp->flags | flag) & flag_off);
14022                                                continue;
14023                                        }
14024                                }
14025                                setvar(name, p, (flag & flag_off));
14026                        } while ((name = *++aptr) != NULL);
14027                        return 0;
14028                }
14029        }
14030
14031        /* No arguments. Show the list of exported or readonly vars.
14032         * -n is ignored.
14033         */
14034        showvars(argv[0], flag, 0);
14035        return 0;
14036}
14037
14038/*
14039 * Delete a function if it exists.
14040 */
14041static void
14042unsetfunc(const char *name)
14043{
14044        struct tblentry *cmdp;
14045
14046        cmdp = cmdlookup(name, 0);
14047        if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
14048                delete_cmd_entry();
14049}
14050
14051/*
14052 * The unset builtin command.  We unset the function before we unset the
14053 * variable to allow a function to be unset when there is a readonly variable
14054 * with the same name.
14055 */
14056static int FAST_FUNC
14057unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
14058{
14059        char **ap;
14060        int i;
14061        int flag = 0;
14062
14063        while ((i = nextopt("vf")) != 0) {
14064                flag = i;
14065        }
14066
14067        for (ap = argptr; *ap; ap++) {
14068                if (flag != 'f') {
14069                        unsetvar(*ap);
14070                        continue;
14071                }
14072                if (flag != 'v')
14073                        unsetfunc(*ap);
14074        }
14075        return 0;
14076}
14077
14078static const unsigned char timescmd_str[] ALIGN1 = {
14079        ' ',  offsetof(struct tms, tms_utime),
14080        '\n', offsetof(struct tms, tms_stime),
14081        ' ',  offsetof(struct tms, tms_cutime),
14082        '\n', offsetof(struct tms, tms_cstime),
14083        0
14084};
14085static int FAST_FUNC
14086timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
14087{
14088        unsigned clk_tck;
14089        const unsigned char *p;
14090        struct tms buf;
14091
14092        clk_tck = bb_clk_tck();
14093
14094        times(&buf);
14095        p = timescmd_str;
14096        do {
14097                unsigned sec, frac;
14098                unsigned long t;
14099                t = *(clock_t *)(((char *) &buf) + p[1]);
14100                sec = t / clk_tck;
14101                frac = t % clk_tck;
14102                out1fmt("%um%u.%03us%c",
14103                        sec / 60, sec % 60,
14104                        (frac * 1000) / clk_tck,
14105                        p[0]);
14106                p += 2;
14107        } while (*p);
14108
14109        return 0;
14110}
14111
14112#if ENABLE_FEATURE_SH_MATH
14113/*
14114 * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
14115 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
14116 *
14117 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
14118 */
14119static int FAST_FUNC
14120letcmd(int argc UNUSED_PARAM, char **argv)
14121{
14122        arith_t i;
14123
14124        argv++;
14125        if (!*argv)
14126                ash_msg_and_raise_error("expression expected");
14127        do {
14128                i = ash_arith(*argv);
14129        } while (*++argv);
14130
14131        return !i;
14132}
14133#endif
14134
14135/*
14136 * The read builtin. Options:
14137 *      -r              Do not interpret '\' specially
14138 *      -s              Turn off echo (tty only)
14139 *      -n NCHARS       Read NCHARS max
14140 *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
14141 *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
14142 *      -u FD           Read from given FD instead of fd 0
14143 *      -d DELIM        End on DELIM char, not newline
14144 * This uses unbuffered input, which may be avoidable in some cases.
14145 * TODO: bash also has:
14146 *      -a ARRAY        Read into array[0],[1],etc
14147 *      -e              Use line editing (tty only)
14148 */
14149static int FAST_FUNC
14150readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
14151{
14152        struct builtin_read_params params;
14153        const char *r;
14154        int i;
14155
14156        memset(&params, 0, sizeof(params));
14157
14158        while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
14159                switch (i) {
14160                case 'p':
14161                        params.opt_p = optionarg;
14162                        break;
14163                case 'n':
14164                        params.opt_n = optionarg;
14165                        break;
14166                case 's':
14167                        params.read_flags |= BUILTIN_READ_SILENT;
14168                        break;
14169                case 't':
14170                        params.opt_t = optionarg;
14171                        break;
14172                case 'r':
14173                        params.read_flags |= BUILTIN_READ_RAW;
14174                        break;
14175                case 'u':
14176                        params.opt_u = optionarg;
14177                        break;
14178#if BASH_READ_D
14179                case 'd':
14180                        params.opt_d = optionarg;
14181                        break;
14182#endif
14183                default:
14184                        break;
14185                }
14186        }
14187
14188        if (!ENABLE_ASH_BASH_COMPAT && !argptr) {
14189                bb_simple_error_msg("read: need variable name");
14190                return 1;
14191        }
14192        params.argv = argptr;
14193        params.setvar = setvar0;
14194        params.ifs = bltinlookup("IFS"); /* can be NULL */
14195
14196        /* "read -s" needs to save/restore termios, can't allow ^C
14197         * to jump out of it.
14198         */
14199 again:
14200        INT_OFF;
14201        r = shell_builtin_read(&params);
14202        INT_ON;
14203
14204        if ((uintptr_t)r == 1 && errno == EINTR) {
14205                /* To get SIGCHLD: sleep 1 & read x; echo $x
14206                 * Correct behavior is to not exit "read"
14207                 */
14208                if (pending_sig == 0)
14209                        goto again;
14210        }
14211
14212        if ((uintptr_t)r > 1)
14213                ash_msg_and_raise_error(r);
14214
14215        return (uintptr_t)r;
14216}
14217
14218static int FAST_FUNC
14219umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
14220{
14221        static const char permuser[3] ALIGN1 = "ogu";
14222
14223        mode_t mask;
14224        int symbolic_mode = 0;
14225
14226        while (nextopt("S") != '\0') {
14227                symbolic_mode = 1;
14228        }
14229
14230        INT_OFF;
14231        mask = umask(0);
14232        umask(mask);
14233        INT_ON;
14234
14235        if (*argptr == NULL) {
14236                if (symbolic_mode) {
14237                        char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
14238                        char *p = buf;
14239                        int i;
14240
14241                        i = 2;
14242                        for (;;) {
14243                                *p++ = ',';
14244                                *p++ = permuser[i];
14245                                *p++ = '=';
14246                                /* mask is 0..0uuugggooo. i=2 selects uuu bits */
14247                                if (!(mask & 0400)) *p++ = 'r';
14248                                if (!(mask & 0200)) *p++ = 'w';
14249                                if (!(mask & 0100)) *p++ = 'x';
14250                                mask <<= 3;
14251                                if (--i < 0)
14252                                        break;
14253                        }
14254                        *p = '\0';
14255                        puts(buf + 1);
14256                } else {
14257                        out1fmt("%04o\n", mask);
14258                }
14259        } else {
14260                char *modestr = *argptr;
14261                /* numeric umasks are taken as-is */
14262                /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
14263                if (!isdigit(modestr[0]))
14264                        mask ^= 0777;
14265                mask = bb_parse_mode(modestr, mask);
14266                if ((unsigned)mask > 0777) {
14267                        ash_msg_and_raise_error("illegal mode: %s", modestr);
14268                }
14269                if (!isdigit(modestr[0]))
14270                        mask ^= 0777;
14271                umask(mask);
14272        }
14273        return 0;
14274}
14275
14276static int FAST_FUNC
14277ulimitcmd(int argc UNUSED_PARAM, char **argv)
14278{
14279        return shell_builtin_ulimit(argv);
14280}
14281
14282/* ============ main() and helpers */
14283
14284/*
14285 * This routine is called when an error or an interrupt occurs in an
14286 * interactive shell and control is returned to the main command loop
14287 * but prior to exitshell.
14288 */
14289static void
14290exitreset(void)
14291{
14292        /* from eval.c: */
14293        if (savestatus >= 0) {
14294                if (exception_type == EXEXIT || evalskip == SKIPFUNCDEF)
14295                        exitstatus = savestatus;
14296                savestatus = -1;
14297        }
14298        evalskip = 0;
14299        loopnest = 0;
14300
14301        /* from expand.c: */
14302        ifsfree();
14303
14304        /* from redir.c: */
14305        unwindredir(NULL);
14306}
14307
14308/*
14309 * This routine is called when an error or an interrupt occurs in an
14310 * interactive shell and control is returned to the main command loop.
14311 * (In dash, this function is auto-generated by build machinery).
14312 */
14313static void
14314reset(void)
14315{
14316        /* from input.c: */
14317        g_parsefile->left_in_buffer = 0;
14318        g_parsefile->left_in_line = 0;      /* clear input buffer */
14319        g_parsefile->unget = 0;
14320        popallfiles();
14321
14322        /* from var.c: */
14323        unwindlocalvars(NULL);
14324}
14325
14326/*
14327 * Called to exit the shell.
14328 */
14329static void
14330exitshell(void)
14331{
14332        struct jmploc loc;
14333        char *p;
14334
14335#if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
14336        save_history(line_input_state); /* may be NULL */
14337#endif
14338        savestatus = exitstatus;
14339        TRACE(("pid %d, exitshell(%d)\n", getpid(), savestatus));
14340        if (setjmp(loc.loc))
14341                goto out;
14342        exception_handler = &loc;
14343        p = trap[0];
14344        if (p) {
14345                trap[0] = NULL;
14346                evalskip = 0;
14347                evalstring(p, 0);
14348                evalskip = SKIPFUNCDEF;
14349                /*free(p); - we'll exit soon */
14350        }
14351 out:
14352        exitreset();
14353        /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
14354         * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
14355         */
14356        setjobctl(0);
14357        flush_stdout_stderr();
14358        _exit(exitstatus);
14359        /* NOTREACHED */
14360}
14361
14362/* Don't inline: conserve stack of caller from having our locals too */
14363static NOINLINE void
14364init(void)
14365{
14366        /* we will never free this */
14367        basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
14368        basepf.linno = 1;
14369
14370        sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
14371        setsignal(SIGCHLD);
14372
14373        {
14374                char **envp;
14375                const char *p;
14376
14377                initvar();
14378                for (envp = environ; envp && *envp; envp++) {
14379/* Used to have
14380 *                      p = endofname(*envp);
14381 *                      if (p != *envp && *p == '=') {
14382 * here to weed out badly-named variables, but this breaks
14383 * scenarios where people do want them passed to children:
14384 * import os
14385 * os.environ["test-test"]="test"
14386 * if os.fork() == 0:
14387 *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
14388 * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])  # breaks this
14389 */
14390                        if (strchr(*envp, '=')) {
14391                                setvareq(*envp, VEXPORT|VTEXTFIXED);
14392                        }
14393                }
14394
14395                setvareq((char*)defifsvar, VTEXTFIXED);
14396                setvareq((char*)defoptindvar, VTEXTFIXED);
14397
14398                setvar0("PPID", utoa(getppid()));
14399#if BASH_SHLVL_VAR
14400                p = lookupvar("SHLVL");
14401                setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
14402#endif
14403#if BASH_HOSTNAME_VAR
14404                if (!lookupvar("HOSTNAME")) {
14405                        struct utsname uts;
14406                        uname(&uts);
14407                        setvar0("HOSTNAME", uts.nodename);
14408                }
14409#endif
14410                p = lookupvar("PWD");
14411                if (p) {
14412                        struct stat st1, st2;
14413                        if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
14414                         || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
14415                        ) {
14416                                p = NULL;
14417                        }
14418                }
14419                setpwd(p, 0);
14420        }
14421}
14422
14423
14424//usage:#define ash_trivial_usage
14425//usage:        "[-il] [-|+Cabefmnuvx] [-|+o OPT]... [-c 'SCRIPT' [ARG0 ARGS] | FILE [ARGS] | -s [ARGS]]"
14426////////        comes from ^^^^^^^^^^optletters
14427//usage:#define ash_full_usage "\n\n"
14428//usage:        "Unix shell interpreter"
14429
14430/*
14431 * Process the shell command line arguments.
14432 */
14433static int
14434procargs(char **argv)
14435{
14436        int i;
14437        const char *xminusc;
14438        char **xargv;
14439        int login_sh;
14440
14441        xargv = argv;
14442        login_sh = xargv[0] && xargv[0][0] == '-';
14443#if NUM_SCRIPTS > 0
14444        if (minusc)
14445                goto setarg0;
14446#endif
14447        arg0 = xargv[0];
14448        /* if (xargv[0]) - mmm, this is always true! */
14449                xargv++;
14450        argptr = xargv;
14451        for (i = 0; i < NOPTS; i++)
14452                optlist[i] = 2;
14453        if (options(&login_sh)) {
14454                /* it already printed err message */
14455                raise_exception(EXERROR);
14456        }
14457        xargv = argptr;
14458        xminusc = minusc;
14459        if (*xargv == NULL) {
14460                if (xminusc)
14461                        ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
14462                sflag = 1;
14463        }
14464        if (iflag == 2 /* no explicit -i given */
14465         && sflag == 1 /* -s given (or implied) */
14466         && !minusc /* bash compat: ash -sc 'echo $-' is not interactive (dash is) */
14467         && isatty(0) && isatty(1) /* we are on tty */
14468        ) {
14469                iflag = 1;
14470        }
14471        if (mflag == 2)
14472                mflag = iflag;
14473        /* Unset options which weren't explicitly set or unset */
14474        for (i = 0; i < NOPTS; i++)
14475                optlist[i] &= 1; /* same effect as "if (optlist[i] == 2) optlist[i] = 0;" */
14476#if DEBUG == 2
14477        debug = 1;
14478#endif
14479        /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
14480        if (xminusc) {
14481                minusc = *xargv++;
14482                if (*xargv)
14483                        goto setarg0;
14484        } else if (!sflag) {
14485                setinputfile(*xargv, 0);
14486 setarg0:
14487                arg0 = *xargv++;
14488                commandname = arg0;
14489        }
14490
14491        shellparam.p = xargv;
14492#if ENABLE_ASH_GETOPTS
14493        shellparam.optind = 1;
14494        shellparam.optoff = -1;
14495#endif
14496        /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
14497        while (*xargv) {
14498                shellparam.nparam++;
14499                xargv++;
14500        }
14501
14502        /* Interactive bash re-enables SIGHUP which is SIG_IGNed on entry.
14503         * Try:
14504         * trap '' hup; bash; echo RET  # type "kill -hup $$", see SIGHUP having effect
14505         * trap '' hup; bash -c 'kill -hup $$; echo ALIVE'  # here SIGHUP is SIG_IGNed
14506         * NB: must do it before setting up signals (in optschanged())
14507         * and reading .profile etc (after we return from here):
14508         */
14509        if (iflag)
14510                signal(SIGHUP, SIG_DFL);
14511
14512        optschanged();
14513
14514        return login_sh;
14515}
14516
14517/*
14518 * Read /etc/profile, ~/.profile, $ENV.
14519 */
14520static void
14521read_profile(const char *name)
14522{
14523        name = expandstr(name, DQSYNTAX);
14524        if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
14525                return;
14526        cmdloop(0);
14527        popfile();
14528}
14529
14530#if PROFILE
14531static short profile_buf[16384];
14532extern int etext();
14533#endif
14534
14535/*
14536 * Main routine.  We initialize things, parse the arguments, execute
14537 * profiles if we're a login shell, and then call cmdloop to execute
14538 * commands.  The setjmp call sets up the location to jump to when an
14539 * exception occurs.  When an exception occurs the variable "state"
14540 * is used to figure out how far we had gotten.
14541 */
14542int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
14543#if NUM_SCRIPTS > 0
14544int ash_main(int argc, char **argv)
14545#else
14546int ash_main(int argc UNUSED_PARAM, char **argv)
14547#endif
14548/* note: 'argc' is used only if embedded scripts are enabled */
14549{
14550        volatile smallint state;
14551        struct jmploc jmploc;
14552        struct stackmark smark;
14553        int login_sh;
14554
14555        /* Initialize global data */
14556        INIT_G_misc();
14557        INIT_G_memstack();
14558        INIT_G_var();
14559#if ENABLE_ASH_ALIAS
14560        INIT_G_alias();
14561#endif
14562        INIT_G_cmdtable();
14563
14564#if PROFILE
14565        monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
14566#endif
14567
14568        state = 0;
14569        if (setjmp(jmploc.loc)) {
14570                smallint e;
14571                smallint s;
14572
14573                exitreset();
14574
14575                e = exception_type;
14576                s = state;
14577                if (e == EXEND || e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
14578                        exitshell();
14579                }
14580
14581                reset();
14582
14583                if (e == EXINT) {
14584                        newline_and_flush(stderr);
14585                }
14586
14587                popstackmark(&smark);
14588                FORCE_INT_ON; /* enable interrupts */
14589                if (s == 1)
14590                        goto state1;
14591                if (s == 2)
14592                        goto state2;
14593                if (s == 3)
14594                        goto state3;
14595                goto state4;
14596        }
14597        exception_handler = &jmploc;
14598        rootpid = getpid();
14599
14600        init();
14601        setstackmark(&smark);
14602
14603#if NUM_SCRIPTS > 0
14604        if (argc < 0)
14605                /* Non-NULL minusc tells procargs that an embedded script is being run */
14606                minusc = get_script_content(-argc - 1);
14607#endif
14608        login_sh = procargs(argv);
14609#if DEBUG
14610        TRACE(("Shell args: "));
14611        trace_puts_args(argv);
14612#endif
14613
14614        if (login_sh) {
14615                const char *hp;
14616
14617                state = 1;
14618                read_profile("/etc/profile");
14619 state1:
14620                state = 2;
14621                hp = lookupvar("HOME");
14622                if (hp)
14623                        read_profile("$HOME/.profile");
14624        }
14625 state2:
14626        state = 3;
14627        if (
14628#ifndef linux
14629         getuid() == geteuid() && getgid() == getegid() &&
14630#endif
14631         iflag
14632        ) {
14633                const char *shinit = lookupvar("ENV");
14634                if (shinit != NULL && *shinit != '\0')
14635                        read_profile(shinit);
14636        }
14637        popstackmark(&smark);
14638 state3:
14639        state = 4;
14640        if (minusc) {
14641                /* evalstring pushes parsefile stack.
14642                 * Ensure we don't falsely claim that 0 (stdin)
14643                 * is one of stacked source fds.
14644                 * Testcase: ash -c 'exec 1>&0' must not complain. */
14645
14646                // if (!sflag) g_parsefile->pf_fd = -1;
14647                // ^^ not necessary since now we special-case fd 0
14648                // in save_fd_on_redirect()
14649
14650                // dash: evalstring(minusc, sflag ? 0 : EV_EXIT);
14651                // The above makes
14652                //  ash -sc 'echo $-'
14653                // continue reading input from stdin after running 'echo'.
14654                // bash does not do this: it prints "hBcs" and exits.
14655                evalstring(minusc, EV_EXIT);
14656        }
14657
14658        if (sflag || minusc == NULL) {
14659#if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
14660                if (line_input_state) {
14661                        const char *hp = lookupvar("HISTFILE");
14662                        if (!hp) {
14663                                hp = lookupvar("HOME");
14664                                if (hp) {
14665                                        INT_OFF;
14666                                        hp = concat_path_file(hp, ".ash_history");
14667                                        setvar0("HISTFILE", hp);
14668                                        free((char*)hp);
14669                                        INT_ON;
14670                                        hp = lookupvar("HISTFILE");
14671                                }
14672                        }
14673                        if (hp)
14674                                line_input_state->hist_file = xstrdup(hp);
14675# if ENABLE_FEATURE_SH_HISTFILESIZE
14676                        hp = lookupvar("HISTFILESIZE");
14677                        line_input_state->max_history = size_from_HISTFILESIZE(hp);
14678# endif
14679                }
14680#endif
14681 state4: /* XXX ??? - why isn't this before the "if" statement */
14682                cmdloop(1);
14683        }
14684#if PROFILE
14685        monitor(0);
14686#endif
14687#ifdef GPROF
14688        {
14689                extern void _mcleanup(void);
14690                _mcleanup();
14691        }
14692#endif
14693        TRACE(("End of main reached\n"));
14694        exitshell();
14695        /* NOTREACHED */
14696}
14697
14698
14699/*-
14700 * Copyright (c) 1989, 1991, 1993, 1994
14701 *      The Regents of the University of California.  All rights reserved.
14702 *
14703 * This code is derived from software contributed to Berkeley by
14704 * Kenneth Almquist.
14705 *
14706 * Redistribution and use in source and binary forms, with or without
14707 * modification, are permitted provided that the following conditions
14708 * are met:
14709 * 1. Redistributions of source code must retain the above copyright
14710 *    notice, this list of conditions and the following disclaimer.
14711 * 2. Redistributions in binary form must reproduce the above copyright
14712 *    notice, this list of conditions and the following disclaimer in the
14713 *    documentation and/or other materials provided with the distribution.
14714 * 3. Neither the name of the University nor the names of its contributors
14715 *    may be used to endorse or promote products derived from this software
14716 *    without specific prior written permission.
14717 *
14718 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
14719 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14720 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14721 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
14722 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14723 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14724 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14725 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14726 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14727 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14728 * SUCH DAMAGE.
14729 */
14730