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#ifndef unlikely
 299# define unlikely(cond) (cond)
 300#endif
 301
 302#if !BB_MMU
 303# error "Do not even bother, ash will not run on NOMMU machine"
 304#endif
 305
 306/* ============ Hash table sizes. Configurable. */
 307
 308#define VTABSIZE 39
 309#define ATABSIZE 39
 310#define CMDTABLESIZE 31         /* should be prime */
 311
 312
 313/* ============ Shell options */
 314
 315/* If you add/change options hare, update --help text too */
 316static const char *const optletters_optnames[] = {
 317        "e"   "errexit",
 318        "f"   "noglob",
 319/* bash has '-o ignoreeof', but no short synonym -I for it */
 320/* (in bash, set -I disables invisible variables (what's that?)) */
 321        "I"   "ignoreeof",
 322/* The below allowed this invocation:
 323 * ash -c 'set -i; echo $-; sleep 5; echo $-'
 324 * to be ^C-ed and get to interactive ash prompt.
 325 * bash does not support such "set -i".
 326 * In our code, this is denoted by empty long name:
 327 */
 328        "i"   "",
 329/* (removing "i" altogether would remove it from "$-", not good) */
 330        "m"   "monitor",
 331        "n"   "noexec",
 332/* Ditto: bash has no "set -s", "set -c" */
 333        "s"   "",
 334        "c"   "",
 335        "x"   "xtrace",
 336        "v"   "verbose",
 337        "C"   "noclobber",
 338        "a"   "allexport",
 339        "b"   "notify",
 340        "u"   "nounset",
 341        "E"   "errtrace",
 342        "\0"  "vi"
 343#if BASH_PIPEFAIL
 344        ,"\0"  "pipefail"
 345#endif
 346#if DEBUG
 347        ,"\0"  "nolog"
 348        ,"\0"  "debug"
 349#endif
 350};
 351//bash 4.4.23 also has these opts (with these defaults):
 352//braceexpand           on
 353//emacs                 on
 354//errtrace              off
 355//functrace             off
 356//hashall               on
 357//histexpand            off
 358//history               on
 359//interactive-comments  on
 360//keyword               off
 361//onecmd                off
 362//physical              off
 363//posix                 off
 364//privileged            off
 365
 366#define optletters(n)  optletters_optnames[n][0]
 367#define optnames(n)   (optletters_optnames[n] + 1)
 368
 369enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
 370
 371
 372/* ============ Misc data */
 373
 374#define msg_illnum "Illegal number: %s"
 375
 376/*
 377 * We enclose jmp_buf in a structure so that we can declare pointers to
 378 * jump locations.  The global variable handler contains the location to
 379 * jump to when an exception occurs, and the global variable exception_type
 380 * contains a code identifying the exception.  To implement nested
 381 * exception handlers, the user should save the value of handler on entry
 382 * to an inner scope, set handler to point to a jmploc structure for the
 383 * inner scope, and restore handler on exit from the scope.
 384 */
 385struct jmploc {
 386        jmp_buf loc;
 387};
 388
 389struct globals_misc {
 390        uint8_t exitstatus;     /* exit status of last command */
 391        uint8_t back_exitstatus;/* exit status of backquoted command */
 392        smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
 393        smallint inps4;         /* Prevent PS4 nesting. */
 394        int savestatus;         /* exit status of last command outside traps */
 395        int rootpid;            /* pid of main shell */
 396        /* shell level: 0 for the main shell, 1 for its children, and so on */
 397        int shlvl;
 398#define rootshell (!shlvl)
 399        int errlinno;
 400
 401        char *minusc;  /* argument to -c option */
 402
 403        char *curdir; // = nullstr;     /* current working directory */
 404        char *physdir; // = nullstr;    /* physical working directory */
 405
 406        char *arg0; /* value of $0 */
 407
 408        struct jmploc *exception_handler;
 409
 410        volatile int suppress_int; /* counter */
 411        volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
 412        volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
 413        volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
 414        smallint exception_type; /* kind of exception: */
 415#define EXINT 0         /* SIGINT received */
 416#define EXERROR 1       /* a generic error */
 417#define EXEND 3         /* exit the shell */
 418#define EXEXIT 4        /* exit the shell via exitcmd */
 419
 420        char nullstr[1];        /* zero length string */
 421
 422        char optlist[NOPTS];
 423#define eflag optlist[0]
 424#define fflag optlist[1]
 425#define Iflag optlist[2]
 426#define iflag optlist[3]
 427#define mflag optlist[4]
 428#define nflag optlist[5]
 429#define sflag optlist[6]
 430#define cflag optlist[7]
 431#define xflag optlist[8]
 432#define vflag optlist[9]
 433#define Cflag optlist[10]
 434#define aflag optlist[11]
 435#define bflag optlist[12]
 436#define uflag optlist[13]
 437#define Eflag optlist[14]
 438#define viflag optlist[15]
 439#if BASH_PIPEFAIL
 440# define pipefail optlist[16]
 441#else
 442# define pipefail 0
 443#endif
 444#if DEBUG
 445# define nolog optlist[16 + BASH_PIPEFAIL]
 446# define debug optlist[17 + BASH_PIPEFAIL]
 447#endif
 448
 449        /* trap handler commands */
 450        /*
 451         * Sigmode records the current value of the signal handlers for the various
 452         * modes.  A value of zero means that the current handler is not known.
 453         * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
 454         */
 455        char sigmode[NSIG - 1];
 456#define S_DFL      1            /* default signal handling (SIG_DFL) */
 457#define S_CATCH    2            /* signal is caught */
 458#define S_IGN      3            /* signal is ignored (SIG_IGN) */
 459#define S_HARD_IGN 4            /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
 460
 461        /* indicates specified signal received */
 462        uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
 463        uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
 464        char *trap[NSIG + 1];
 465/* trap[0] is EXIT trap, trap[NTRAP_ERR] is ERR trap, other trap[i] are signal traps */
 466#define NTRAP_ERR  NSIG
 467#define NTRAP_LAST NSIG
 468
 469        char **trap_ptr;        /* used only by "trap hack" */
 470
 471        /* Rarely referenced stuff */
 472#if ENABLE_ASH_RANDOM_SUPPORT
 473        random_t random_gen;
 474#endif
 475        pid_t backgndpid;        /* pid of last background process */
 476};
 477extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc;
 478#define G_misc (*ash_ptr_to_globals_misc)
 479#define exitstatus        (G_misc.exitstatus )
 480#define back_exitstatus   (G_misc.back_exitstatus )
 481#define job_warning       (G_misc.job_warning)
 482#define inps4       (G_misc.inps4      )
 483#define savestatus  (G_misc.savestatus )
 484#define rootpid     (G_misc.rootpid    )
 485#define shlvl       (G_misc.shlvl      )
 486#define errlinno    (G_misc.errlinno   )
 487#define minusc      (G_misc.minusc     )
 488#define curdir      (G_misc.curdir     )
 489#define physdir     (G_misc.physdir    )
 490#define arg0        (G_misc.arg0       )
 491#define exception_handler (G_misc.exception_handler)
 492#define exception_type    (G_misc.exception_type   )
 493#define suppress_int      (G_misc.suppress_int     )
 494#define pending_int       (G_misc.pending_int      )
 495#define got_sigchld       (G_misc.got_sigchld      )
 496#define pending_sig       (G_misc.pending_sig      )
 497#define nullstr     (G_misc.nullstr    )
 498#define optlist     (G_misc.optlist    )
 499#define sigmode     (G_misc.sigmode    )
 500#define gotsig      (G_misc.gotsig     )
 501#define may_have_traps    (G_misc.may_have_traps   )
 502#define trap        (G_misc.trap       )
 503#define trap_ptr    (G_misc.trap_ptr   )
 504#define random_gen  (G_misc.random_gen )
 505#define backgndpid  (G_misc.backgndpid )
 506#define INIT_G_misc() do { \
 507        XZALLOC_CONST_PTR(&ash_ptr_to_globals_misc, sizeof(G_misc)); \
 508        savestatus = -1; \
 509        curdir = nullstr; \
 510        physdir = nullstr; \
 511        trap_ptr = trap; \
 512} while (0)
 513
 514
 515/* ============ DEBUG */
 516#if DEBUG
 517static void trace_printf(const char *fmt, ...);
 518static void trace_vprintf(const char *fmt, va_list va);
 519# define TRACE(param)    trace_printf param
 520# define TRACEV(param)   trace_vprintf param
 521# define close(fd) do { \
 522        int dfd = (fd); \
 523        if (close(dfd) < 0) \
 524                bb_error_msg("bug on %d: closing %d(0x%x)", \
 525                        __LINE__, dfd, dfd); \
 526} while (0)
 527#else
 528# define TRACE(param)
 529# define TRACEV(param)
 530#endif
 531
 532
 533/* ============ Utility functions */
 534#define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
 535#define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
 536
 537static int
 538isdigit_str9(const char *str)
 539{
 540        int maxlen = 9 + 1; /* max 9 digits: 999999999 */
 541        while (--maxlen && isdigit(*str))
 542                str++;
 543        return (*str == '\0');
 544}
 545
 546static const char *
 547var_end(const char *var)
 548{
 549        while (*var)
 550                if (*var++ == '=')
 551                        break;
 552        return var;
 553}
 554
 555
 556/* ============ Parser data */
 557
 558/*
 559 * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
 560 */
 561struct strlist {
 562        struct strlist *next;
 563        char *text;
 564};
 565
 566struct alias;
 567
 568struct strpush {
 569        struct strpush *prev;   /* preceding string on stack */
 570        char *prev_string;
 571        int prev_left_in_line;
 572#if ENABLE_ASH_ALIAS
 573        struct alias *ap;       /* if push was associated with an alias */
 574#endif
 575        char *string;           /* remember the string since it may change */
 576
 577        /* Delay freeing so we can stop nested aliases. */
 578        struct strpush *spfree;
 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        /* Delay freeing so we can stop nested aliases. */
 603        struct strpush *spfree;
 604
 605        /* Remember last two characters for pungetc. */
 606        int lastc[2];
 607
 608        /* Number of outstanding calls to pungetc. */
 609        int unget;
 610};
 611
 612static struct parsefile basepf;        /* top level input file */
 613static struct parsefile *g_parsefile = &basepf;  /* current input file */
 614static char *commandname;              /* currently executing command */
 615
 616
 617/* ============ Interrupts / exceptions */
 618
 619static void exitshell(void) NORETURN;
 620
 621/*
 622 * These macros allow the user to suspend the handling of interrupt signals
 623 * over a period of time.  This is similar to SIGHOLD or to sigblock, but
 624 * much more efficient and portable.  (But hacking the kernel is so much
 625 * more fun than worrying about efficiency and portability. :-))
 626 */
 627#if DEBUG_INTONOFF
 628# define INT_OFF do { \
 629        TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
 630        suppress_int++; \
 631        barrier(); \
 632} while (0)
 633#else
 634# define INT_OFF do { \
 635        suppress_int++; \
 636        barrier(); \
 637} while (0)
 638#endif
 639
 640/*
 641 * Called to raise an exception.  Since C doesn't include exceptions, we
 642 * just do a longjmp to the exception handler.  The type of exception is
 643 * stored in the global variable "exception_type".
 644 */
 645static void raise_exception(int) NORETURN;
 646static void
 647raise_exception(int e)
 648{
 649#if DEBUG
 650        if (exception_handler == NULL)
 651                abort();
 652#endif
 653        INT_OFF;
 654        exception_type = e;
 655        longjmp(exception_handler->loc, 1);
 656}
 657#if DEBUG
 658#define raise_exception(e) do { \
 659        TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
 660        raise_exception(e); \
 661} while (0)
 662#endif
 663
 664/*
 665 * Called when a SIGINT is received.  (If the user specifies
 666 * that SIGINT is to be trapped or ignored using the trap builtin, then
 667 * this routine is not called.)  Suppressint is nonzero when interrupts
 668 * are held using the INT_OFF macro.  (The test for iflag is just
 669 * defensive programming.)
 670 */
 671static void raise_interrupt(void) NORETURN;
 672static void
 673raise_interrupt(void)
 674{
 675        pending_int = 0;
 676        /* Signal is not automatically unmasked after it is raised,
 677         * do it ourself - unmask all signals */
 678        sigprocmask_allsigs(SIG_UNBLOCK);
 679        /* pending_sig = 0; - now done in signal_handler() */
 680
 681        if (!(rootshell && iflag)) {
 682                /* Kill ourself with SIGINT */
 683                signal(SIGINT, SIG_DFL);
 684                raise(SIGINT);
 685        }
 686        /* bash: ^C even on empty command line sets $? */
 687        exitstatus = SIGINT + 128;
 688        raise_exception(EXINT);
 689        /* NOTREACHED */
 690}
 691#if DEBUG
 692#define raise_interrupt() do { \
 693        TRACE(("raising interrupt on line %d\n", __LINE__)); \
 694        raise_interrupt(); \
 695} while (0)
 696#endif
 697
 698static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
 699int_on(void)
 700{
 701        barrier();
 702        if (--suppress_int == 0 && pending_int) {
 703                raise_interrupt();
 704        }
 705}
 706#if DEBUG_INTONOFF
 707# define INT_ON do { \
 708        TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
 709        int_on(); \
 710} while (0)
 711#else
 712# define INT_ON int_on()
 713#endif
 714static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
 715force_int_on(void)
 716{
 717        barrier();
 718        suppress_int = 0;
 719        if (pending_int)
 720                raise_interrupt();
 721}
 722#define FORCE_INT_ON force_int_on()
 723
 724#define SAVE_INT(v) ((v) = suppress_int)
 725
 726#define RESTORE_INT(v) do { \
 727        barrier(); \
 728        suppress_int = (v); \
 729        if (suppress_int == 0 && pending_int) \
 730                raise_interrupt(); \
 731} while (0)
 732
 733
 734/* ============ Stdout/stderr output */
 735
 736static void
 737outstr(const char *p, FILE *file)
 738{
 739        INT_OFF;
 740        fputs(p, file);
 741        INT_ON;
 742}
 743
 744static void
 745flush_stdout_stderr(void)
 746{
 747        INT_OFF;
 748        fflush_all();
 749        INT_ON;
 750}
 751
 752/* Was called outcslow(c,FILE*), but c was always '\n' */
 753static void
 754newline_and_flush(FILE *dest)
 755{
 756        INT_OFF;
 757        putc('\n', dest);
 758        fflush(dest);
 759        INT_ON;
 760}
 761
 762static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
 763static int
 764out1fmt(const char *fmt, ...)
 765{
 766        va_list ap;
 767        int r;
 768
 769        INT_OFF;
 770        va_start(ap, fmt);
 771        r = vprintf(fmt, ap);
 772        va_end(ap);
 773        INT_ON;
 774        return r;
 775}
 776
 777static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
 778static int
 779fmtstr(char *outbuf, size_t length, const char *fmt, ...)
 780{
 781        va_list ap;
 782        int ret;
 783
 784        INT_OFF;
 785        va_start(ap, fmt);
 786        ret = vsnprintf(outbuf, length, fmt, ap);
 787        va_end(ap);
 788        INT_ON;
 789        return ret > (int)length ? length : ret;
 790}
 791
 792static void
 793out1str(const char *p)
 794{
 795        outstr(p, stdout);
 796}
 797
 798static void
 799out2str(const char *p)
 800{
 801        outstr(p, stderr);
 802        flush_stdout_stderr();
 803}
 804
 805
 806/* ============ Parser structures */
 807
 808/* control characters in argument strings */
 809#define CTL_FIRST CTLESC
 810#define CTLESC       ((unsigned char)'\201')    /* escape next character */
 811#define CTLVAR       ((unsigned char)'\202')    /* variable defn */
 812#define CTLENDVAR    ((unsigned char)'\203')
 813#define CTLBACKQ     ((unsigned char)'\204')
 814#define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
 815#define CTLENDARI    ((unsigned char)'\207')
 816#define CTLQUOTEMARK ((unsigned char)'\210')
 817#define CTL_LAST CTLQUOTEMARK
 818#if BASH_PROCESS_SUBST
 819# define CTLTOPROC    ((unsigned char)'\211')
 820# define CTLFROMPROC  ((unsigned char)'\212')
 821# undef CTL_LAST
 822# define CTL_LAST CTLFROMPROC
 823#endif
 824
 825/* variable substitution byte (follows CTLVAR) */
 826#define VSTYPE  0x0f            /* type of variable substitution */
 827#define VSNUL   0x10            /* colon--treat the empty string as unset */
 828
 829/* values of VSTYPE field */
 830#define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
 831#define VSMINUS         0x2     /* ${var-text} */
 832#define VSPLUS          0x3     /* ${var+text} */
 833#define VSQUESTION      0x4     /* ${var?message} */
 834#define VSASSIGN        0x5     /* ${var=text} */
 835#define VSTRIMRIGHT     0x6     /* ${var%pattern} */
 836#define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
 837#define VSTRIMLEFT      0x8     /* ${var#pattern} */
 838#define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
 839#define VSLENGTH        0xa     /* ${#var} */
 840#if BASH_SUBSTR
 841#define VSSUBSTR        0xc     /* ${var:position:length} */
 842#endif
 843#if BASH_PATTERN_SUBST
 844#define VSREPLACE       0xd     /* ${var/pattern/replacement} */
 845#define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
 846#endif
 847
 848static const char dolatstr[] ALIGN1 = {
 849        CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
 850};
 851#define DOLATSTRLEN 6
 852
 853#define NCMD      0
 854#define NPIPE     1
 855#define NREDIR    2
 856#define NBACKGND  3
 857#define NSUBSHELL 4
 858#define NAND      5
 859#define NOR       6
 860#define NSEMI     7
 861#define NIF       8
 862#define NWHILE    9
 863#define NUNTIL   10
 864#define NFOR     11
 865#define NCASE    12
 866#define NCLIST   13
 867#define NDEFUN   14
 868#define NARG     15
 869#define NTO      16
 870#if BASH_REDIR_OUTPUT
 871#define NTO2     17
 872#endif
 873#define NCLOBBER 18
 874#define NFROM    19
 875#define NFROMTO  20
 876#define NAPPEND  21
 877#define NTOFD    22
 878#define NFROMFD  23
 879#define NHERE    24
 880#define NXHERE   25
 881#define NNOT     26
 882#define N_NUMBER 27
 883
 884union node;
 885
 886struct ncmd {
 887        smallint type; /* Nxxxx */
 888        int linno;
 889        union node *assign;
 890        union node *args;
 891        union node *redirect;
 892};
 893
 894struct npipe {
 895        smallint type;
 896        smallint pipe_backgnd;
 897        struct nodelist *cmdlist;
 898};
 899
 900struct nredir {
 901        smallint type;
 902        int linno;
 903        union node *n;
 904        union node *redirect;
 905};
 906
 907struct nbinary {
 908        smallint type;
 909        union node *ch1;
 910        union node *ch2;
 911};
 912
 913struct nif {
 914        smallint type;
 915        union node *test;
 916        union node *ifpart;
 917        union node *elsepart;
 918};
 919
 920struct nfor {
 921        smallint type;
 922        int linno;
 923        union node *args;
 924        union node *body;
 925        char *var;
 926};
 927
 928struct ncase {
 929        smallint type;
 930        int linno;
 931        union node *expr;
 932        union node *cases;
 933};
 934
 935struct nclist {
 936        smallint type;
 937        union node *next;
 938        union node *pattern;
 939        union node *body;
 940};
 941
 942struct ndefun {
 943        smallint type;
 944        int linno;
 945        char *text;
 946        union node *body;
 947};
 948
 949struct narg {
 950        smallint type;
 951        union node *next;
 952        char *text;
 953        struct nodelist *backquote;
 954};
 955
 956/* nfile and ndup layout must match!
 957 * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
 958 * that it is actually NTO2 (>&file), and change its type.
 959 */
 960struct nfile {
 961        smallint type;
 962        union node *next;
 963        int fd;
 964        int _unused_dupfd;
 965        union node *fname;
 966        char *expfname;
 967};
 968
 969struct ndup {
 970        smallint type;
 971        union node *next;
 972        int fd;
 973        int dupfd;
 974        union node *vname;
 975        char *_unused_expfname;
 976};
 977
 978struct nhere {
 979        smallint type;
 980        union node *next;
 981        int fd;
 982        union node *doc;
 983};
 984
 985struct nnot {
 986        smallint type;
 987        union node *com;
 988};
 989
 990union node {
 991        smallint type;
 992        struct ncmd ncmd;
 993        struct npipe npipe;
 994        struct nredir nredir;
 995        struct nbinary nbinary;
 996        struct nif nif;
 997        struct nfor nfor;
 998        struct ncase ncase;
 999        struct nclist nclist;
1000        struct ndefun ndefun;
1001        struct narg narg;
1002        struct nfile nfile;
1003        struct ndup ndup;
1004        struct nhere nhere;
1005        struct nnot nnot;
1006};
1007
1008/*
1009 * NODE_EOF is returned by parsecmd when it encounters an end of file.
1010 * It must be distinct from NULL.
1011 */
1012#define NODE_EOF ((union node *) -1L)
1013
1014struct nodelist {
1015        struct nodelist *next;
1016        union node *n;
1017};
1018
1019struct funcnode {
1020        int count;
1021        union node n;
1022};
1023
1024/*
1025 * Free a parse tree.
1026 */
1027static void
1028freefunc(struct funcnode *f)
1029{
1030        if (f && --f->count < 0)
1031                free(f);
1032}
1033
1034
1035/* ============ Debugging output */
1036
1037#if DEBUG
1038
1039static FILE *tracefile;
1040
1041static void
1042trace_printf(const char *fmt, ...)
1043{
1044        va_list va;
1045
1046        if (debug != 1)
1047                return;
1048        if (DEBUG_TIME)
1049                fprintf(tracefile, "%u ", (int) time(NULL));
1050        if (DEBUG_PID)
1051                fprintf(tracefile, "[%u] ", (int) getpid());
1052        if (DEBUG_SIG)
1053                fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
1054        va_start(va, fmt);
1055        vfprintf(tracefile, fmt, va);
1056        va_end(va);
1057}
1058
1059static void
1060trace_vprintf(const char *fmt, va_list va)
1061{
1062        if (debug != 1)
1063                return;
1064        vfprintf(tracefile, fmt, va);
1065        fprintf(tracefile, "\n");
1066}
1067
1068static void
1069trace_puts(const char *s)
1070{
1071        if (debug != 1)
1072                return;
1073        fputs(s, tracefile);
1074}
1075
1076static void
1077trace_puts_quoted(char *s)
1078{
1079        char *p;
1080        char c;
1081
1082        if (debug != 1)
1083                return;
1084        putc('"', tracefile);
1085        for (p = s; *p; p++) {
1086                switch ((unsigned char)*p) {
1087                case '\n': c = 'n'; goto backslash;
1088                case '\t': c = 't'; goto backslash;
1089                case '\r': c = 'r'; goto backslash;
1090                case '\"': c = '\"'; goto backslash;
1091                case '\\': c = '\\'; goto backslash;
1092                case CTLESC: c = 'e'; goto backslash;
1093                case CTLVAR: c = 'v'; goto backslash;
1094                case CTLBACKQ: c = 'q'; goto backslash;
1095#if BASH_PROCESS_SUBST
1096                case CTLTOPROC: c = 'p'; goto backslash;
1097                case CTLFROMPROC: c = 'P'; goto backslash;
1098#endif
1099 backslash:
1100                        putc('\\', tracefile);
1101                        putc(c, tracefile);
1102                        break;
1103                default:
1104                        if (*p >= ' ' && *p <= '~')
1105                                putc(*p, tracefile);
1106                        else {
1107                                putc('\\', tracefile);
1108                                putc((*p >> 6) & 03, tracefile);
1109                                putc((*p >> 3) & 07, tracefile);
1110                                putc(*p & 07, tracefile);
1111                        }
1112                        break;
1113                }
1114        }
1115        putc('"', tracefile);
1116}
1117
1118static void
1119trace_puts_args(char **ap)
1120{
1121        if (debug != 1)
1122                return;
1123        if (!*ap)
1124                return;
1125        while (1) {
1126                trace_puts_quoted(*ap);
1127                if (!*++ap) {
1128                        putc('\n', tracefile);
1129                        break;
1130                }
1131                putc(' ', tracefile);
1132        }
1133}
1134
1135static void
1136opentrace(void)
1137{
1138        char s[100];
1139#ifdef O_APPEND
1140        int flags;
1141#endif
1142
1143        if (debug != 1) {
1144                if (tracefile)
1145                        fflush(tracefile);
1146                /* leave open because libedit might be using it */
1147                return;
1148        }
1149        strcpy(s, "./trace");
1150        if (tracefile) {
1151                if (!freopen(s, "a", tracefile)) {
1152                        fprintf(stderr, "Can't re-open %s\n", s);
1153                        debug = 0;
1154                        return;
1155                }
1156        } else {
1157                tracefile = fopen(s, "a");
1158                if (tracefile == NULL) {
1159                        fprintf(stderr, "Can't open %s\n", s);
1160                        debug = 0;
1161                        return;
1162                }
1163        }
1164#ifdef O_APPEND
1165        flags = fcntl(fileno(tracefile), F_GETFL);
1166        if (flags >= 0)
1167                fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
1168#endif
1169        setlinebuf(tracefile);
1170        fputs("\nTracing started.\n", tracefile);
1171}
1172
1173static void
1174indent(int amount, char *pfx, FILE *fp)
1175{
1176        int i;
1177
1178        for (i = 0; i < amount; i++) {
1179                if (pfx && i == amount - 1)
1180                        fputs(pfx, fp);
1181                putc('\t', fp);
1182        }
1183}
1184
1185/* little circular references here... */
1186static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1187
1188static void
1189sharg(union node *arg, FILE *fp)
1190{
1191        char *p;
1192        struct nodelist *bqlist;
1193        unsigned char subtype;
1194
1195        if (arg->type != NARG) {
1196                out1fmt("<node type %d>\n", arg->type);
1197                abort();
1198        }
1199        bqlist = arg->narg.backquote;
1200        for (p = arg->narg.text; *p; p++) {
1201                switch ((unsigned char)*p) {
1202                case CTLESC:
1203                        p++;
1204                        putc(*p, fp);
1205                        break;
1206                case CTLVAR:
1207                        putc('$', fp);
1208                        putc('{', fp);
1209                        subtype = *++p;
1210                        if (subtype == VSLENGTH)
1211                                putc('#', fp);
1212
1213                        while (*p != '=') {
1214                                putc(*p, fp);
1215                                p++;
1216                        }
1217
1218                        if (subtype & VSNUL)
1219                                putc(':', fp);
1220
1221                        switch (subtype & VSTYPE) {
1222                        case VSNORMAL:
1223                                putc('}', fp);
1224                                break;
1225                        case VSMINUS:
1226                                putc('-', fp);
1227                                break;
1228                        case VSPLUS:
1229                                putc('+', fp);
1230                                break;
1231                        case VSQUESTION:
1232                                putc('?', fp);
1233                                break;
1234                        case VSASSIGN:
1235                                putc('=', fp);
1236                                break;
1237                        case VSTRIMLEFT:
1238                                putc('#', fp);
1239                                break;
1240                        case VSTRIMLEFTMAX:
1241                                putc('#', fp);
1242                                putc('#', fp);
1243                                break;
1244                        case VSTRIMRIGHT:
1245                                putc('%', fp);
1246                                break;
1247                        case VSTRIMRIGHTMAX:
1248                                putc('%', fp);
1249                                putc('%', fp);
1250                                break;
1251                        case VSLENGTH:
1252                                break;
1253                        default:
1254                                out1fmt("<subtype %d>", subtype);
1255                        }
1256                        break;
1257                case CTLENDVAR:
1258                        putc('}', fp);
1259                        break;
1260#if BASH_PROCESS_SUBST
1261                case CTLTOPROC:
1262                        putc('>', fp);
1263                        goto backq;
1264                case CTLFROMPROC:
1265                        putc('<', fp);
1266                        goto backq;
1267#endif
1268                case CTLBACKQ:
1269                        putc('$', fp);
1270 IF_BASH_PROCESS_SUBST(backq:)
1271                        putc('(', fp);
1272                        shtree(bqlist->n, -1, NULL, fp);
1273                        putc(')', fp);
1274                        break;
1275                default:
1276                        putc(*p, fp);
1277                        break;
1278                }
1279        }
1280}
1281
1282static void
1283shcmd(union node *cmd, FILE *fp)
1284{
1285        union node *np;
1286        int first;
1287        const char *s;
1288        int dftfd;
1289
1290        first = 1;
1291        for (np = cmd->ncmd.args; np; np = np->narg.next) {
1292                if (!first)
1293                        putc(' ', fp);
1294                sharg(np, fp);
1295                first = 0;
1296        }
1297        for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1298                if (!first)
1299                        putc(' ', fp);
1300                dftfd = 0;
1301                switch (np->nfile.type) {
1302                case NTO:      s = ">>"+1; dftfd = 1; break;
1303                case NCLOBBER: s = ">|"; dftfd = 1; break;
1304                case NAPPEND:  s = ">>"; dftfd = 1; break;
1305#if BASH_REDIR_OUTPUT
1306                case NTO2:
1307#endif
1308                case NTOFD:    s = ">&"; dftfd = 1; break;
1309                case NFROM:    s = "<"; break;
1310                case NFROMFD:  s = "<&"; break;
1311                case NFROMTO:  s = "<>"; break;
1312                default:       s = "*error*"; break;
1313                }
1314                if (np->nfile.fd != dftfd)
1315                        fprintf(fp, "%d", np->nfile.fd);
1316                fputs(s, fp);
1317                if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1318                        fprintf(fp, "%d", np->ndup.dupfd);
1319                } else {
1320                        sharg(np->nfile.fname, fp);
1321                }
1322                first = 0;
1323        }
1324}
1325
1326static void
1327shtree(union node *n, int ind, char *pfx, FILE *fp)
1328{
1329        struct nodelist *lp;
1330        const char *s;
1331
1332        if (n == NULL)
1333                return;
1334
1335        indent(ind, pfx, fp);
1336
1337        if (n == NODE_EOF) {
1338                fputs("<EOF>", fp);
1339                return;
1340        }
1341
1342        switch (n->type) {
1343        case NSEMI:
1344                s = "; ";
1345                goto binop;
1346        case NAND:
1347                s = " && ";
1348                goto binop;
1349        case NOR:
1350                s = " || ";
1351 binop:
1352                shtree(n->nbinary.ch1, ind, NULL, fp);
1353                /* if (ind < 0) */
1354                        fputs(s, fp);
1355                shtree(n->nbinary.ch2, ind, NULL, fp);
1356                break;
1357        case NCMD:
1358                shcmd(n, fp);
1359                if (ind >= 0)
1360                        putc('\n', fp);
1361                break;
1362        case NPIPE:
1363                for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1364                        shtree(lp->n, 0, NULL, fp);
1365                        if (lp->next)
1366                                fputs(" | ", fp);
1367                }
1368                if (n->npipe.pipe_backgnd)
1369                        fputs(" &", fp);
1370                if (ind >= 0)
1371                        putc('\n', fp);
1372                break;
1373        default:
1374                fprintf(fp, "<node type %d>", n->type);
1375                if (ind >= 0)
1376                        putc('\n', fp);
1377                break;
1378        }
1379}
1380
1381static void
1382showtree(union node *n)
1383{
1384        trace_puts("showtree called\n");
1385        shtree(n, 1, NULL, stderr);
1386}
1387
1388#endif /* DEBUG */
1389
1390
1391/* ============ Message printing */
1392
1393static void
1394ash_vmsg(const char *msg, va_list ap)
1395{
1396        fprintf(stderr, "%s: ", arg0);
1397        if (commandname) {
1398                if (strcmp(arg0, commandname))
1399                        fprintf(stderr, "%s: ", commandname);
1400                if (!iflag || g_parsefile->pf_fd > 0)
1401                        fprintf(stderr, "line %d: ", errlinno);
1402        }
1403        vfprintf(stderr, msg, ap);
1404        newline_and_flush(stderr);
1405}
1406
1407/*
1408 * Exverror is called to raise the error exception.  If the second argument
1409 * is not NULL then error prints an error message using printf style
1410 * formatting.  It then raises the error exception.
1411 */
1412static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1413static void
1414ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1415{
1416#if DEBUG
1417        if (msg) {
1418                TRACE(("ash_vmsg_and_raise(%d):", cond));
1419                TRACEV((msg, ap));
1420        } else
1421                TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1422        if (msg)
1423#endif
1424                ash_vmsg(msg, ap);
1425
1426        flush_stdout_stderr();
1427        raise_exception(cond);
1428        /* NOTREACHED */
1429}
1430
1431static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1432static void
1433ash_msg_and_raise_error(const char *msg, ...)
1434{
1435        va_list ap;
1436
1437        exitstatus = 2;
1438
1439        va_start(ap, msg);
1440        ash_vmsg_and_raise(EXERROR, msg, ap);
1441        /* NOTREACHED */
1442        va_end(ap);
1443}
1444
1445/*
1446 * 'fmt' must be a string literal.
1447 */
1448#define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": "STRERROR_FMT, ##__VA_ARGS__ STRERROR_ERRNO)
1449
1450static void raise_error_syntax(const char *) NORETURN;
1451static void
1452raise_error_syntax(const char *msg)
1453{
1454        errlinno = g_parsefile->linno;
1455        ash_msg_and_raise_error("syntax error: %s", msg);
1456        /* NOTREACHED */
1457}
1458
1459static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1460static void
1461ash_msg_and_raise(int cond, const char *msg, ...)
1462{
1463        va_list ap;
1464
1465        va_start(ap, msg);
1466        ash_vmsg_and_raise(cond, msg, ap);
1467        /* NOTREACHED */
1468        va_end(ap);
1469}
1470
1471/*
1472 * error/warning routines for external builtins
1473 */
1474static void
1475ash_msg(const char *fmt, ...)
1476{
1477        va_list ap;
1478
1479        va_start(ap, fmt);
1480        ash_vmsg(fmt, ap);
1481        va_end(ap);
1482}
1483
1484/*
1485 * Return a string describing an error.  The returned string may be a
1486 * pointer to a static buffer that will be overwritten on the next call.
1487 * Action describes the operation that got the error.
1488 */
1489static const char *
1490errmsg(int e, const char *em)
1491{
1492        if (e == ENOENT || e == ENOTDIR) {
1493                return em;
1494        }
1495        return strerror(e);
1496}
1497
1498
1499/* ============ Memory allocation */
1500
1501#if 0
1502/* I consider these wrappers nearly useless:
1503 * ok, they return you to nearest exception handler, but
1504 * how much memory do you leak in the process, making
1505 * memory starvation worse?
1506 */
1507static void *
1508ckrealloc(void * p, size_t nbytes)
1509{
1510        p = realloc(p, nbytes);
1511        if (!p)
1512                ash_msg_and_raise_error(bb_msg_memory_exhausted);
1513        return p;
1514}
1515
1516static void *
1517ckmalloc(size_t nbytes)
1518{
1519        return ckrealloc(NULL, nbytes);
1520}
1521
1522static void *
1523ckzalloc(size_t nbytes)
1524{
1525        return memset(ckmalloc(nbytes), 0, nbytes);
1526}
1527
1528static char *
1529ckstrdup(const char *s)
1530{
1531        char *p = strdup(s);
1532        if (!p)
1533                ash_msg_and_raise_error(bb_msg_memory_exhausted);
1534        return p;
1535}
1536#else
1537/* Using bbox equivalents. They exit if out of memory */
1538# define ckrealloc xrealloc
1539# define ckmalloc  xmalloc
1540# define ckzalloc  xzalloc
1541# define ckstrdup  xstrdup
1542#endif
1543
1544/*
1545 * It appears that grabstackstr() will barf with such alignments
1546 * because stalloc() will return a string allocated in a new stackblock.
1547 */
1548#define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1549enum {
1550        /* Most machines require the value returned from malloc to be aligned
1551         * in some way.  The following macro will get this right
1552         * on many machines.  */
1553        SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1554        /* Minimum size of a block */
1555        MINSIZE = SHELL_ALIGN(504),
1556};
1557
1558struct stack_block {
1559        struct stack_block *prev;
1560        char space[MINSIZE];
1561};
1562
1563struct stackmark {
1564        struct stack_block *stackp;
1565        char *stacknxt;
1566        size_t stacknleft;
1567};
1568
1569
1570struct globals_memstack {
1571        struct stack_block *g_stackp; // = &stackbase;
1572        char *g_stacknxt; // = stackbase.space;
1573        char *sstrend; // = stackbase.space + MINSIZE;
1574        size_t g_stacknleft; // = MINSIZE;
1575        struct stack_block stackbase;
1576};
1577extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack;
1578#define G_memstack (*ash_ptr_to_globals_memstack)
1579#define g_stackp     (G_memstack.g_stackp    )
1580#define g_stacknxt   (G_memstack.g_stacknxt  )
1581#define sstrend      (G_memstack.sstrend     )
1582#define g_stacknleft (G_memstack.g_stacknleft)
1583#define stackbase    (G_memstack.stackbase   )
1584#define INIT_G_memstack() do { \
1585        XZALLOC_CONST_PTR(&ash_ptr_to_globals_memstack, sizeof(G_memstack)); \
1586        g_stackp = &stackbase; \
1587        g_stacknxt = stackbase.space; \
1588        g_stacknleft = MINSIZE; \
1589        sstrend = stackbase.space + MINSIZE; \
1590} while (0)
1591
1592
1593#define stackblock()     ((void *)g_stacknxt)
1594#define stackblocksize() g_stacknleft
1595
1596/*
1597 * Parse trees for commands are allocated in lifo order, so we use a stack
1598 * to make this more efficient, and also to avoid all sorts of exception
1599 * handling code to handle interrupts in the middle of a parse.
1600 *
1601 * The size 504 was chosen because the Ultrix malloc handles that size
1602 * well.
1603 */
1604static void *
1605stalloc(size_t nbytes)
1606{
1607        char *p;
1608        size_t aligned;
1609
1610        aligned = SHELL_ALIGN(nbytes);
1611        if (aligned > g_stacknleft) {
1612                size_t len;
1613                size_t blocksize;
1614                struct stack_block *sp;
1615
1616                blocksize = aligned;
1617                if (blocksize < MINSIZE)
1618                        blocksize = MINSIZE;
1619                len = sizeof(struct stack_block) - MINSIZE + blocksize;
1620                if (len < blocksize)
1621                        ash_msg_and_raise_error(bb_msg_memory_exhausted);
1622                INT_OFF;
1623                sp = ckmalloc(len);
1624                sp->prev = g_stackp;
1625                g_stacknxt = sp->space;
1626                g_stacknleft = blocksize;
1627                sstrend = g_stacknxt + blocksize;
1628                g_stackp = sp;
1629                INT_ON;
1630        }
1631        p = g_stacknxt;
1632        g_stacknxt += aligned;
1633        g_stacknleft -= aligned;
1634        return p;
1635}
1636
1637static void *
1638stzalloc(size_t nbytes)
1639{
1640        return memset(stalloc(nbytes), 0, nbytes);
1641}
1642
1643static void
1644stunalloc(void *p)
1645{
1646#if DEBUG
1647        if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1648                write(STDERR_FILENO, "stunalloc\n", 10);
1649                abort();
1650        }
1651#endif
1652        g_stacknleft += g_stacknxt - (char *)p;
1653        g_stacknxt = p;
1654}
1655
1656/*
1657 * Like strdup but works with the ash stack.
1658 */
1659static char *
1660sstrdup(const char *p)
1661{
1662        size_t len = strlen(p) + 1;
1663        return memcpy(stalloc(len), p, len);
1664}
1665
1666static ALWAYS_INLINE void
1667grabstackblock(size_t len)
1668{
1669        stalloc(len);
1670}
1671
1672static void
1673pushstackmark(struct stackmark *mark, size_t len)
1674{
1675        mark->stackp = g_stackp;
1676        mark->stacknxt = g_stacknxt;
1677        mark->stacknleft = g_stacknleft;
1678        grabstackblock(len);
1679}
1680
1681static void
1682setstackmark(struct stackmark *mark)
1683{
1684        pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1685}
1686
1687static void
1688popstackmark(struct stackmark *mark)
1689{
1690        struct stack_block *sp;
1691
1692        if (!mark->stackp)
1693                return;
1694
1695        INT_OFF;
1696        while (g_stackp != mark->stackp) {
1697                sp = g_stackp;
1698                g_stackp = sp->prev;
1699                free(sp);
1700        }
1701        g_stacknxt = mark->stacknxt;
1702        g_stacknleft = mark->stacknleft;
1703        sstrend = mark->stacknxt + mark->stacknleft;
1704        INT_ON;
1705}
1706
1707/*
1708 * When the parser reads in a string, it wants to stick the string on the
1709 * stack and only adjust the stack pointer when it knows how big the
1710 * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1711 * of space on top of the stack and stackblocklen returns the length of
1712 * this block.  Growstackblock will grow this space by at least one byte,
1713 * possibly moving it (like realloc).  Grabstackblock actually allocates the
1714 * part of the block that has been used.
1715 */
1716static void
1717growstackblock(size_t min)
1718{
1719        size_t newlen;
1720
1721        newlen = g_stacknleft * 2;
1722        if (newlen < g_stacknleft)
1723                ash_msg_and_raise_error(bb_msg_memory_exhausted);
1724        min = SHELL_ALIGN(min | 128);
1725        if (newlen < min)
1726                newlen += min;
1727
1728        if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1729                struct stack_block *sp;
1730                struct stack_block *prevstackp;
1731                size_t grosslen;
1732
1733                INT_OFF;
1734                sp = g_stackp;
1735                prevstackp = sp->prev;
1736                grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1737                sp = ckrealloc(sp, grosslen);
1738                sp->prev = prevstackp;
1739                g_stackp = sp;
1740                g_stacknxt = sp->space;
1741                g_stacknleft = newlen;
1742                sstrend = sp->space + newlen;
1743                INT_ON;
1744        } else {
1745                char *oldspace = g_stacknxt;
1746                size_t oldlen = g_stacknleft;
1747                char *p = stalloc(newlen);
1748
1749                /* free the space we just allocated */
1750                g_stacknxt = memcpy(p, oldspace, oldlen);
1751                g_stacknleft += newlen;
1752        }
1753}
1754
1755/*
1756 * The following routines are somewhat easier to use than the above.
1757 * The user declares a variable of type STACKSTR, which may be declared
1758 * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1759 * the user uses the macro STPUTC to add characters to the string.  In
1760 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1761 * grown as necessary.  When the user is done, she can just leave the
1762 * string there and refer to it using stackblock().  Or she can allocate
1763 * the space for it using grabstackstr().  If it is necessary to allow
1764 * someone else to use the stack temporarily and then continue to grow
1765 * the string, the user should use grabstack to allocate the space, and
1766 * then call ungrabstr(p) to return to the previous mode of operation.
1767 *
1768 * USTPUTC is like STPUTC except that it doesn't check for overflow.
1769 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1770 * is space for at least one character.
1771 */
1772static void *
1773growstackstr(void)
1774{
1775        size_t len = stackblocksize();
1776        growstackblock(0);
1777        return (char *)stackblock() + len;
1778}
1779
1780static char *
1781growstackto(size_t len)
1782{
1783        if (stackblocksize() < len)
1784                growstackblock(len);
1785        return stackblock();
1786}
1787
1788/*
1789 * Called from CHECKSTRSPACE.
1790 */
1791static char *
1792makestrspace(size_t newlen, char *p)
1793{
1794        size_t len = p - g_stacknxt;
1795
1796        return growstackto(len + newlen) + len;
1797}
1798
1799static char *
1800stnputs(const char *s, size_t n, char *p)
1801{
1802        p = makestrspace(n, p);
1803        p = (char *)mempcpy(p, s, n);
1804        return p;
1805}
1806
1807static char *
1808stack_putstr(const char *s, char *p)
1809{
1810        return stnputs(s, strlen(s), p);
1811}
1812
1813static char *
1814_STPUTC(int c, char *p)
1815{
1816        if (p == sstrend)
1817                p = growstackstr();
1818        *p++ = c;
1819        return p;
1820}
1821
1822#define STARTSTACKSTR(p)        ((p) = stackblock())
1823#define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1824#define CHECKSTRSPACE(n, p) do { \
1825        char *q = (p); \
1826        size_t l = (n); \
1827        size_t m = sstrend - q; \
1828        if (l > m) \
1829                (p) = makestrspace(l, q); \
1830} while (0)
1831#define USTPUTC(c, p)           (*(p)++ = (c))
1832#define STACKSTRNUL(p) do { \
1833        if ((p) == sstrend) \
1834                (p) = growstackstr(); \
1835        *(p) = '\0'; \
1836} while (0)
1837#define STUNPUTC(p)             (--(p))
1838#define STTOPC(p)               ((p)[-1])
1839#define STADJUST(amount, p)     ((p) += (amount))
1840
1841#define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1842#define ungrabstackstr(s, p)    stunalloc(s)
1843#define stackstrend()           ((void *)sstrend)
1844
1845
1846/* ============ String helpers */
1847
1848/*
1849 * prefix -- see if pfx is a prefix of string.
1850 */
1851static char *
1852prefix(const char *string, const char *pfx)
1853{
1854        while (*pfx) {
1855                if (*pfx++ != *string++)
1856                        return NULL;
1857        }
1858        return (char *) string;
1859}
1860
1861/*
1862 * Check for a valid number.  This should be elsewhere.
1863 */
1864static int
1865is_number(const char *p)
1866{
1867        do {
1868                if (!isdigit(*p))
1869                        return 0;
1870        } while (*++p != '\0');
1871        return 1;
1872}
1873
1874/*
1875 * Convert a string of digits to an integer, printing an error message on
1876 * failure.
1877 */
1878static int
1879number(const char *s)
1880{
1881        if (!is_number(s))
1882                ash_msg_and_raise_error(msg_illnum, s);
1883        return atoi(s);
1884}
1885
1886/*
1887 * Produce a single quoted string suitable as input to the shell.
1888 * The return string is allocated on the stack.
1889 */
1890static char *
1891single_quote(const char *s)
1892{
1893        char *p;
1894
1895        STARTSTACKSTR(p);
1896
1897        do {
1898                char *q;
1899                size_t len;
1900
1901                len = strchrnul(s, '\'') - s;
1902
1903                q = p = makestrspace(len + 3, p);
1904
1905                *q++ = '\'';
1906                q = (char *)mempcpy(q, s, len);
1907                *q++ = '\'';
1908                s += len;
1909
1910                STADJUST(q - p, p);
1911
1912                if (*s != '\'')
1913                        break;
1914                len = 0;
1915                do len++; while (*++s == '\'');
1916
1917                q = p = makestrspace(len + 3, p);
1918
1919                *q++ = '"';
1920                q = (char *)mempcpy(q, s - len, len);
1921                *q++ = '"';
1922
1923                STADJUST(q - p, p);
1924        } while (*s);
1925
1926        USTPUTC('\0', p);
1927
1928        return stackblock();
1929}
1930
1931/*
1932 * Produce a possibly single quoted string suitable as input to the shell.
1933 * If quoting was done, the return string is allocated on the stack,
1934 * otherwise a pointer to the original string is returned.
1935 */
1936static const char *
1937maybe_single_quote(const char *s)
1938{
1939        const char *p = s;
1940
1941        while (*p) {
1942                /* Assuming ACSII */
1943                /* quote ctrl_chars space !"#$%&'()* */
1944                if (*p < '+')
1945                        goto need_quoting;
1946                /* quote ;<=>? */
1947                if (*p >= ';' && *p <= '?')
1948                        goto need_quoting;
1949                /* quote `[\ */
1950                if (*p == '`')
1951                        goto need_quoting;
1952                if (*p == '[')
1953                        goto need_quoting;
1954                if (*p == '\\')
1955                        goto need_quoting;
1956                /* quote {|}~ DEL and high bytes */
1957                if (*p > 'z')
1958                        goto need_quoting;
1959                /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1960                /* TODO: maybe avoid quoting % */
1961                p++;
1962        }
1963        return s;
1964
1965 need_quoting:
1966        return single_quote(s);
1967}
1968
1969
1970/* ============ nextopt */
1971
1972static char **argptr;                  /* argument list for builtin commands */
1973static char *optionarg;                /* set by nextopt (like getopt) */
1974static char *optptr;                   /* used by nextopt */
1975
1976/*
1977 * XXX - should get rid of. Have all builtins use getopt(3).
1978 * The library getopt must have the BSD extension static variable
1979 * "optreset", otherwise it can't be used within the shell safely.
1980 *
1981 * Standard option processing (a la getopt) for builtin routines.
1982 * The only argument that is passed to nextopt is the option string;
1983 * the other arguments are unnecessary. It returns the character,
1984 * or '\0' on end of input.
1985 */
1986static int
1987nextopt(const char *optstring)
1988{
1989        char *p;
1990        const char *q;
1991        char c;
1992
1993        p = optptr;
1994        if (p == NULL || *p == '\0') {
1995                /* We ate entire "-param", take next one */
1996                p = *argptr;
1997                if (p == NULL)
1998                        return '\0';
1999                if (*p != '-')
2000                        return '\0';
2001                if (*++p == '\0') /* just "-" ? */
2002                        return '\0';
2003                argptr++;
2004                if (LONE_DASH(p)) /* "--" ? */
2005                        return '\0';
2006                /* p => next "-param" */
2007        }
2008        /* p => some option char in the middle of a "-param" */
2009        c = *p++;
2010        for (q = optstring; *q != c;) {
2011                if (*q == '\0')
2012                        ash_msg_and_raise_error("illegal option -%c", c);
2013                if (*++q == ':')
2014                        q++;
2015        }
2016        if (*++q == ':') {
2017                if (*p == '\0') {
2018                        p = *argptr++;
2019                        if (p == NULL)
2020                                ash_msg_and_raise_error("no arg for -%c option", c);
2021                }
2022                optionarg = p;
2023                p = NULL;
2024        }
2025        optptr = p;
2026        return c;
2027}
2028
2029
2030/* ============ Shell variables */
2031
2032struct shparam {
2033        int nparam;             /* # of positional parameters (without $0) */
2034#if ENABLE_ASH_GETOPTS
2035        int optind;             /* next parameter to be processed by getopts */
2036        int optoff;             /* used by getopts */
2037#endif
2038        unsigned char malloced; /* if parameter list dynamically allocated */
2039        char **p;               /* parameter list */
2040};
2041
2042/*
2043 * Free the list of positional parameters.
2044 */
2045static void
2046freeparam(volatile struct shparam *param)
2047{
2048        if (param->malloced) {
2049                char **ap, **ap1;
2050                ap = ap1 = param->p;
2051                while (*ap)
2052                        free(*ap++);
2053                free(ap1);
2054        }
2055}
2056
2057#if ENABLE_ASH_GETOPTS
2058static void FAST_FUNC getoptsreset(const char *value);
2059#endif
2060
2061struct var {
2062        struct var *next;               /* next entry in hash list */
2063        int flags;                      /* flags are defined above */
2064        const char *var_text;           /* name=value */
2065        void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
2066                                        /* the variable gets set/unset */
2067};
2068
2069struct localvar {
2070        struct localvar *next;          /* next local variable in list */
2071        struct var *vp;                 /* the variable that was made local */
2072        int flags;                      /* saved flags */
2073        const char *text;               /* saved text */
2074};
2075
2076/* flags */
2077#define VEXPORT         0x01    /* variable is exported */
2078#define VREADONLY       0x02    /* variable cannot be modified */
2079#define VSTRFIXED       0x04    /* variable struct is statically allocated */
2080#define VTEXTFIXED      0x08    /* text is statically allocated */
2081#define VSTACK          0x10    /* text is allocated on the stack */
2082#define VUNSET          0x20    /* the variable is not set */
2083#define VNOFUNC         0x40    /* don't call the callback function */
2084#define VNOSET          0x80    /* do not set variable - just readonly test */
2085#define VNOSAVE         0x100   /* when text is on the heap before setvareq */
2086#if ENABLE_ASH_RANDOM_SUPPORT
2087# define VDYNAMIC       0x200   /* dynamic variable */
2088#else
2089# define VDYNAMIC       0
2090#endif
2091
2092
2093/* Need to be before varinit_data[] */
2094#if ENABLE_LOCALE_SUPPORT
2095static void FAST_FUNC
2096change_lc_all(const char *value)
2097{
2098        if (value && *value != '\0')
2099                setlocale(LC_ALL, value);
2100}
2101static void FAST_FUNC
2102change_lc_ctype(const char *value)
2103{
2104        if (value && *value != '\0')
2105                setlocale(LC_CTYPE, value);
2106}
2107#endif
2108#if ENABLE_ASH_MAIL
2109static void chkmail(void);
2110static void changemail(const char *var_value) FAST_FUNC;
2111#else
2112# define chkmail()  ((void)0)
2113#endif
2114static void changepath(const char *) FAST_FUNC;
2115#if ENABLE_ASH_RANDOM_SUPPORT
2116static void change_random(const char *) FAST_FUNC;
2117#endif
2118#if BASH_EPOCH_VARS
2119static void change_seconds(const char *) FAST_FUNC;
2120static void change_realtime(const char *) FAST_FUNC;
2121#endif
2122
2123static const struct {
2124        int flags;
2125        const char *var_text;
2126        void (*var_func)(const char *) FAST_FUNC;
2127} varinit_data[] ALIGN_PTR = {
2128        /*
2129         * Note: VEXPORT would not work correctly here for NOFORK applets:
2130         * some environment strings may be constant.
2131         */
2132        { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2133#if ENABLE_ASH_MAIL
2134        { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2135        { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2136#endif
2137        { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2138        { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2139        { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2140        { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2141#if ENABLE_ASH_GETOPTS
2142        { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2143#endif
2144        { VSTRFIXED|VTEXTFIXED       , NULL /* inited to linenovar */, NULL },
2145        { VSTRFIXED|VTEXTFIXED       , NULL /* inited to funcnamevar */, NULL },
2146#if ENABLE_ASH_RANDOM_SUPPORT
2147        { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2148#endif
2149#if BASH_EPOCH_VARS
2150        { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "EPOCHSECONDS", change_seconds },
2151        { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "EPOCHREALTIME", change_realtime },
2152#endif
2153#if ENABLE_LOCALE_SUPPORT
2154        { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2155        { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2156#endif
2157#if ENABLE_FEATURE_EDITING_SAVEHISTORY
2158        { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2159#endif
2160};
2161
2162struct redirtab;
2163
2164struct globals_var {
2165        struct shparam shellparam;      /* $@ current positional parameters */
2166        struct redirtab *redirlist;
2167        int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2168        struct var *vartab[VTABSIZE];
2169        struct var varinit[ARRAY_SIZE(varinit_data)];
2170        int lineno;
2171        char linenovar[sizeof("LINENO=") + sizeof(int)*3];
2172        char funcnamevar[sizeof("FUNCNAME=") + 64];
2173        char *funcname;
2174        unsigned trap_depth;
2175        bool in_trap_ERR; /* ERR cannot recurse, no need to be a counter */
2176};
2177extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var;
2178#define G_var (*ash_ptr_to_globals_var)
2179#define shellparam    (G_var.shellparam   )
2180//#define redirlist     (G_var.redirlist    )
2181#define preverrout_fd (G_var.preverrout_fd)
2182#define vartab        (G_var.vartab       )
2183#define varinit       (G_var.varinit      )
2184#define lineno        (G_var.lineno       )
2185#define linenovar     (G_var.linenovar    )
2186#define funcnamevar   (G_var.funcnamevar  )
2187#define funcname      (G_var.funcname     )
2188#define trap_depth    (G_var.trap_depth   )
2189#define in_trap_ERR   (G_var.in_trap_ERR  )
2190#define vifs      varinit[0]
2191#if ENABLE_ASH_MAIL
2192# define vmail    varinit[1]
2193# define vmpath   varinit[2]
2194#endif
2195#define VAR_OFFSET1 (ENABLE_ASH_MAIL*2)
2196#define vpath     varinit[VAR_OFFSET1 + 1]
2197#define vps1      varinit[VAR_OFFSET1 + 2]
2198#define vps2      varinit[VAR_OFFSET1 + 3]
2199#define vps4      varinit[VAR_OFFSET1 + 4]
2200#if ENABLE_ASH_GETOPTS
2201# define voptind  varinit[VAR_OFFSET1 + 5]
2202#endif
2203#define VAR_OFFSET2 (VAR_OFFSET1 + ENABLE_ASH_GETOPTS)
2204#define vlineno   varinit[VAR_OFFSET2 + 5]
2205#define vfuncname varinit[VAR_OFFSET2 + 6]
2206#if ENABLE_ASH_RANDOM_SUPPORT
2207# define vrandom  varinit[VAR_OFFSET2 + 7]
2208#endif
2209#define VAR_OFFSET3 (VAR_OFFSET2 + ENABLE_ASH_RANDOM_SUPPORT)
2210#if BASH_EPOCH_VARS
2211# define vepochs  varinit[VAR_OFFSET3 + 7]
2212# define vepochr  varinit[VAR_OFFSET3 + 8]
2213#endif
2214#define INIT_G_var() do { \
2215        unsigned i; \
2216        XZALLOC_CONST_PTR(&ash_ptr_to_globals_var, sizeof(G_var)); \
2217        for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2218                varinit[i].flags    = varinit_data[i].flags; \
2219                varinit[i].var_text = varinit_data[i].var_text; \
2220                varinit[i].var_func = varinit_data[i].var_func; \
2221        } \
2222        strcpy(linenovar, "LINENO="); \
2223        vlineno.var_text = linenovar; \
2224        strcpy(funcnamevar, "FUNCNAME="); \
2225        vfuncname.var_text = funcnamevar; \
2226} while (0)
2227
2228/*
2229 * The following macros access the values of the above variables.
2230 * They have to skip over the name.  They return the null string
2231 * for unset variables.
2232 */
2233#define ifsval()        (vifs.var_text + 4)
2234#define ifsset()        ((vifs.flags & VUNSET) == 0)
2235#if ENABLE_ASH_MAIL
2236# define mailval()      (vmail.var_text + 5)
2237# define mpathval()     (vmpath.var_text + 9)
2238# define mpathset()     ((vmpath.flags & VUNSET) == 0)
2239#endif
2240#define pathval()       (vpath.var_text + 5)
2241#define ps1val()        (vps1.var_text + 4)
2242#define ps2val()        (vps2.var_text + 4)
2243#define ps4val()        (vps4.var_text + 4)
2244#if ENABLE_ASH_GETOPTS
2245# define optindval()    (voptind.var_text + 7)
2246#endif
2247
2248#if ENABLE_ASH_GETOPTS
2249static void FAST_FUNC
2250getoptsreset(const char *value)
2251{
2252        shellparam.optind = 1;
2253        if (is_number(value))
2254                shellparam.optind = number(value) ?: 1;
2255        shellparam.optoff = -1;
2256}
2257#endif
2258
2259/*
2260 * Compares two strings up to the first = or '\0'.  The first
2261 * string must be terminated by '='; the second may be terminated by
2262 * either '=' or '\0'.
2263 */
2264static int
2265varcmp(const char *p, const char *q)
2266{
2267        int c, d;
2268
2269        while ((c = *p) == (d = *q)) {
2270                if (c == '\0' || c == '=')
2271                        goto out;
2272                p++;
2273                q++;
2274        }
2275        if (c == '=')
2276                c = '\0';
2277        if (d == '=')
2278                d = '\0';
2279 out:
2280        return c - d;
2281}
2282
2283/*
2284 * Find the appropriate entry in the hash table from the name.
2285 */
2286static struct var **
2287hashvar(const char *p)
2288{
2289        unsigned hashval;
2290
2291        hashval = ((unsigned char) *p) << 4;
2292        while (*p && *p != '=')
2293                hashval += (unsigned char) *p++;
2294        return &vartab[hashval % VTABSIZE];
2295}
2296
2297static int
2298vpcmp(const void *a, const void *b)
2299{
2300        return varcmp(*(const char **)a, *(const char **)b);
2301}
2302
2303/*
2304 * This routine initializes the builtin variables.
2305 */
2306static void
2307initvar(void)
2308{
2309        struct var *vp;
2310        struct var *end;
2311        struct var **vpp;
2312
2313        /*
2314         * PS1 depends on uid
2315         */
2316#if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2317        vps1.var_text = "PS1=\\w \\$ ";
2318#else
2319        if (!geteuid())
2320                vps1.var_text = "PS1=# ";
2321#endif
2322        vp = varinit;
2323        end = vp + ARRAY_SIZE(varinit);
2324        do {
2325                vpp = hashvar(vp->var_text);
2326                vp->next = *vpp;
2327                *vpp = vp;
2328        } while (++vp < end);
2329}
2330
2331static struct var **
2332findvar(struct var **vpp, const char *name)
2333{
2334        for (; *vpp; vpp = &(*vpp)->next) {
2335                if (varcmp((*vpp)->var_text, name) == 0) {
2336                        break;
2337                }
2338        }
2339        return vpp;
2340}
2341
2342/*
2343 * Find the value of a variable.  Returns NULL if not set.
2344 */
2345static const char* FAST_FUNC
2346lookupvar(const char *name)
2347{
2348        struct var *v;
2349
2350        v = *findvar(hashvar(name), name);
2351        if (v) {
2352#if ENABLE_ASH_RANDOM_SUPPORT || BASH_EPOCH_VARS
2353        /*
2354         * Dynamic variables are implemented roughly the same way they are
2355         * in bash. Namely, they're "special" so long as they aren't unset.
2356         * As soon as they're unset, they're no longer dynamic, and dynamic
2357         * lookup will no longer happen at that point. -- PFM.
2358         */
2359                if (v->flags & VDYNAMIC)
2360                        v->var_func(NULL);
2361#endif
2362                if (!(v->flags & VUNSET)) {
2363                        if (v->var_text == linenovar) {
2364                                fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno);
2365                        } else
2366                        if (v->var_text == funcnamevar) {
2367                                safe_strncpy(funcnamevar+9, funcname ? funcname : "", sizeof(funcnamevar)-9);
2368                        }
2369                        return var_end(v->var_text);
2370                }
2371        }
2372        return NULL;
2373}
2374
2375#if ENABLE_UNICODE_SUPPORT
2376static void
2377reinit_unicode_for_ash(void)
2378{
2379        /* Unicode support should be activated even if LANG is set
2380         * _during_ shell execution, not only if it was set when
2381         * shell was started. Therefore, re-check LANG every time:
2382         */
2383        if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2384         || ENABLE_UNICODE_USING_LOCALE
2385        ) {
2386                const char *s = lookupvar("LC_ALL");
2387                if (!s) s = lookupvar("LC_CTYPE");
2388                if (!s) s = lookupvar("LANG");
2389                reinit_unicode(s);
2390        }
2391}
2392#else
2393# define reinit_unicode_for_ash() ((void)0)
2394#endif
2395
2396/*
2397 * Search the environment of a builtin command.
2398 */
2399static ALWAYS_INLINE const char *
2400bltinlookup(const char *name)
2401{
2402        return lookupvar(name);
2403}
2404
2405/*
2406 * Same as setvar except that the variable and value are passed in
2407 * the first argument as name=value.  Since the first argument will
2408 * be actually stored in the table, it should not be a string that
2409 * will go away.
2410 * Called with interrupts off.
2411 */
2412static struct var *
2413setvareq(char *s, int flags)
2414{
2415        struct var *vp, **vpp;
2416
2417        vpp = hashvar(s);
2418        flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2419        vpp = findvar(vpp, s);
2420        vp = *vpp;
2421        if (vp) {
2422                if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2423                        const char *n;
2424
2425                        if (flags & VNOSAVE)
2426                                free(s);
2427                        n = vp->var_text;
2428                        exitstatus = 1;
2429                        ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2430                }
2431
2432                if (flags & VNOSET)
2433                        goto out;
2434
2435                if (vp->var_func && !(flags & VNOFUNC))
2436                        vp->var_func(var_end(s));
2437
2438                if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2439                        free((char*)vp->var_text);
2440
2441                if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2442                        *vpp = vp->next;
2443                        free(vp);
2444 out_free:
2445                        if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2446                                free(s);
2447                        goto out;
2448                }
2449
2450                flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2451#if ENABLE_ASH_RANDOM_SUPPORT || BASH_EPOCH_VARS
2452                if (flags & VUNSET)
2453                        flags &= ~VDYNAMIC;
2454#endif
2455        } else {
2456                /* variable s is not found */
2457                if (flags & VNOSET)
2458                        goto out;
2459                if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2460                        goto out_free;
2461                vp = ckzalloc(sizeof(*vp));
2462                vp->next = *vpp;
2463                /*vp->func = NULL; - ckzalloc did it */
2464                *vpp = vp;
2465        }
2466        if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2467                s = ckstrdup(s);
2468        vp->var_text = s;
2469        vp->flags = flags;
2470
2471 out:
2472        return vp;
2473}
2474
2475/*
2476 * Set the value of a variable.  The flags argument is ored with the
2477 * flags of the variable.  If val is NULL, the variable is unset.
2478 */
2479static struct var *
2480setvar(const char *name, const char *val, int flags)
2481{
2482        const char *q;
2483        char *p;
2484        char *nameeq;
2485        size_t namelen;
2486        size_t vallen;
2487        struct var *vp;
2488
2489        q = endofname(name);
2490        p = strchrnul(q, '=');
2491        namelen = p - name;
2492        if (!namelen || p != q)
2493                ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2494        vallen = 0;
2495        if (val == NULL) {
2496                flags |= VUNSET;
2497        } else {
2498                vallen = strlen(val);
2499        }
2500
2501        INT_OFF;
2502        nameeq = ckzalloc(namelen + vallen + 2);
2503        p = mempcpy(nameeq, name, namelen);
2504        if (val) {
2505                *p++ = '=';
2506                memcpy(p, val, vallen);
2507        }
2508        vp = setvareq(nameeq, flags | VNOSAVE);
2509        INT_ON;
2510
2511        return vp;
2512}
2513
2514static void FAST_FUNC
2515setvar0(const char *name, const char *val)
2516{
2517        setvar(name, val, 0);
2518}
2519
2520/*
2521 * Unset the specified variable.
2522 */
2523static void
2524unsetvar(const char *s)
2525{
2526        setvar(s, NULL, 0);
2527}
2528
2529/*
2530 * Generate a list of variables satisfying the given conditions.
2531 */
2532#if !ENABLE_FEATURE_SH_NOFORK
2533# define listvars(on, off, lp, end) listvars(on, off, end)
2534#endif
2535static char **
2536listvars(int on, int off, struct strlist *lp, char ***end)
2537{
2538        struct var **vpp;
2539        struct var *vp;
2540        char **ep;
2541        int mask;
2542
2543        STARTSTACKSTR(ep);
2544        vpp = vartab;
2545        mask = on | off;
2546        do {
2547                for (vp = *vpp; vp; vp = vp->next) {
2548                        if ((vp->flags & mask) == on) {
2549#if ENABLE_FEATURE_SH_NOFORK
2550                                /* If variable with the same name is both
2551                                 * exported and temporarily set for a command:
2552                                 *  export ZVAR=5
2553                                 *  ZVAR=6 printenv
2554                                 * then "ZVAR=6" will be both in vartab and
2555                                 * lp lists. Do not pass it twice to printenv.
2556                                 */
2557                                struct strlist *lp1 = lp;
2558                                while (lp1) {
2559                                        if (strcmp(lp1->text, vp->var_text) == 0)
2560                                                goto skip;
2561                                        lp1 = lp1->next;
2562                                }
2563#endif
2564                                if (ep == stackstrend())
2565                                        ep = growstackstr();
2566                                *ep++ = (char*)vp->var_text;
2567#if ENABLE_FEATURE_SH_NOFORK
2568 skip: ;
2569#endif
2570                        }
2571                }
2572        } while (++vpp < vartab + VTABSIZE);
2573
2574#if ENABLE_FEATURE_SH_NOFORK
2575        while (lp) {
2576                if (ep == stackstrend())
2577                        ep = growstackstr();
2578                *ep++ = lp->text;
2579                lp = lp->next;
2580        }
2581#endif
2582
2583        if (ep == stackstrend())
2584                ep = growstackstr();
2585        if (end)
2586                *end = ep;
2587        *ep++ = NULL;
2588        return grabstackstr(ep);
2589}
2590
2591
2592/* ============ Path search helper */
2593static const char *
2594legal_pathopt(const char *opt, const char *term, int magic)
2595{
2596        switch (magic) {
2597        case 0:
2598                opt = NULL;
2599                break;
2600
2601        case 1:
2602                opt = prefix(opt, "builtin") ?: prefix(opt, "func");
2603                break;
2604
2605        default:
2606                opt += strcspn(opt, term);
2607                break;
2608        }
2609
2610        if (opt && *opt == '%')
2611                opt++;
2612
2613        return opt;
2614}
2615
2616/*
2617 * The variable path (passed by reference) should be set to the start
2618 * of the path before the first call; padvance will update
2619 * this value as it proceeds.  Successive calls to padvance will return
2620 * the possible path expansions in sequence.  If an option (indicated by
2621 * a percent sign) appears in the path entry then the global variable
2622 * pathopt will be set to point to it; otherwise pathopt will be set to
2623 * NULL.
2624 *
2625 * If magic is 0 then pathopt recognition will be disabled.  If magic is
2626 * 1 we shall recognise %builtin/%func.  Otherwise we shall accept any
2627 * pathopt.
2628 */
2629static const char *pathopt;     /* set by padvance */
2630
2631static int
2632padvance_magic(const char **path, const char *name, int magic)
2633{
2634        const char *term = "%:";
2635        const char *lpathopt;
2636        const char *p;
2637        char *q;
2638        const char *start;
2639        size_t qlen;
2640        size_t len;
2641
2642        if (*path == NULL)
2643                return -1;
2644
2645        lpathopt = NULL;
2646        start = *path;
2647
2648        if (*start == '%' && (p = legal_pathopt(start + 1, term, magic))) {
2649                lpathopt = start + 1;
2650                start = p;
2651                term = ":";
2652        }
2653
2654        len = strcspn(start, term);
2655        p = start + len;
2656
2657        if (*p == '%') {
2658                size_t extra = strchrnul(p, ':') - p;
2659
2660                if (legal_pathopt(p + 1, term, magic))
2661                        lpathopt = p + 1;
2662                else
2663                        len += extra;
2664
2665                p += extra;
2666        }
2667
2668        pathopt = lpathopt;
2669        *path = *p == ':' ? p + 1 : NULL;
2670
2671        /* "2" is for '/' and '\0' */
2672        qlen = len + strlen(name) + 2;
2673        q = growstackto(qlen);
2674
2675        if (len) {
2676                q = mempcpy(q, start, len);
2677                *q++ = '/';
2678        }
2679        strcpy(q, name);
2680
2681        return qlen;
2682}
2683
2684static int
2685padvance(const char **path, const char *name)
2686{
2687        return padvance_magic(path, name, 1);
2688}
2689
2690
2691/* ============ Prompt */
2692
2693static smallint doprompt;                   /* if set, prompt the user */
2694static smallint needprompt;                 /* true if interactive and at start of line */
2695
2696#if ENABLE_FEATURE_EDITING
2697static line_input_t *line_input_state;
2698static const char *cmdedit_prompt;
2699static void
2700putprompt(const char *s)
2701{
2702        if (ENABLE_ASH_EXPAND_PRMT) {
2703                free((char*)cmdedit_prompt);
2704                cmdedit_prompt = ckstrdup(s);
2705                return;
2706        }
2707        cmdedit_prompt = s;
2708}
2709#else
2710static void
2711putprompt(const char *s)
2712{
2713        out2str(s);
2714}
2715#endif
2716
2717/* expandstr() needs parsing machinery, so it is far away ahead... */
2718static const char *expandstr(const char *ps, int syntax_type);
2719/* Values for syntax param */
2720#define BASESYNTAX 0    /* not in quotes */
2721#define DQSYNTAX   1    /* in double quotes */
2722#define SQSYNTAX   2    /* in single quotes */
2723#define ARISYNTAX  3    /* in arithmetic */
2724#if ENABLE_ASH_EXPAND_PRMT
2725# define PSSYNTAX  4    /* prompt. never passed to SIT() */
2726#endif
2727/* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2728
2729/*
2730 * called by editline -- any expansions to the prompt should be added here.
2731 */
2732static void
2733setprompt_if(smallint do_set, int whichprompt)
2734{
2735        const char *prompt;
2736        IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2737
2738        if (!do_set)
2739                return;
2740
2741        needprompt = 0;
2742
2743        switch (whichprompt) {
2744        case 1:
2745                prompt = ps1val();
2746                break;
2747        case 2:
2748                prompt = ps2val();
2749                break;
2750        default:                        /* 0 */
2751                prompt = nullstr;
2752        }
2753#if ENABLE_ASH_EXPAND_PRMT
2754        pushstackmark(&smark, stackblocksize());
2755        putprompt(expandstr(prompt, PSSYNTAX));
2756        popstackmark(&smark);
2757#else
2758        putprompt(prompt);
2759#endif
2760}
2761
2762
2763/* ============ The cd and pwd commands */
2764
2765#define CD_PHYSICAL 1
2766#define CD_PRINT 2
2767
2768static int
2769cdopt(void)
2770{
2771        int flags = 0;
2772        int i, j;
2773
2774        j = 'L';
2775        while ((i = nextopt("LP")) != '\0') {
2776                if (i != j) {
2777                        flags ^= CD_PHYSICAL;
2778                        j = i;
2779                }
2780        }
2781
2782        return flags;
2783}
2784
2785/*
2786 * Update curdir (the name of the current directory) in response to a
2787 * cd command.
2788 */
2789static const char *
2790updatepwd(const char *dir)
2791{
2792        char *new;
2793        char *p;
2794        char *cdcomppath;
2795        const char *lim;
2796
2797        cdcomppath = sstrdup(dir);
2798        STARTSTACKSTR(new);
2799        if (*dir != '/') {
2800                if (curdir == nullstr)
2801                        return 0;
2802                new = stack_putstr(curdir, new);
2803        }
2804        new = makestrspace(strlen(dir) + 2, new);
2805        lim = (char *)stackblock() + 1;
2806        if (*dir != '/') {
2807                if (new[-1] != '/')
2808                        USTPUTC('/', new);
2809                if (new > lim && *lim == '/')
2810                        lim++;
2811        } else {
2812                USTPUTC('/', new);
2813                cdcomppath++;
2814                if (dir[1] == '/' && dir[2] != '/') {
2815                        USTPUTC('/', new);
2816                        cdcomppath++;
2817                        lim++;
2818                }
2819        }
2820        p = strtok_r(cdcomppath, "/", &cdcomppath);
2821        while (p) {
2822                switch (*p) {
2823                case '.':
2824                        if (p[1] == '.' && p[2] == '\0') {
2825                                while (new > lim) {
2826                                        STUNPUTC(new);
2827                                        if (new[-1] == '/')
2828                                                break;
2829                                }
2830                                break;
2831                        }
2832                        if (p[1] == '\0')
2833                                break;
2834                        /* fall through */
2835                default:
2836                        new = stack_putstr(p, new);
2837                        USTPUTC('/', new);
2838                }
2839                p = strtok_r(NULL, "/", &cdcomppath);
2840        }
2841        if (new > lim)
2842                STUNPUTC(new);
2843        *new = 0;
2844        return stackblock();
2845}
2846
2847/*
2848 * Find out what the current directory is. If we already know the current
2849 * directory, this routine returns immediately.
2850 */
2851static char *
2852getpwd(void)
2853{
2854        char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2855        return dir ? dir : nullstr;
2856}
2857
2858static void
2859setpwd(const char *val, int setold)
2860{
2861        char *oldcur, *dir;
2862
2863        oldcur = dir = curdir;
2864
2865        if (setold) {
2866                setvar("OLDPWD", oldcur, VEXPORT);
2867        }
2868        INT_OFF;
2869        if (physdir != nullstr) {
2870                if (physdir != oldcur)
2871                        free(physdir);
2872                physdir = nullstr;
2873        }
2874        if (oldcur == val || !val) {
2875                char *s = getpwd();
2876                physdir = s;
2877                if (!val)
2878                        dir = s;
2879        } else
2880                dir = ckstrdup(val);
2881        if (oldcur != dir && oldcur != nullstr) {
2882                free(oldcur);
2883        }
2884        curdir = dir;
2885        INT_ON;
2886        setvar("PWD", dir, VEXPORT);
2887}
2888
2889static void hashcd(void);
2890
2891/*
2892 * Actually do the chdir.  We also call hashcd to let other routines
2893 * know that the current directory has changed.
2894 */
2895static int
2896docd(const char *dest, int flags)
2897{
2898        const char *dir = NULL;
2899        int err;
2900
2901        TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2902
2903        INT_OFF;
2904        if (!(flags & CD_PHYSICAL)) {
2905                dir = updatepwd(dest);
2906                if (dir)
2907                        dest = dir;
2908        }
2909        err = chdir(dest);
2910        if (err)
2911                goto out;
2912        setpwd(dir, 1);
2913        hashcd();
2914 out:
2915        INT_ON;
2916        return err;
2917}
2918
2919static int FAST_FUNC
2920cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2921{
2922        const char *dest;
2923        const char *path;
2924        const char *p;
2925        char c;
2926        struct stat statb;
2927        int flags;
2928        int len;
2929
2930        flags = cdopt();
2931        dest = *argptr;
2932        if (!dest)
2933                dest = bltinlookup("HOME");
2934        else if (LONE_DASH(dest)) {
2935                dest = bltinlookup("OLDPWD");
2936                flags |= CD_PRINT;
2937        }
2938        if (!dest)
2939                dest = nullstr;
2940        if (*dest == '/')
2941                goto step6;
2942        if (*dest == '.') {
2943                c = dest[1];
2944 dotdot:
2945                switch (c) {
2946                case '\0':
2947                case '/':
2948                        goto step6;
2949                case '.':
2950                        c = dest[2];
2951                        if (c != '.')
2952                                goto dotdot;
2953                }
2954        }
2955        if (!*dest)
2956                dest = ".";
2957        path = bltinlookup("CDPATH");
2958        while (p = path, (len = padvance(&path, dest)) >= 0) {
2959                c = *p;
2960                p = stalloc(len);
2961
2962                if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2963                        if (c && c != ':')
2964                                flags |= CD_PRINT;
2965 docd:
2966                        if (!docd(p, flags))
2967                                goto out;
2968                        goto err;
2969                }
2970        }
2971
2972 step6:
2973        p = dest;
2974        goto docd;
2975
2976 err:
2977        ash_msg_and_raise_perror("can't cd to %s", dest);
2978        /* NOTREACHED */
2979 out:
2980        if (flags & CD_PRINT)
2981                out1fmt("%s\n", curdir);
2982        return 0;
2983}
2984
2985static int FAST_FUNC
2986pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2987{
2988        int flags;
2989        const char *dir = curdir;
2990
2991        flags = cdopt();
2992        if (flags) {
2993                if (physdir == nullstr)
2994                        setpwd(dir, 0);
2995                dir = physdir;
2996        }
2997        out1fmt("%s\n", dir);
2998        return 0;
2999}
3000
3001
3002/* ============ ... */
3003
3004
3005#define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
3006
3007/* Syntax classes */
3008#define CWORD     0             /* character is nothing special */
3009#define CNL       1             /* newline character */
3010#define CBACK     2             /* a backslash character */
3011#define CSQUOTE   3             /* single quote */
3012#define CDQUOTE   4             /* double quote */
3013#define CENDQUOTE 5             /* a terminating quote */
3014#define CBQUOTE   6             /* backwards single quote */
3015#define CVAR      7             /* a dollar sign */
3016#define CENDVAR   8             /* a '}' character */
3017#define CLP       9             /* a left paren in arithmetic */
3018#define CRP      10             /* a right paren in arithmetic */
3019#define CENDFILE 11             /* end of file */
3020#define CCTL     12             /* like CWORD, except it must be escaped */
3021#define CSPCL    13             /* these terminate a word */
3022
3023#define PEOF     256
3024
3025#define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
3026
3027#if ENABLE_FEATURE_SH_MATH
3028# define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
3029#else
3030# define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
3031#endif
3032static const uint16_t S_I_T[] ALIGN2 = {
3033        SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 0, ' ' */
3034        SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 1, \n */
3035        SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 2, !*-/:=?[]~ */
3036        SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 3, '"' */
3037        SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 4, $ */
3038        SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 5, "'" */
3039        SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 6, ( */
3040        SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 7, ) */
3041        SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 8, \ */
3042        SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 9, ` */
3043        SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 10, } */
3044#if !USE_SIT_FUNCTION
3045        SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 11, PEOF */
3046        SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 12, 0-9A-Za-z */
3047        SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 13, CTLESC ... */
3048#endif
3049#undef SIT_ITEM
3050};
3051/* Constants below must match table above */
3052enum {
3053        CSPCL_CWORD_CWORD_CWORD            , /*  0 */
3054        CNL_CNL_CNL_CNL                    , /*  1 */
3055        CWORD_CCTL_CCTL_CWORD              , /*  2 */
3056        CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  3 */
3057        CVAR_CVAR_CWORD_CVAR               , /*  4 */
3058        CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  5 */
3059        CSPCL_CWORD_CWORD_CLP              , /*  6 */
3060        CSPCL_CWORD_CWORD_CRP              , /*  7 */
3061        CBACK_CBACK_CCTL_CBACK             , /*  8 */
3062        CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /*  9 */
3063        CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 10 */
3064        CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 11 */
3065        CWORD_CWORD_CWORD_CWORD            , /* 12 */
3066        CCTL_CCTL_CCTL_CCTL                , /* 13 */
3067};
3068
3069/* c in SIT(c, syntax) must be an *unsigned char* or PEOF,
3070 * caller must ensure proper cast on it if c is *char_ptr!
3071 */
3072#if USE_SIT_FUNCTION
3073
3074static int
3075SIT(int c, int syntax)
3076{
3077        /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
3078        static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
3079        /*
3080         * This causes '/' to be prepended with CTLESC in dquoted string,
3081         * making "./file"* treated incorrectly because we feed
3082         * ".\/file*" string to glob(), confusing it (see expandmeta func).
3083         * The "homegrown" glob implementation is okay with that,
3084         * but glibc one isn't. With '/' always treated as CWORD,
3085         * both work fine.
3086         */
3087        static const uint8_t syntax_index_table[] ALIGN1 = {
3088                0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
3089                6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
3090                2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
3091                10, 2                           /* "}~" */
3092        };
3093        const char *s;
3094        int indx;
3095
3096        if (c == PEOF)
3097                return CENDFILE;
3098        /* Cast is purely for paranoia here,
3099         * just in case someone passed signed char to us */
3100        if ((unsigned char)c >= CTL_FIRST
3101         && (unsigned char)c <= CTL_LAST
3102        ) {
3103                return CCTL;
3104        }
3105        s = strchrnul(spec_symbls, c);
3106        if (*s == '\0')
3107                return CWORD;
3108        indx = syntax_index_table[s - spec_symbls];
3109        return (S_I_T[indx] >> (syntax*4)) & 0xf;
3110}
3111
3112#else   /* !USE_SIT_FUNCTION */
3113
3114static const uint8_t syntax_index_table[] ALIGN1 = {
3115        /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
3116        /*   0      */ CWORD_CWORD_CWORD_CWORD,
3117        /*   1      */ CWORD_CWORD_CWORD_CWORD,
3118        /*   2      */ CWORD_CWORD_CWORD_CWORD,
3119        /*   3      */ CWORD_CWORD_CWORD_CWORD,
3120        /*   4      */ CWORD_CWORD_CWORD_CWORD,
3121        /*   5      */ CWORD_CWORD_CWORD_CWORD,
3122        /*   6      */ CWORD_CWORD_CWORD_CWORD,
3123        /*   7      */ CWORD_CWORD_CWORD_CWORD,
3124        /*   8      */ CWORD_CWORD_CWORD_CWORD,
3125        /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
3126        /*  10 "\n" */ CNL_CNL_CNL_CNL,
3127        /*  11      */ CWORD_CWORD_CWORD_CWORD,
3128        /*  12      */ CWORD_CWORD_CWORD_CWORD,
3129        /*  13      */ CWORD_CWORD_CWORD_CWORD,
3130        /*  14      */ CWORD_CWORD_CWORD_CWORD,
3131        /*  15      */ CWORD_CWORD_CWORD_CWORD,
3132        /*  16      */ CWORD_CWORD_CWORD_CWORD,
3133        /*  17      */ CWORD_CWORD_CWORD_CWORD,
3134        /*  18      */ CWORD_CWORD_CWORD_CWORD,
3135        /*  19      */ CWORD_CWORD_CWORD_CWORD,
3136        /*  20      */ CWORD_CWORD_CWORD_CWORD,
3137        /*  21      */ CWORD_CWORD_CWORD_CWORD,
3138        /*  22      */ CWORD_CWORD_CWORD_CWORD,
3139        /*  23      */ CWORD_CWORD_CWORD_CWORD,
3140        /*  24      */ CWORD_CWORD_CWORD_CWORD,
3141        /*  25      */ CWORD_CWORD_CWORD_CWORD,
3142        /*  26      */ CWORD_CWORD_CWORD_CWORD,
3143        /*  27      */ CWORD_CWORD_CWORD_CWORD,
3144        /*  28      */ CWORD_CWORD_CWORD_CWORD,
3145        /*  29      */ CWORD_CWORD_CWORD_CWORD,
3146        /*  30      */ CWORD_CWORD_CWORD_CWORD,
3147        /*  31      */ CWORD_CWORD_CWORD_CWORD,
3148        /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
3149        /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
3150        /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
3151        /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
3152        /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
3153        /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
3154        /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
3155        /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
3156        /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
3157        /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
3158        /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
3159        /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
3160        /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
3161        /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
3162        /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
3163/* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
3164        /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
3165        /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
3166        /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
3167        /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
3168        /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
3169        /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
3170        /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
3171        /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
3172        /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
3173        /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
3174        /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
3175        /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
3176        /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
3177        /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
3178        /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
3179        /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
3180        /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
3181        /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
3182        /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
3183        /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
3184        /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
3185        /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
3186        /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
3187        /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
3188        /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
3189        /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
3190        /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
3191        /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
3192        /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
3193        /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
3194        /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
3195        /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
3196        /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
3197        /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
3198        /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
3199        /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
3200        /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3201        /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3202        /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3203        /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3204        /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3205        /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3206        /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3207        /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3208        /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3209        /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3210        /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3211        /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3212        /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3213        /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3214        /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3215        /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3216        /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3217        /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3218        /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3219        /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3220        /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3221        /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3222        /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3223        /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3224        /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3225        /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3226        /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3227        /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3228        /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3229        /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3230        /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3231        /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3232        /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3233        /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3234        /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3235        /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3236        /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3237        /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3238        /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3239        /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3240        /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3241        /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3242        /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3243        /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3244        /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3245        /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3246        /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3247        /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3248        /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3249        /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3250        /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3251        /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3252        /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3253        /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3254#if BASH_PROCESS_SUBST
3255        /* 137 CTLTOPROC    */ CCTL_CCTL_CCTL_CCTL,
3256        /* 138 CTLFROMPROC  */ CCTL_CCTL_CCTL_CCTL,
3257#else
3258        /* 137      */ CWORD_CWORD_CWORD_CWORD,
3259        /* 138      */ CWORD_CWORD_CWORD_CWORD,
3260#endif
3261        /* 139      */ CWORD_CWORD_CWORD_CWORD,
3262        /* 140      */ CWORD_CWORD_CWORD_CWORD,
3263        /* 141      */ CWORD_CWORD_CWORD_CWORD,
3264        /* 142      */ CWORD_CWORD_CWORD_CWORD,
3265        /* 143      */ CWORD_CWORD_CWORD_CWORD,
3266        /* 144      */ CWORD_CWORD_CWORD_CWORD,
3267        /* 145      */ CWORD_CWORD_CWORD_CWORD,
3268        /* 146      */ CWORD_CWORD_CWORD_CWORD,
3269        /* 147      */ CWORD_CWORD_CWORD_CWORD,
3270        /* 148      */ CWORD_CWORD_CWORD_CWORD,
3271        /* 149      */ CWORD_CWORD_CWORD_CWORD,
3272        /* 150      */ CWORD_CWORD_CWORD_CWORD,
3273        /* 151      */ CWORD_CWORD_CWORD_CWORD,
3274        /* 152      */ CWORD_CWORD_CWORD_CWORD,
3275        /* 153      */ CWORD_CWORD_CWORD_CWORD,
3276        /* 154      */ CWORD_CWORD_CWORD_CWORD,
3277        /* 155      */ CWORD_CWORD_CWORD_CWORD,
3278        /* 156      */ CWORD_CWORD_CWORD_CWORD,
3279        /* 157      */ CWORD_CWORD_CWORD_CWORD,
3280        /* 158      */ CWORD_CWORD_CWORD_CWORD,
3281        /* 159      */ CWORD_CWORD_CWORD_CWORD,
3282        /* 160      */ CWORD_CWORD_CWORD_CWORD,
3283        /* 161      */ CWORD_CWORD_CWORD_CWORD,
3284        /* 162      */ CWORD_CWORD_CWORD_CWORD,
3285        /* 163      */ CWORD_CWORD_CWORD_CWORD,
3286        /* 164      */ CWORD_CWORD_CWORD_CWORD,
3287        /* 165      */ CWORD_CWORD_CWORD_CWORD,
3288        /* 166      */ CWORD_CWORD_CWORD_CWORD,
3289        /* 167      */ CWORD_CWORD_CWORD_CWORD,
3290        /* 168      */ CWORD_CWORD_CWORD_CWORD,
3291        /* 169      */ CWORD_CWORD_CWORD_CWORD,
3292        /* 170      */ CWORD_CWORD_CWORD_CWORD,
3293        /* 171      */ CWORD_CWORD_CWORD_CWORD,
3294        /* 172      */ CWORD_CWORD_CWORD_CWORD,
3295        /* 173      */ CWORD_CWORD_CWORD_CWORD,
3296        /* 174      */ CWORD_CWORD_CWORD_CWORD,
3297        /* 175      */ CWORD_CWORD_CWORD_CWORD,
3298        /* 176      */ CWORD_CWORD_CWORD_CWORD,
3299        /* 177      */ CWORD_CWORD_CWORD_CWORD,
3300        /* 178      */ CWORD_CWORD_CWORD_CWORD,
3301        /* 179      */ CWORD_CWORD_CWORD_CWORD,
3302        /* 180      */ CWORD_CWORD_CWORD_CWORD,
3303        /* 181      */ CWORD_CWORD_CWORD_CWORD,
3304        /* 182      */ CWORD_CWORD_CWORD_CWORD,
3305        /* 183      */ CWORD_CWORD_CWORD_CWORD,
3306        /* 184      */ CWORD_CWORD_CWORD_CWORD,
3307        /* 185      */ CWORD_CWORD_CWORD_CWORD,
3308        /* 186      */ CWORD_CWORD_CWORD_CWORD,
3309        /* 187      */ CWORD_CWORD_CWORD_CWORD,
3310        /* 188      */ CWORD_CWORD_CWORD_CWORD,
3311        /* 189      */ CWORD_CWORD_CWORD_CWORD,
3312        /* 190      */ CWORD_CWORD_CWORD_CWORD,
3313        /* 191      */ CWORD_CWORD_CWORD_CWORD,
3314        /* 192      */ CWORD_CWORD_CWORD_CWORD,
3315        /* 193      */ CWORD_CWORD_CWORD_CWORD,
3316        /* 194      */ CWORD_CWORD_CWORD_CWORD,
3317        /* 195      */ CWORD_CWORD_CWORD_CWORD,
3318        /* 196      */ CWORD_CWORD_CWORD_CWORD,
3319        /* 197      */ CWORD_CWORD_CWORD_CWORD,
3320        /* 198      */ CWORD_CWORD_CWORD_CWORD,
3321        /* 199      */ CWORD_CWORD_CWORD_CWORD,
3322        /* 200      */ CWORD_CWORD_CWORD_CWORD,
3323        /* 201      */ CWORD_CWORD_CWORD_CWORD,
3324        /* 202      */ CWORD_CWORD_CWORD_CWORD,
3325        /* 203      */ CWORD_CWORD_CWORD_CWORD,
3326        /* 204      */ CWORD_CWORD_CWORD_CWORD,
3327        /* 205      */ CWORD_CWORD_CWORD_CWORD,
3328        /* 206      */ CWORD_CWORD_CWORD_CWORD,
3329        /* 207      */ CWORD_CWORD_CWORD_CWORD,
3330        /* 208      */ CWORD_CWORD_CWORD_CWORD,
3331        /* 209      */ CWORD_CWORD_CWORD_CWORD,
3332        /* 210      */ CWORD_CWORD_CWORD_CWORD,
3333        /* 211      */ CWORD_CWORD_CWORD_CWORD,
3334        /* 212      */ CWORD_CWORD_CWORD_CWORD,
3335        /* 213      */ CWORD_CWORD_CWORD_CWORD,
3336        /* 214      */ CWORD_CWORD_CWORD_CWORD,
3337        /* 215      */ CWORD_CWORD_CWORD_CWORD,
3338        /* 216      */ CWORD_CWORD_CWORD_CWORD,
3339        /* 217      */ CWORD_CWORD_CWORD_CWORD,
3340        /* 218      */ CWORD_CWORD_CWORD_CWORD,
3341        /* 219      */ CWORD_CWORD_CWORD_CWORD,
3342        /* 220      */ CWORD_CWORD_CWORD_CWORD,
3343        /* 221      */ CWORD_CWORD_CWORD_CWORD,
3344        /* 222      */ CWORD_CWORD_CWORD_CWORD,
3345        /* 223      */ CWORD_CWORD_CWORD_CWORD,
3346        /* 224      */ CWORD_CWORD_CWORD_CWORD,
3347        /* 225      */ CWORD_CWORD_CWORD_CWORD,
3348        /* 226      */ CWORD_CWORD_CWORD_CWORD,
3349        /* 227      */ CWORD_CWORD_CWORD_CWORD,
3350        /* 228      */ CWORD_CWORD_CWORD_CWORD,
3351        /* 229      */ CWORD_CWORD_CWORD_CWORD,
3352        /* 230      */ CWORD_CWORD_CWORD_CWORD,
3353        /* 231      */ CWORD_CWORD_CWORD_CWORD,
3354        /* 232      */ CWORD_CWORD_CWORD_CWORD,
3355        /* 233      */ CWORD_CWORD_CWORD_CWORD,
3356        /* 234      */ CWORD_CWORD_CWORD_CWORD,
3357        /* 235      */ CWORD_CWORD_CWORD_CWORD,
3358        /* 236      */ CWORD_CWORD_CWORD_CWORD,
3359        /* 237      */ CWORD_CWORD_CWORD_CWORD,
3360        /* 238      */ CWORD_CWORD_CWORD_CWORD,
3361        /* 239      */ CWORD_CWORD_CWORD_CWORD,
3362        /* 230      */ CWORD_CWORD_CWORD_CWORD,
3363        /* 241      */ CWORD_CWORD_CWORD_CWORD,
3364        /* 242      */ CWORD_CWORD_CWORD_CWORD,
3365        /* 243      */ CWORD_CWORD_CWORD_CWORD,
3366        /* 244      */ CWORD_CWORD_CWORD_CWORD,
3367        /* 245      */ CWORD_CWORD_CWORD_CWORD,
3368        /* 246      */ CWORD_CWORD_CWORD_CWORD,
3369        /* 247      */ CWORD_CWORD_CWORD_CWORD,
3370        /* 248      */ CWORD_CWORD_CWORD_CWORD,
3371        /* 249      */ CWORD_CWORD_CWORD_CWORD,
3372        /* 250      */ CWORD_CWORD_CWORD_CWORD,
3373        /* 251      */ CWORD_CWORD_CWORD_CWORD,
3374        /* 252      */ CWORD_CWORD_CWORD_CWORD,
3375        /* 253      */ CWORD_CWORD_CWORD_CWORD,
3376        /* 254      */ CWORD_CWORD_CWORD_CWORD,
3377        /* 255      */ CWORD_CWORD_CWORD_CWORD,
3378        /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3379};
3380
3381#if 1
3382# define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3383#else /* debug version, caught one signed char bug */
3384# define SIT(c, syntax) \
3385        ({ \
3386                if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3387                        bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3388                if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3389                        bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3390                ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3391        })
3392#endif
3393
3394#endif  /* !USE_SIT_FUNCTION */
3395
3396
3397/* ============ Alias handling */
3398
3399#if ENABLE_ASH_ALIAS
3400
3401#define ALIASINUSE 1
3402#define ALIASDEAD  2
3403
3404struct alias {
3405        struct alias *next;
3406        char *name;
3407        char *val;
3408        int flag;
3409};
3410
3411
3412static struct alias **atab; // [ATABSIZE];
3413#define INIT_G_alias() do { \
3414        atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3415} while (0)
3416
3417
3418static struct alias **
3419__lookupalias(const char *name)
3420{
3421        unsigned int hashval;
3422        struct alias **app;
3423        const char *p;
3424        unsigned int ch;
3425
3426        p = name;
3427
3428        ch = (unsigned char)*p;
3429        hashval = ch << 4;
3430        while (ch) {
3431                hashval += ch;
3432                ch = (unsigned char)*++p;
3433        }
3434        app = &atab[hashval % ATABSIZE];
3435
3436        for (; *app; app = &(*app)->next) {
3437                if (strcmp(name, (*app)->name) == 0) {
3438                        break;
3439                }
3440        }
3441
3442        return app;
3443}
3444
3445static struct alias *
3446lookupalias(const char *name, int check)
3447{
3448        struct alias *ap = *__lookupalias(name);
3449
3450        if (check && ap && (ap->flag & ALIASINUSE))
3451                return NULL;
3452        return ap;
3453}
3454
3455static struct alias *
3456freealias(struct alias *ap)
3457{
3458        struct alias *next;
3459
3460        if (ap->flag & ALIASINUSE) {
3461                ap->flag |= ALIASDEAD;
3462                return ap;
3463        }
3464
3465        next = ap->next;
3466        free(ap->name);
3467        free(ap->val);
3468        free(ap);
3469        return next;
3470}
3471
3472static void
3473setalias(const char *name, const char *val)
3474{
3475        struct alias *ap, **app;
3476
3477        app = __lookupalias(name);
3478        ap = *app;
3479        INT_OFF;
3480        if (ap) {
3481                if (!(ap->flag & ALIASINUSE)) {
3482                        free(ap->val);
3483                }
3484                ap->val = ckstrdup(val);
3485                ap->flag &= ~ALIASDEAD;
3486        } else {
3487                /* not found */
3488                ap = ckzalloc(sizeof(struct alias));
3489                ap->name = ckstrdup(name);
3490                ap->val = ckstrdup(val);
3491                /*ap->flag = 0; - ckzalloc did it */
3492                /*ap->next = NULL;*/
3493                *app = ap;
3494        }
3495        INT_ON;
3496}
3497
3498static int
3499unalias(const char *name)
3500{
3501        struct alias **app;
3502
3503        app = __lookupalias(name);
3504
3505        if (*app) {
3506                INT_OFF;
3507                *app = freealias(*app);
3508                INT_ON;
3509                return 0;
3510        }
3511
3512        return 1;
3513}
3514
3515static void
3516rmaliases(void)
3517{
3518        struct alias *ap, **app;
3519        int i;
3520
3521        INT_OFF;
3522        for (i = 0; i < ATABSIZE; i++) {
3523                app = &atab[i];
3524                for (ap = *app; ap; ap = *app) {
3525                        *app = freealias(*app);
3526                        if (ap == *app) {
3527                                app = &ap->next;
3528                        }
3529                }
3530        }
3531        INT_ON;
3532}
3533
3534static void
3535printalias(const struct alias *ap)
3536{
3537        out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3538}
3539
3540/*
3541 * TODO - sort output
3542 */
3543static int FAST_FUNC
3544aliascmd(int argc UNUSED_PARAM, char **argv)
3545{
3546        char *n, *v;
3547        int ret = 0;
3548        struct alias *ap;
3549
3550        if (!argv[1]) {
3551                int i;
3552
3553                for (i = 0; i < ATABSIZE; i++) {
3554                        for (ap = atab[i]; ap; ap = ap->next) {
3555                                printalias(ap);
3556                        }
3557                }
3558                return 0;
3559        }
3560        while ((n = *++argv) != NULL) {
3561                v = strchr(n+1, '=');
3562                if (v == NULL) { /* n+1: funny ksh stuff */
3563                        ap = *__lookupalias(n);
3564                        if (ap == NULL) {
3565                                fprintf(stderr, "%s: %s not found\n", "alias", n);
3566                                ret = 1;
3567                        } else
3568                                printalias(ap);
3569                } else {
3570                        *v++ = '\0';
3571                        setalias(n, v);
3572                }
3573        }
3574
3575        return ret;
3576}
3577
3578static int FAST_FUNC
3579unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3580{
3581        int i;
3582
3583        while (nextopt("a") != '\0') {
3584                rmaliases();
3585                return 0;
3586        }
3587        for (i = 0; *argptr; argptr++) {
3588                if (unalias(*argptr)) {
3589                        fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3590                        i = 1;
3591                }
3592        }
3593
3594        return i;
3595}
3596
3597#endif /* ASH_ALIAS */
3598
3599
3600/* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3601#define FORK_FG    0
3602#define FORK_BG    1
3603#define FORK_NOJOB 2
3604
3605/* mode flags for showjob(s) */
3606#define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3607#define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3608#define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3609#define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3610
3611/*
3612 * A job structure contains information about a job.  A job is either a
3613 * single process or a set of processes contained in a pipeline.  In the
3614 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3615 * array of pids.
3616 */
3617struct procstat {
3618        pid_t   ps_pid;         /* process id */
3619        int     ps_status;      /* last process status from wait() */
3620        char    *ps_cmd;        /* text of command being run */
3621};
3622
3623struct job {
3624        struct procstat ps0;    /* status of process */
3625        struct procstat *ps;    /* status of processes when more than one */
3626#if JOBS
3627        int stopstatus;         /* status of a stopped job */
3628#endif
3629        unsigned nprocs;        /* number of processes */
3630
3631#define JOBRUNNING      0       /* at least one proc running */
3632#define JOBSTOPPED      1       /* all procs are stopped */
3633#define JOBDONE         2       /* all procs are completed */
3634        unsigned
3635                state: 8,
3636#if JOBS
3637                sigint: 1,      /* job was killed by SIGINT */
3638                jobctl: 1,      /* job running under job control */
3639#endif
3640                waited: 1,      /* true if this entry has been waited for */
3641                used: 1,        /* true if this entry is in used */
3642                changed: 1;     /* true if status has changed */
3643        struct job *prev_job;   /* previous job */
3644};
3645
3646static struct job *makejob(/*union node *,*/ int);
3647static int forkshell(struct job *, union node *, int);
3648static int waitforjob(struct job *);
3649
3650#if !JOBS
3651enum { doing_jobctl = 0 };
3652#define setjobctl(on) do {} while (0)
3653#else
3654static smallint doing_jobctl; //references:8
3655static void setjobctl(int);
3656#endif
3657
3658/*
3659 * Ignore a signal.
3660 */
3661static void
3662ignoresig(int signo)
3663{
3664        /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3665        if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3666                /* No, need to do it */
3667                signal(signo, SIG_IGN);
3668        }
3669        sigmode[signo - 1] = S_HARD_IGN;
3670}
3671
3672/*
3673 * Only one usage site - in setsignal()
3674 */
3675static void
3676signal_handler(int signo)
3677{
3678        if (signo == SIGCHLD) {
3679                got_sigchld = 1;
3680                if (!trap[SIGCHLD])
3681                        return;
3682        }
3683
3684        gotsig[signo - 1] = 1;
3685        pending_sig = signo;
3686
3687        if (signo == SIGINT && !trap[SIGINT]) {
3688                if (!suppress_int) {
3689                        pending_sig = 0;
3690                        raise_interrupt(); /* does not return */
3691                }
3692                pending_int = 1;
3693        }
3694}
3695
3696/*
3697 * Set the signal handler for the specified signal.  The routine figures
3698 * out what it should be set to.
3699 */
3700static void
3701setsignal(int signo)
3702{
3703        char *t;
3704        char cur_act, new_act;
3705        struct sigaction act;
3706
3707        t = trap[signo];
3708        new_act = S_DFL;
3709        if (t != NULL) { /* trap for this sig is set */
3710                new_act = S_CATCH;
3711                if (t[0] == '\0') /* trap is "": ignore this sig */
3712                        new_act = S_IGN;
3713        }
3714
3715        if (rootshell && new_act == S_DFL) {
3716                switch (signo) {
3717                case SIGINT:
3718                        if (iflag || minusc || sflag == 0)
3719                                new_act = S_CATCH;
3720                        break;
3721                case SIGQUIT:
3722#if DEBUG
3723                        if (debug)
3724                                break;
3725#endif
3726                        /* man bash:
3727                         * "In all cases, bash ignores SIGQUIT. Non-builtin
3728                         * commands run by bash have signal handlers
3729                         * set to the values inherited by the shell
3730                         * from its parent". */
3731                        new_act = S_IGN;
3732                        break;
3733                case SIGTERM:
3734                        if (iflag)
3735                                new_act = S_IGN;
3736                        break;
3737#if JOBS
3738                case SIGTSTP:
3739                case SIGTTOU:
3740                        if (mflag)
3741                                new_act = S_IGN;
3742                        break;
3743#endif
3744                }
3745        }
3746        /* if !rootshell, we reset SIGQUIT to DFL,
3747         * whereas we have to restore it to what shell got on entry.
3748         * This is handled by the fact that if signal was IGNored on entry,
3749         * then cur_act is S_HARD_IGN and we never change its sigaction
3750         * (see code below).
3751         */
3752
3753        if (signo == SIGCHLD)
3754                new_act = S_CATCH;
3755
3756        t = &sigmode[signo - 1];
3757        cur_act = *t;
3758        if (cur_act == 0) {
3759                /* current setting is not yet known */
3760                if (sigaction(signo, NULL, &act)) {
3761                        /* pretend it worked; maybe we should give a warning,
3762                         * but other shells don't. We don't alter sigmode,
3763                         * so we retry every time.
3764                         * btw, in Linux it never fails. --vda */
3765                        return;
3766                }
3767                if (act.sa_handler == SIG_IGN) {
3768                        cur_act = S_HARD_IGN;
3769                        if (mflag
3770                         && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3771                        ) {
3772                                cur_act = S_IGN;   /* don't hard ignore these */
3773                        }
3774                }
3775                if (act.sa_handler == SIG_DFL && new_act == S_DFL) {
3776                        /* installing SIG_DFL over SIG_DFL is a no-op */
3777                        /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3778                        *t = S_DFL;
3779                        return;
3780                }
3781        }
3782        if (cur_act == S_HARD_IGN || cur_act == new_act)
3783                return;
3784
3785        *t = new_act;
3786
3787        act.sa_handler = SIG_DFL;
3788        switch (new_act) {
3789        case S_CATCH:
3790                act.sa_handler = signal_handler;
3791                break;
3792        case S_IGN:
3793                act.sa_handler = SIG_IGN;
3794                break;
3795        }
3796        /* flags and mask matter only if !DFL and !IGN, but we do it
3797         * for all cases for more deterministic behavior:
3798         */
3799        act.sa_flags = 0; //TODO: why not SA_RESTART?
3800        sigfillset(&act.sa_mask);
3801
3802        sigaction_set(signo, &act);
3803}
3804
3805/* mode flags for set_curjob */
3806#define CUR_DELETE 2
3807#define CUR_RUNNING 1
3808#define CUR_STOPPED 0
3809
3810#if JOBS
3811/* pgrp of shell on invocation */
3812static int initialpgrp; //references:2
3813static int ttyfd = -1; //5
3814#endif
3815/* array of jobs */
3816static struct job *jobtab; //5
3817/* size of array */
3818static unsigned njobs; //4
3819/* current job */
3820static struct job *curjob; //lots
3821
3822#if 0
3823/* Bash has a feature: it restores termios after a successful wait for
3824 * a foreground job which had at least one stopped or sigkilled member.
3825 * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3826 * properly restoring tty state. Should we do this too?
3827 * A reproducer: ^Z an interactive python:
3828 *
3829 * # python
3830 * Python 2.7.12 (...)
3831 * >>> ^Z
3832 *      { python leaves tty in -icanon -echo state. We do survive that... }
3833 *  [1]+  Stopped                    python
3834 *      { ...however, next program (python #2) does not survive it well: }
3835 * # python
3836 * Python 2.7.12 (...)
3837 * >>> Traceback (most recent call last):
3838 *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3839 *   File "<stdin>", line 1, in <module>
3840 * NameError: name 'qwerty' is not defined
3841 *
3842 * The implementation below is modeled on bash code and seems to work.
3843 * However, I'm not sure we should do this. For one: what if I'd fg
3844 * the stopped python instead? It'll be confused by "restored" tty state.
3845 */
3846static struct termios shell_tty_info;
3847static void
3848get_tty_state(void)
3849{
3850        if (rootshell && ttyfd >= 0)
3851                tcgetattr(ttyfd, &shell_tty_info);
3852}
3853static void
3854set_tty_state(void)
3855{
3856        /* if (rootshell) - caller ensures this */
3857        if (ttyfd >= 0)
3858                tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3859}
3860static int
3861job_signal_status(struct job *jp)
3862{
3863        int status;
3864        unsigned i;
3865        struct procstat *ps = jp->ps;
3866        for (i = 0; i < jp->nprocs; i++) {
3867                status = ps[i].ps_status;
3868                if (WIFSIGNALED(status) || WIFSTOPPED(status))
3869                        return status;
3870        }
3871        return 0;
3872}
3873static void
3874restore_tty_if_stopped_or_signaled(struct job *jp)
3875{
3876//TODO: check what happens if we come from waitforjob() in expbackq()
3877        if (rootshell) {
3878                int s = job_signal_status(jp);
3879                if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3880                        set_tty_state();
3881        }
3882}
3883#else
3884# define get_tty_state() ((void)0)
3885# define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3886#endif
3887
3888static void
3889set_curjob(struct job *jp, unsigned mode)
3890{
3891        struct job *jp1;
3892        struct job **jpp, **curp;
3893
3894        /* first remove from list */
3895        jpp = curp = &curjob;
3896        while (1) {
3897                jp1 = *jpp;
3898                if (jp1 == jp)
3899                        break;
3900                jpp = &jp1->prev_job;
3901        }
3902        *jpp = jp1->prev_job;
3903
3904        /* Then re-insert in correct position */
3905        jpp = curp;
3906        switch (mode) {
3907        default:
3908#if DEBUG
3909                abort();
3910#endif
3911        case CUR_DELETE:
3912                /* job being deleted */
3913                break;
3914        case CUR_RUNNING:
3915                /* newly created job or backgrounded job,
3916                 * put after all stopped jobs.
3917                 */
3918                while (1) {
3919                        jp1 = *jpp;
3920#if JOBS
3921                        if (!jp1 || jp1->state != JOBSTOPPED)
3922#endif
3923                                break;
3924                        jpp = &jp1->prev_job;
3925                }
3926                /* FALLTHROUGH */
3927#if JOBS
3928        case CUR_STOPPED:
3929#endif
3930                /* newly stopped job - becomes curjob */
3931                jp->prev_job = *jpp;
3932                *jpp = jp;
3933                break;
3934        }
3935}
3936
3937#if JOBS || DEBUG
3938static int
3939jobno(const struct job *jp)
3940{
3941        return jp - jobtab + 1;
3942}
3943#endif
3944
3945/*
3946 * Convert a job name to a job structure.
3947 */
3948#if !JOBS
3949#define getjob(name, getctl) getjob(name)
3950#endif
3951static struct job *
3952getjob(const char *name, int getctl)
3953{
3954        struct job *jp;
3955        struct job *found;
3956        const char *err_msg = "%s: no such job";
3957        unsigned num;
3958        int c;
3959        const char *p;
3960        char *(*match)(const char *, const char *);
3961
3962        jp = curjob;
3963        p = name;
3964        if (!p)
3965                goto currentjob;
3966
3967        if (*p != '%')
3968                goto err;
3969
3970        c = *++p;
3971        if (!c)
3972                goto currentjob;
3973
3974        if (!p[1]) {
3975                if (c == '+' || c == '%') {
3976 currentjob:
3977                        err_msg = "No current job";
3978                        goto check;
3979                }
3980                if (c == '-') {
3981                        if (jp)
3982                                jp = jp->prev_job;
3983                        err_msg = "No previous job";
3984 check:
3985                        if (!jp)
3986                                goto err;
3987                        goto gotit;
3988                }
3989        }
3990
3991        if (is_number(p)) {
3992                num = atoi(p);
3993                if (num > 0 && num <= njobs) {
3994                        jp = jobtab + num - 1;
3995                        if (jp->used)
3996                                goto gotit;
3997                        goto err;
3998                }
3999        }
4000
4001        match = prefix;
4002        if (*p == '?') {
4003                match = strstr;
4004                p++;
4005        }
4006
4007        found = NULL;
4008        while (jp) {
4009                if (match(jp->ps[0].ps_cmd, p)) {
4010                        if (found)
4011                                goto err;
4012                        found = jp;
4013                        err_msg = "%s: ambiguous";
4014                }
4015                jp = jp->prev_job;
4016        }
4017        if (!found)
4018                goto err;
4019        jp = found;
4020
4021 gotit:
4022#if JOBS
4023        err_msg = "job %s not created under job control";
4024        if (getctl && jp->jobctl == 0)
4025                goto err;
4026#endif
4027        return jp;
4028 err:
4029        ash_msg_and_raise_error(err_msg, name);
4030}
4031
4032/*
4033 * Mark a job structure as unused.
4034 */
4035static void
4036freejob(struct job *jp)
4037{
4038        struct procstat *ps;
4039        int i;
4040
4041        INT_OFF;
4042        for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
4043                if (ps->ps_cmd != nullstr)
4044                        free(ps->ps_cmd);
4045        }
4046        if (jp->ps != &jp->ps0)
4047                free(jp->ps);
4048        jp->used = 0;
4049        set_curjob(jp, CUR_DELETE);
4050        INT_ON;
4051}
4052
4053#if JOBS
4054static void
4055xtcsetpgrp(int fd, pid_t pgrp)
4056{
4057        if (tcsetpgrp(fd, pgrp))
4058                ash_msg_and_raise_perror("can't set tty process group");
4059}
4060
4061/*
4062 * Turn job control on and off.
4063 *
4064 * Note:  This code assumes that the third arg to ioctl is a character
4065 * pointer, which is true on Berkeley systems but not System V.  Since
4066 * System V doesn't have job control yet, this isn't a problem now.
4067 *
4068 * Called with interrupts off.
4069 */
4070static void
4071setjobctl(int on)
4072{
4073        int fd;
4074        int pgrp;
4075
4076        if (on == doing_jobctl || rootshell == 0)
4077                return;
4078        if (on) {
4079                int ofd;
4080                ofd = fd = open(_PATH_TTY, O_RDWR);
4081                if (fd < 0) {
4082        /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
4083         * That sometimes helps to acquire controlling tty.
4084         * Obviously, a workaround for bugs when someone
4085         * failed to provide a controlling tty to bash! :) */
4086                        fd = 2;
4087                        while (!isatty(fd))
4088                                if (--fd < 0)
4089                                        goto out;
4090                }
4091                /* fd is a tty at this point */
4092                fd = fcntl(fd, F_DUPFD_CLOEXEC, 10);
4093                if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
4094                        close(ofd);
4095                if (fd < 0)
4096                        goto out; /* F_DUPFD failed */
4097                if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
4098                        close_on_exec_on(fd);
4099                while (1) { /* while we are in the background */
4100                        pgrp = tcgetpgrp(fd);
4101                        if (pgrp < 0) {
4102 out:
4103                                ash_msg("can't access tty; job control turned off");
4104                                mflag = on = 0;
4105                                goto close;
4106                        }
4107                        if (pgrp == getpgrp())
4108                                break;
4109                        killpg(0, SIGTTIN);
4110                }
4111                initialpgrp = pgrp;
4112
4113                setsignal(SIGTSTP);
4114                setsignal(SIGTTOU);
4115                setsignal(SIGTTIN);
4116                pgrp = rootpid;
4117                setpgid(0, pgrp);
4118                xtcsetpgrp(fd, pgrp);
4119        } else {
4120                /* turning job control off */
4121                fd = ttyfd;
4122                pgrp = initialpgrp;
4123                /* was xtcsetpgrp, but this can make exiting ash
4124                 * loop forever if pty is already deleted */
4125                tcsetpgrp(fd, pgrp);
4126                setpgid(0, pgrp);
4127                setsignal(SIGTSTP);
4128                setsignal(SIGTTOU);
4129                setsignal(SIGTTIN);
4130 close:
4131                if (fd >= 0)
4132                        close(fd);
4133                fd = -1;
4134        }
4135        ttyfd = fd;
4136        doing_jobctl = on;
4137}
4138
4139static int FAST_FUNC
4140killcmd(int argc, char **argv)
4141{
4142        if (argv[1] && strcmp(argv[1], "-l") != 0) {
4143                int i = 1;
4144                do {
4145                        if (argv[i][0] == '%') {
4146                                /*
4147                                 * "kill %N" - job kill
4148                                 * Converting to pgrp / pid kill
4149                                 */
4150                                struct job *jp;
4151                                char *dst;
4152                                int j, n;
4153
4154                                jp = getjob(argv[i], 0);
4155                                /*
4156                                 * In jobs started under job control, we signal
4157                                 * entire process group by kill -PGRP_ID.
4158                                 * This happens, f.e., in interactive shell.
4159                                 *
4160                                 * Otherwise, we signal each child via
4161                                 * kill PID1 PID2 PID3.
4162                                 * Testcases:
4163                                 * sh -c 'sleep 1|sleep 1 & kill %1'
4164                                 * sh -c 'true|sleep 2 & sleep 1; kill %1'
4165                                 * sh -c 'true|sleep 1 & sleep 2; kill %1'
4166                                 */
4167                                n = jp->nprocs; /* can't be 0 (I hope) */
4168                                if (jp->jobctl)
4169                                        n = 1;
4170                                dst = alloca(n * sizeof(int)*4);
4171                                argv[i] = dst;
4172                                for (j = 0; j < n; j++) {
4173                                        struct procstat *ps = &jp->ps[j];
4174                                        /* Skip non-running and not-stopped members
4175                                         * (i.e. dead members) of the job
4176                                         */
4177                                        if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
4178                                                continue;
4179                                        /*
4180                                         * kill_main has matching code to expect
4181                                         * leading space. Needed to not confuse
4182                                         * negative pids with "kill -SIGNAL_NO" syntax
4183                                         */
4184                                        dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
4185                                }
4186                                *dst = '\0';
4187                        }
4188                } while (argv[++i]);
4189        }
4190        return kill_main(argc, argv);
4191}
4192
4193static void
4194showpipe(struct job *jp /*, FILE *out*/)
4195{
4196        struct procstat *ps;
4197        struct procstat *psend;
4198
4199        psend = jp->ps + jp->nprocs;
4200        for (ps = jp->ps + 1; ps < psend; ps++)
4201                printf(" | %s", ps->ps_cmd);
4202        newline_and_flush(stdout);
4203        flush_stdout_stderr();
4204}
4205
4206
4207static int
4208restartjob(struct job *jp, int mode)
4209{
4210        struct procstat *ps;
4211        int i;
4212        int status;
4213        pid_t pgid;
4214
4215        INT_OFF;
4216        if (jp->state == JOBDONE)
4217                goto out;
4218        jp->state = JOBRUNNING;
4219        pgid = jp->ps[0].ps_pid;
4220        if (mode == FORK_FG) {
4221                get_tty_state();
4222                xtcsetpgrp(ttyfd, pgid);
4223        }
4224        killpg(pgid, SIGCONT);
4225        ps = jp->ps;
4226        i = jp->nprocs;
4227        do {
4228                if (WIFSTOPPED(ps->ps_status)) {
4229                        ps->ps_status = -1;
4230                }
4231                ps++;
4232        } while (--i);
4233 out:
4234        status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4235        INT_ON;
4236        return status;
4237}
4238
4239static int FAST_FUNC
4240fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4241{
4242        struct job *jp;
4243        int mode;
4244        int retval;
4245
4246        mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4247        nextopt(nullstr);
4248        argv = argptr;
4249        do {
4250                jp = getjob(*argv, 1);
4251                if (mode == FORK_BG) {
4252                        set_curjob(jp, CUR_RUNNING);
4253                        printf("[%d] ", jobno(jp));
4254                }
4255                out1str(jp->ps[0].ps_cmd);
4256                showpipe(jp /*, stdout*/);
4257                retval = restartjob(jp, mode);
4258        } while (*argv && *++argv);
4259        return retval;
4260}
4261#endif
4262
4263static int
4264sprint_status48(char *os, int status, int sigonly)
4265{
4266        char *s = os;
4267        int st;
4268
4269        if (!WIFEXITED(status)) {
4270#if JOBS
4271                if (WIFSTOPPED(status))
4272                        st = WSTOPSIG(status);
4273                else
4274#endif
4275                        st = WTERMSIG(status);
4276                if (sigonly) {
4277                        if (st == SIGINT || st == SIGPIPE)
4278                                goto out;
4279#if JOBS
4280                        if (WIFSTOPPED(status))
4281                                goto out;
4282#endif
4283                }
4284                st &= 0x7f;
4285                s = stpncpy(s, strsignal(st), 32);
4286                if (WCOREDUMP(status)) {
4287                        s = stpcpy(s, " (core dumped)");
4288                }
4289        } else if (!sigonly) {
4290                st = WEXITSTATUS(status);
4291                s += fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4292        }
4293 out:
4294        return s - os;
4295}
4296
4297#define DOWAIT_NONBLOCK 0
4298#define DOWAIT_BLOCK    1
4299#define DOWAIT_BLOCK_OR_SIG 2
4300#if BASH_WAIT_N
4301# define DOWAIT_JOBSTATUS 0x10   /* OR this to get job's exitstatus instead of pid */
4302#endif
4303
4304static int
4305waitproc(int block, int *status)
4306{
4307        sigset_t oldmask;
4308        int flags = block == DOWAIT_BLOCK ? 0 : WNOHANG;
4309        int err;
4310
4311#if JOBS
4312        if (doing_jobctl)
4313                flags |= WUNTRACED;
4314#endif
4315
4316        do {
4317                got_sigchld = 0;
4318                do
4319                        err = waitpid(-1, status, flags);
4320                while (err < 0 && errno == EINTR);
4321
4322                if (err || (err = -!block))
4323                        break;
4324
4325                sigfillset(&oldmask);
4326                sigprocmask2(SIG_SETMASK, &oldmask); /* mask is updated */
4327                while (!got_sigchld && !pending_sig)
4328                        sigsuspend(&oldmask);
4329                sigprocmask(SIG_SETMASK, &oldmask, NULL);
4330                //simpler, but unsafe: a signal can set pending_sig after check, but before pause():
4331                //while (!got_sigchld && !pending_sig)
4332                //      pause();
4333
4334        } while (got_sigchld);
4335
4336        return err;
4337}
4338
4339static int
4340waitone(int block, struct job *job)
4341{
4342        int pid;
4343        int status;
4344        struct job *jp;
4345        struct job *thisjob = NULL;
4346#if BASH_WAIT_N
4347        bool want_jobexitstatus = (block & DOWAIT_JOBSTATUS);
4348        block = (block & ~DOWAIT_JOBSTATUS);
4349#endif
4350
4351        TRACE(("dowait(0x%x) called\n", block));
4352
4353        /* It's wrong to call waitpid() outside of INT_OFF region:
4354         * signal can arrive just after syscall return and handler can
4355         * longjmp away, losing stop/exit notification processing.
4356         * Thus, for "jobs" builtin, and for waiting for a fg job,
4357         * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4358         *
4359         * However, for "wait" builtin it is wrong to simply call waitpid()
4360         * in INT_OFF region: "wait" needs to wait for any running job
4361         * to change state, but should exit on any trap too.
4362         * In INT_OFF region, a signal just before syscall entry can set
4363         * pending_sig variables, but we can't check them, and we would
4364         * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4365         *
4366         * Because of this, we run inside INT_OFF, but use a special routine
4367         * which combines waitpid() and sigsuspend().
4368         * This is the reason why we need to have a handler for SIGCHLD:
4369         * SIG_DFL handler does not wake sigsuspend().
4370         */
4371        INT_OFF;
4372        pid = waitproc(block, &status);
4373        TRACE(("wait returns pid %d, status=%d\n", pid, status));
4374        if (pid <= 0)
4375                goto out;
4376
4377        for (jp = curjob; jp; jp = jp->prev_job) {
4378                int jobstate;
4379                struct procstat *ps;
4380                struct procstat *psend;
4381                if (jp->state == JOBDONE)
4382                        continue;
4383                jobstate = JOBDONE;
4384                ps = jp->ps;
4385                psend = ps + jp->nprocs;
4386                do {
4387                        if (ps->ps_pid == pid) {
4388                                TRACE(("Job %d: changing status of proc %d "
4389                                        "from 0x%x to 0x%x\n",
4390                                        jobno(jp), pid, ps->ps_status, status));
4391                                ps->ps_status = status;
4392                                thisjob = jp;
4393                        }
4394                        if (ps->ps_status == -1)
4395                                jobstate = JOBRUNNING;
4396#if JOBS
4397                        if (jobstate == JOBRUNNING)
4398                                continue;
4399                        if (WIFSTOPPED(ps->ps_status)) {
4400                                jp->stopstatus = ps->ps_status;
4401                                jobstate = JOBSTOPPED;
4402                        }
4403#endif
4404                } while (++ps < psend);
4405                if (!thisjob)
4406                        continue;
4407
4408                /* Found the job where one of its processes changed its state.
4409                 * Is there at least one live and running process in this job? */
4410                if (jobstate != JOBRUNNING) {
4411                        /* No. All live processes in the job are stopped
4412                         * (JOBSTOPPED) or there are no live processes (JOBDONE)
4413                         */
4414                        thisjob->changed = 1;
4415                        if (thisjob->state != jobstate) {
4416                                TRACE(("Job %d: changing state from %d to %d\n",
4417                                        jobno(thisjob), thisjob->state, jobstate));
4418                                thisjob->state = jobstate;
4419#if JOBS
4420                                if (jobstate == JOBSTOPPED)
4421                                        set_curjob(thisjob, CUR_STOPPED);
4422#endif
4423                        }
4424                }
4425                goto out;
4426        }
4427        /* The process wasn't found in job list */
4428 out:
4429        INT_ON;
4430
4431#if BASH_WAIT_N
4432        if (want_jobexitstatus) {
4433                pid = -1;
4434                if (thisjob && thisjob->state == JOBDONE)
4435                        pid = thisjob->ps[thisjob->nprocs - 1].ps_status;
4436        }
4437#endif
4438        if (thisjob && thisjob == job) {
4439                char s[48 + 1];
4440                int len;
4441
4442                len = sprint_status48(s, status, 1);
4443                if (len) {
4444                        s[len] = '\n';
4445                        s[len + 1] = '\0';
4446                        out2str(s);
4447                }
4448        }
4449        return pid;
4450}
4451
4452static int
4453dowait(int block, struct job *jp)
4454{
4455        smallint gotchld = *(volatile smallint *)&got_sigchld;
4456        int rpid;
4457        int pid;
4458
4459        if (jp && jp->state != JOBRUNNING)
4460                block = DOWAIT_NONBLOCK;
4461
4462        if (block == DOWAIT_NONBLOCK && !gotchld)
4463                return 1;
4464
4465        rpid = 1;
4466
4467        do {
4468                pid = waitone(block, jp);
4469                rpid &= !!pid;
4470
4471                if (!pid || (jp && jp->state != JOBRUNNING))
4472                        block = DOWAIT_NONBLOCK;
4473        } while (pid >= 0);
4474
4475        return rpid;
4476}
4477
4478#if JOBS
4479static void
4480showjob(struct job *jp, int mode)
4481{
4482        struct procstat *ps;
4483        struct procstat *psend;
4484        int col;
4485        int indent_col;
4486        char s[16 + 16 + 48];
4487        FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4488
4489        ps = jp->ps;
4490
4491        if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4492                /* just output process (group) id of pipeline */
4493                fprintf(out, "%d\n", ps->ps_pid);
4494                return;
4495        }
4496
4497        col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4498        indent_col = col;
4499
4500        if (jp == curjob)
4501                s[col - 3] = '+';
4502        else if (curjob && jp == curjob->prev_job)
4503                s[col - 3] = '-';
4504
4505        if (mode & SHOW_PIDS)
4506                col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4507
4508        psend = ps + jp->nprocs;
4509
4510        if (jp->state == JOBRUNNING) {
4511                strcpy(s + col, "Running");
4512                col += sizeof("Running") - 1;
4513        } else {
4514                int status = psend[-1].ps_status;
4515                if (jp->state == JOBSTOPPED)
4516                        status = jp->stopstatus;
4517                col += sprint_status48(s + col, status, 0);
4518        }
4519        /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4520
4521        /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4522         * or prints several "PID             | <cmdN>" lines,
4523         * depending on SHOW_PIDS bit.
4524         * We do not print status of individual processes
4525         * between PID and <cmdN>. bash does it, but not very well:
4526         * first line shows overall job status, not process status,
4527         * making it impossible to know 1st process status.
4528         */
4529        goto start;
4530        do {
4531                /* for each process */
4532                s[0] = '\0';
4533                col = 33;
4534                if (mode & SHOW_PIDS)
4535                        col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4536 start:
4537                fprintf(out, "%s%*c%s%s",
4538                                s,
4539                                33 - col >= 0 ? 33 - col : 0, ' ',
4540                                ps == jp->ps ? "" : "| ",
4541                                ps->ps_cmd
4542                );
4543        } while (++ps != psend);
4544        newline_and_flush(out);
4545
4546        jp->changed = 0;
4547
4548        if (jp->state == JOBDONE) {
4549                TRACE(("showjob: freeing job %d\n", jobno(jp)));
4550                freejob(jp);
4551        }
4552}
4553
4554/*
4555 * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4556 * statuses have changed since the last call to showjobs.
4557 */
4558static void
4559showjobs(int mode)
4560{
4561        struct job *jp;
4562
4563        TRACE(("showjobs(0x%x) called\n", mode));
4564
4565        /* Handle all finished jobs */
4566        dowait(DOWAIT_NONBLOCK, NULL);
4567
4568        for (jp = curjob; jp; jp = jp->prev_job) {
4569                if (!(mode & SHOW_CHANGED) || jp->changed) {
4570                        showjob(jp, mode);
4571                }
4572        }
4573}
4574
4575static int FAST_FUNC
4576jobscmd(int argc UNUSED_PARAM, char **argv)
4577{
4578        int mode, m;
4579
4580        mode = 0;
4581        while ((m = nextopt("lp")) != '\0') {
4582                if (m == 'l')
4583                        mode |= SHOW_PIDS;
4584                else
4585                        mode |= SHOW_ONLY_PGID;
4586        }
4587
4588        argv = argptr;
4589        if (*argv) {
4590                do
4591                        showjob(getjob(*argv, 0), mode);
4592                while (*++argv);
4593        } else {
4594                showjobs(mode);
4595        }
4596
4597        return 0;
4598}
4599#endif /* JOBS */
4600
4601/* Called only on finished or stopped jobs (no members are running) */
4602static int
4603getstatus(struct job *job)
4604{
4605        int status;
4606        int retval;
4607        struct procstat *ps;
4608
4609        /* Fetch last member's status */
4610        ps = job->ps + job->nprocs - 1;
4611        status = ps->ps_status;
4612        if (pipefail) {
4613                /* "set -o pipefail" mode: use last _nonzero_ status */
4614                while (status == 0 && --ps >= job->ps)
4615                        status = ps->ps_status;
4616        }
4617
4618        retval = WEXITSTATUS(status);
4619        if (!WIFEXITED(status)) {
4620#if JOBS
4621                retval = WSTOPSIG(status);
4622                if (!WIFSTOPPED(status))
4623#endif
4624                {
4625                        /* XXX: limits number of signals */
4626                        retval = WTERMSIG(status);
4627#if JOBS
4628                        if (retval == SIGINT)
4629                                job->sigint = 1;
4630#endif
4631                }
4632                retval |= 128;
4633        }
4634        TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4635                jobno(job), job->nprocs, status, retval));
4636        return retval;
4637}
4638
4639static int FAST_FUNC
4640waitcmd(int argc UNUSED_PARAM, char **argv)
4641{
4642        struct job *job;
4643        int retval;
4644        struct job *jp;
4645#if BASH_WAIT_N
4646        int status;
4647        char one = nextopt("n");
4648#else
4649        nextopt(nullstr);
4650#endif
4651        retval = 0;
4652
4653        argv = argptr;
4654        if (!argv[0]) {
4655                /* wait for all jobs / one job if -n */
4656                for (;;) {
4657                        jp = curjob;
4658#if BASH_WAIT_N
4659                        if (one && !jp)
4660                                /* exitcode of "wait -n" with nothing to wait for is 127, not 0 */
4661                                retval = 127;
4662#endif
4663                        while (1) {
4664                                if (!jp) /* no running procs */
4665                                        goto ret;
4666                                if (jp->state == JOBRUNNING)
4667                                        break;
4668                                jp->waited = 1;
4669                                jp = jp->prev_job;
4670                        }
4671        /* man bash:
4672         * "When bash is waiting for an asynchronous command via
4673         * the wait builtin, the reception of a signal for which a trap
4674         * has been set will cause the wait builtin to return immediately
4675         * with an exit status greater than 128, immediately after which
4676         * the trap is executed."
4677         */
4678#if BASH_WAIT_N
4679                        status = dowait(DOWAIT_BLOCK_OR_SIG | DOWAIT_JOBSTATUS, NULL);
4680#else
4681                        dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4682#endif
4683                        /* if child sends us a signal *and immediately exits*,
4684                         * dowait() returns pid > 0. Check this case,
4685                         * not "if (dowait() < 0)"!
4686                         */
4687                        if (pending_sig)
4688                                goto sigout;
4689#if BASH_WAIT_N
4690                        if (one) {
4691                                /* wait -n waits for one _job_, not one _process_.
4692                                 *  date; sleep 3 & sleep 2 | sleep 1 & wait -n; date
4693                                 * should wait for 2 seconds. Not 1 or 3.
4694                                 */
4695                                if (status != -1 && !WIFSTOPPED(status)) {
4696                                        retval = WEXITSTATUS(status);
4697                                        if (WIFSIGNALED(status))
4698                                                retval = 128 | WTERMSIG(status);
4699                                        goto ret;
4700                                }
4701                        }
4702#endif
4703                }
4704        }
4705
4706        retval = 127;
4707        do {
4708                if (**argv != '%') {
4709                        pid_t pid = number(*argv);
4710                        job = curjob;
4711                        while (1) {
4712                                if (!job)
4713                                        goto repeat;
4714                                if (job->ps[job->nprocs - 1].ps_pid == pid)
4715                                        break;
4716                                job = job->prev_job;
4717                        }
4718                } else {
4719                        job = getjob(*argv, 0);
4720                }
4721                /* loop until process terminated or stopped */
4722                dowait(DOWAIT_BLOCK_OR_SIG, job);
4723                if (pending_sig)
4724                        goto sigout;
4725                job->waited = 1;
4726                retval = getstatus(job);
4727 repeat: ;
4728        } while (*++argv);
4729
4730 ret:
4731        return retval;
4732 sigout:
4733        retval = 128 | pending_sig;
4734        return retval;
4735}
4736
4737static struct job *
4738growjobtab(void)
4739{
4740        size_t len;
4741        ptrdiff_t offset;
4742        struct job *jp, *jq;
4743
4744        len = njobs * sizeof(*jp);
4745        jq = jobtab;
4746        jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4747
4748        offset = (char *)jp - (char *)jq;
4749        if (offset) {
4750                /* Relocate pointers */
4751                size_t l = len;
4752
4753                jq = (struct job *)((char *)jq + l);
4754                while (l) {
4755                        l -= sizeof(*jp);
4756                        jq--;
4757#define joff(p) ((struct job *)((char *)(p) + l))
4758#define jmove(p) (p) = (void *)((char *)(p) + offset)
4759                        if (joff(jp)->ps == &jq->ps0)
4760                                jmove(joff(jp)->ps);
4761                        if (joff(jp)->prev_job)
4762                                jmove(joff(jp)->prev_job);
4763                }
4764                if (curjob)
4765                        jmove(curjob);
4766#undef joff
4767#undef jmove
4768        }
4769
4770        njobs += 4;
4771        jobtab = jp;
4772        jp = (struct job *)((char *)jp + len);
4773        jq = jp + 3;
4774        do {
4775                jq->used = 0;
4776        } while (--jq >= jp);
4777        return jp;
4778}
4779
4780/*
4781 * Return a new job structure.
4782 * Called with interrupts off.
4783 */
4784static struct job *
4785makejob(/*union node *node,*/ int nprocs)
4786{
4787        int i;
4788        struct job *jp;
4789
4790        for (i = njobs, jp = jobtab; ; jp++) {
4791                if (--i < 0) {
4792                        jp = growjobtab();
4793                        break;
4794                }
4795                if (jp->used == 0)
4796                        break;
4797                if (jp->state != JOBDONE || !jp->waited)
4798                        continue;
4799#if JOBS
4800                if (doing_jobctl)
4801                        continue;
4802#endif
4803                freejob(jp);
4804                break;
4805        }
4806        memset(jp, 0, sizeof(*jp));
4807#if JOBS
4808        /* jp->jobctl is a bitfield.
4809         * "jp->jobctl |= doing_jobctl" likely to give awful code */
4810        if (doing_jobctl)
4811                jp->jobctl = 1;
4812#endif
4813        jp->prev_job = curjob;
4814        curjob = jp;
4815        jp->used = 1;
4816        jp->ps = &jp->ps0;
4817        if (nprocs > 1) {
4818                jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4819        }
4820        TRACE(("makejob(%d) returns %%%d\n", nprocs,
4821                                jobno(jp)));
4822        return jp;
4823}
4824
4825#if JOBS
4826/*
4827 * Return a string identifying a command (to be printed by the
4828 * jobs command).
4829 */
4830static char *cmdnextc;
4831
4832static void
4833cmdputs(const char *s)
4834{
4835        static const char vstype[VSTYPE + 1][3] ALIGN1 = {
4836                "", "}", "-", "+", "?", "=",
4837                "%", "%%", "#", "##"
4838                IF_BASH_SUBSTR(, ":")
4839                IF_BASH_PATTERN_SUBST(, "/", "//")
4840        };
4841
4842        const char *p, *str;
4843        char cc[2];
4844        char *nextc;
4845        unsigned char c;
4846        unsigned char subtype = 0;
4847        int quoted = 0;
4848
4849        cc[1] = '\0';
4850        nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4851        p = s;
4852        while ((c = *p++) != '\0') {
4853                str = NULL;
4854                switch (c) {
4855                case CTLESC:
4856                        c = *p++;
4857                        break;
4858                case CTLVAR:
4859                        subtype = *p++;
4860                        if ((subtype & VSTYPE) == VSLENGTH)
4861                                str = "${#";
4862                        else
4863                                str = "${";
4864                        goto dostr;
4865                case CTLENDVAR:
4866                        str = "\"}";
4867                        str += !(quoted & 1);
4868                        quoted >>= 1;
4869                        subtype = 0;
4870                        goto dostr;
4871#if BASH_PROCESS_SUBST
4872                case CTLBACKQ:
4873                        c = '$';
4874                        str = "(...)";
4875                        break;
4876                case CTLTOPROC:
4877                        c = '>';
4878                        str = "(...)";
4879                        break;
4880                case CTLFROMPROC:
4881                        c = '<';
4882                        str = "(...)";
4883                        break;
4884#else
4885                case CTLBACKQ:
4886                        str = "$(...)";
4887                        goto dostr;
4888#endif
4889#if ENABLE_FEATURE_SH_MATH
4890                case CTLARI:
4891                        str = "$((";
4892                        goto dostr;
4893                case CTLENDARI:
4894                        str = "))";
4895                        goto dostr;
4896#endif
4897                case CTLQUOTEMARK:
4898                        quoted ^= 1;
4899                        c = '"';
4900                        break;
4901                case '=':
4902                        if (subtype == 0)
4903                                break;
4904                        if ((subtype & VSTYPE) != VSNORMAL)
4905                                quoted <<= 1;
4906                        str = vstype[subtype & VSTYPE];
4907                        if (subtype & VSNUL)
4908                                c = ':';
4909                        else
4910                                goto checkstr;
4911                        break;
4912                case '\'':
4913                case '\\':
4914                case '"':
4915                case '$':
4916                        /* These can only happen inside quotes */
4917                        cc[0] = c;
4918                        str = cc;
4919//FIXME:
4920// $ true $$ &
4921// $ <cr>
4922// [1]+  Done    true ${\$}   <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4923                        c = '\\';
4924                        break;
4925                default:
4926                        break;
4927                }
4928                USTPUTC(c, nextc);
4929 checkstr:
4930                if (!str)
4931                        continue;
4932 dostr:
4933                while ((c = *str++) != '\0') {
4934                        USTPUTC(c, nextc);
4935                }
4936        } /* while *p++ not NUL */
4937
4938        if (quoted & 1) {
4939                USTPUTC('"', nextc);
4940        }
4941        *nextc = 0;
4942        cmdnextc = nextc;
4943}
4944
4945/* cmdtxt() and cmdlist() call each other */
4946static void cmdtxt(union node *n);
4947
4948static void
4949cmdlist(union node *np, int sep)
4950{
4951        for (; np; np = np->narg.next) {
4952                if (!sep)
4953                        cmdputs(" ");
4954                cmdtxt(np);
4955                if (sep && np->narg.next)
4956                        cmdputs(" ");
4957        }
4958}
4959
4960static void
4961cmdtxt(union node *n)
4962{
4963        union node *np;
4964        struct nodelist *lp;
4965        const char *p;
4966
4967        if (!n)
4968                return;
4969        switch (n->type) {
4970        default:
4971#if DEBUG
4972                abort();
4973#endif
4974        case NPIPE:
4975                lp = n->npipe.cmdlist;
4976                for (;;) {
4977                        cmdtxt(lp->n);
4978                        lp = lp->next;
4979                        if (!lp)
4980                                break;
4981                        cmdputs(" | ");
4982                }
4983                break;
4984        case NSEMI:
4985                p = "; ";
4986                goto binop;
4987        case NAND:
4988                p = " && ";
4989                goto binop;
4990        case NOR:
4991                p = " || ";
4992 binop:
4993                cmdtxt(n->nbinary.ch1);
4994                cmdputs(p);
4995                n = n->nbinary.ch2;
4996                goto donode;
4997        case NREDIR:
4998        case NBACKGND:
4999                n = n->nredir.n;
5000                goto donode;
5001        case NNOT:
5002                cmdputs("!");
5003                n = n->nnot.com;
5004 donode:
5005                cmdtxt(n);
5006                break;
5007        case NIF:
5008                cmdputs("if ");
5009                cmdtxt(n->nif.test);
5010                cmdputs("; then ");
5011                if (n->nif.elsepart) {
5012                        cmdtxt(n->nif.ifpart);
5013                        cmdputs("; else ");
5014                        n = n->nif.elsepart;
5015                } else {
5016                        n = n->nif.ifpart;
5017                }
5018                p = "; fi";
5019                goto dotail;
5020        case NSUBSHELL:
5021                cmdputs("(");
5022                n = n->nredir.n;
5023                p = ")";
5024                goto dotail;
5025        case NWHILE:
5026                p = "while ";
5027                goto until;
5028        case NUNTIL:
5029                p = "until ";
5030 until:
5031                cmdputs(p);
5032                cmdtxt(n->nbinary.ch1);
5033                n = n->nbinary.ch2;
5034                p = "; done";
5035 dodo:
5036                cmdputs("; do ");
5037 dotail:
5038                cmdtxt(n);
5039                goto dotail2;
5040        case NFOR:
5041                cmdputs("for ");
5042                cmdputs(n->nfor.var);
5043                cmdputs(" in ");
5044                cmdlist(n->nfor.args, 1);
5045                n = n->nfor.body;
5046                p = "; done";
5047                goto dodo;
5048        case NDEFUN:
5049                cmdputs(n->ndefun.text);
5050                p = "() { ... }";
5051                goto dotail2;
5052        case NCMD:
5053                cmdlist(n->ncmd.args, 1);
5054                cmdlist(n->ncmd.redirect, 0);
5055                break;
5056        case NARG:
5057                p = n->narg.text;
5058 dotail2:
5059                cmdputs(p);
5060                break;
5061        case NHERE:
5062        case NXHERE:
5063                p = "<<...";
5064                goto dotail2;
5065        case NCASE:
5066                cmdputs("case ");
5067                cmdputs(n->ncase.expr->narg.text);
5068                cmdputs(" in ");
5069                for (np = n->ncase.cases; np; np = np->nclist.next) {
5070                        cmdtxt(np->nclist.pattern);
5071                        cmdputs(") ");
5072                        cmdtxt(np->nclist.body);
5073                        cmdputs(";; ");
5074                }
5075                p = "esac";
5076                goto dotail2;
5077        case NTO:
5078                p = ">";
5079                goto redir;
5080        case NCLOBBER:
5081                p = ">|";
5082                goto redir;
5083        case NAPPEND:
5084                p = ">>";
5085                goto redir;
5086#if BASH_REDIR_OUTPUT
5087        case NTO2:
5088#endif
5089        case NTOFD:
5090                p = ">&";
5091                goto redir;
5092        case NFROM:
5093                p = "<";
5094                goto redir;
5095        case NFROMFD:
5096                p = "<&";
5097                goto redir;
5098        case NFROMTO:
5099                p = "<>";
5100 redir:
5101                cmdputs(utoa(n->nfile.fd));
5102                cmdputs(p);
5103                if (n->type == NTOFD || n->type == NFROMFD) {
5104                        if (n->ndup.dupfd >= 0)
5105                                cmdputs(utoa(n->ndup.dupfd));
5106                        else
5107                                cmdputs("-");
5108                        break;
5109                }
5110                n = n->nfile.fname;
5111                goto donode;
5112        }
5113}
5114
5115static char *
5116commandtext(union node *n)
5117{
5118        char *name;
5119
5120        STARTSTACKSTR(cmdnextc);
5121        cmdtxt(n);
5122        name = stackblock();
5123        TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
5124        return ckstrdup(name);
5125}
5126#endif /* JOBS */
5127
5128/*
5129 * Fork off a subshell.  If we are doing job control, give the subshell its
5130 * own process group.  Jp is a job structure that the job is to be added to.
5131 * N is the command that will be evaluated by the child.  Both jp and n may
5132 * be NULL.  The mode parameter can be one of the following:
5133 *      FORK_FG - Fork off a foreground process.
5134 *      FORK_BG - Fork off a background process.
5135 *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
5136 *                   process group even if job control is on.
5137 *
5138 * When job control is turned off, background processes have their standard
5139 * input redirected to /dev/null (except for the second and later processes
5140 * in a pipeline).
5141 *
5142 * Called with interrupts off.
5143 */
5144/*
5145 * Clear traps on a fork.
5146 */
5147static void
5148clear_traps(void)
5149{
5150        char **tp;
5151
5152        INT_OFF;
5153        for (tp = trap; tp <= &trap[NTRAP_LAST]; tp++) {
5154                if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
5155                        if (trap_ptr == trap)
5156                                free(*tp);
5157                        /* else: it "belongs" to trap_ptr vector, don't free */
5158                        *tp = NULL;
5159                        if ((tp - trap) != 0 && (tp - trap) < NSIG)
5160                                setsignal(tp - trap);
5161                }
5162        }
5163        may_have_traps = 0;
5164        INT_ON;
5165}
5166
5167/* Lives far away from here, needed for forkchild */
5168static void closescript(void);
5169
5170/* Called after fork(), in child */
5171/* jp and n are NULL when called by openhere() for heredoc support */
5172static NOINLINE void
5173forkchild(struct job *jp, union node *n, int mode)
5174{
5175        int oldlvl;
5176
5177        TRACE(("Child shell %d\n", getpid()));
5178        oldlvl = shlvl;
5179        shlvl++;
5180
5181        /* man bash: "Non-builtin commands run by bash have signal handlers
5182         * set to the values inherited by the shell from its parent".
5183         * Do we do it correctly? */
5184
5185        closescript();
5186
5187        if (mode == FORK_NOJOB          /* is it `xxx` ? */
5188         && n && n->type == NCMD        /* is it single cmd? */
5189        /* && n->ncmd.args->type == NARG - always true? */
5190         && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
5191         && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
5192        /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
5193        ) {
5194                TRACE(("Trap hack\n"));
5195                /* Awful hack for `trap` or $(trap).
5196                 *
5197                 * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
5198                 * contains an example where "trap" is executed in a subshell:
5199                 *
5200                 * save_traps=$(trap)
5201                 * ...
5202                 * eval "$save_traps"
5203                 *
5204                 * Standard does not say that "trap" in subshell shall print
5205                 * parent shell's traps. It only says that its output
5206                 * must have suitable form, but then, in the above example
5207                 * (which is not supposed to be normative), it implies that.
5208                 *
5209                 * bash (and probably other shell) does implement it
5210                 * (traps are reset to defaults, but "trap" still shows them),
5211                 * but as a result, "trap" logic is hopelessly messed up:
5212                 *
5213                 * # trap
5214                 * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
5215                 * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
5216                 * # true | trap   <--- trap is in subshell - no output (ditto)
5217                 * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
5218                 * trap -- 'echo Ho' SIGWINCH
5219                 * # echo `(trap)`         <--- in subshell in subshell - output
5220                 * trap -- 'echo Ho' SIGWINCH
5221                 * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
5222                 * trap -- 'echo Ho' SIGWINCH
5223                 *
5224                 * The rules when to forget and when to not forget traps
5225                 * get really complex and nonsensical.
5226                 *
5227                 * Our solution: ONLY bare $(trap) or `trap` is special.
5228                 */
5229                /* Save trap handler strings for trap builtin to print */
5230                trap_ptr = xmemdup(trap, sizeof(trap));
5231                /* Fall through into clearing traps */
5232        }
5233        clear_traps();
5234#if JOBS
5235        /* do job control only in root shell */
5236        doing_jobctl = 0;
5237        if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
5238                pid_t pgrp;
5239
5240                if (jp->nprocs == 0)
5241                        pgrp = getpid();
5242                else
5243                        pgrp = jp->ps[0].ps_pid;
5244                /* this can fail because we are doing it in the parent also */
5245                setpgid(0, pgrp);
5246                if (mode == FORK_FG)
5247                        xtcsetpgrp(ttyfd, pgrp);
5248                setsignal(SIGTSTP);
5249                setsignal(SIGTTOU);
5250        } else
5251#endif
5252        if (mode == FORK_BG) {
5253                /* man bash: "When job control is not in effect,
5254                 * asynchronous commands ignore SIGINT and SIGQUIT" */
5255                ignoresig(SIGINT);
5256                ignoresig(SIGQUIT);
5257                if (jp->nprocs == 0) {
5258                        close(0);
5259                        if (open(bb_dev_null, O_RDONLY) != 0)
5260                                ash_msg_and_raise_perror("can't open '%s'", bb_dev_null);
5261                }
5262        }
5263        if (oldlvl == 0) {
5264                if (iflag) { /* why if iflag only? */
5265                        setsignal(SIGINT);
5266                        setsignal(SIGTERM);
5267                }
5268                /* man bash:
5269                 * "In all cases, bash ignores SIGQUIT. Non-builtin
5270                 * commands run by bash have signal handlers
5271                 * set to the values inherited by the shell
5272                 * from its parent".
5273                 * Take care of the second rule: */
5274                setsignal(SIGQUIT);
5275        }
5276#if JOBS
5277        if (n && n->type == NCMD
5278         && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5279        ) {
5280                TRACE(("Job hack\n"));
5281                /* "jobs": we do not want to clear job list for it,
5282                 * instead we remove only _its_ own_ job from job list.
5283                 * This makes "jobs .... | cat" more useful.
5284                 */
5285                freejob(curjob);
5286                return;
5287        }
5288#endif
5289        for (jp = curjob; jp; jp = jp->prev_job)
5290                freejob(jp);
5291}
5292
5293/* Called after fork(), in parent */
5294#if !JOBS
5295#define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5296#endif
5297static void
5298forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5299{
5300        TRACE(("In parent shell: child = %d\n", pid));
5301        if (!jp) /* jp is NULL when called by openhere() for heredoc support */
5302                return;
5303#if JOBS
5304        if (mode != FORK_NOJOB && jp->jobctl) {
5305                int pgrp;
5306
5307                if (jp->nprocs == 0)
5308                        pgrp = pid;
5309                else
5310                        pgrp = jp->ps[0].ps_pid;
5311                /* This can fail because we are doing it in the child also */
5312                setpgid(pid, pgrp);
5313        }
5314#endif
5315        if (mode == FORK_BG) {
5316                backgndpid = pid;               /* set $! */
5317                set_curjob(jp, CUR_RUNNING);
5318        }
5319        if (jp) {
5320                struct procstat *ps = &jp->ps[jp->nprocs++];
5321                ps->ps_pid = pid;
5322                ps->ps_status = -1;
5323                ps->ps_cmd = nullstr;
5324#if JOBS
5325                if (doing_jobctl && n)
5326                        ps->ps_cmd = commandtext(n);
5327#endif
5328        }
5329}
5330
5331/* jp and n are NULL when called by openhere() for heredoc support */
5332static int
5333forkshell(struct job *jp, union node *n, int mode)
5334{
5335        int pid;
5336
5337        TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5338        pid = fork();
5339        if (pid < 0) {
5340                TRACE(("Fork failed, errno=%d", errno));
5341                if (jp)
5342                        freejob(jp);
5343                ash_msg_and_raise_perror("can't fork");
5344        }
5345        if (pid == 0) {
5346                CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5347                forkchild(jp, n, mode);
5348        } else {
5349                forkparent(jp, n, mode, pid);
5350        }
5351        return pid;
5352}
5353
5354/*
5355 * Wait for job to finish.
5356 *
5357 * Under job control we have the problem that while a child process
5358 * is running interrupts generated by the user are sent to the child
5359 * but not to the shell.  This means that an infinite loop started by
5360 * an interactive user may be hard to kill.  With job control turned off,
5361 * an interactive user may place an interactive program inside a loop.
5362 * If the interactive program catches interrupts, the user doesn't want
5363 * these interrupts to also abort the loop.  The approach we take here
5364 * is to have the shell ignore interrupt signals while waiting for a
5365 * foreground process to terminate, and then send itself an interrupt
5366 * signal if the child process was terminated by an interrupt signal.
5367 * Unfortunately, some programs want to do a bit of cleanup and then
5368 * exit on interrupt; unless these processes terminate themselves by
5369 * sending a signal to themselves (instead of calling exit) they will
5370 * confuse this approach.
5371 *
5372 * Called with interrupts off.
5373 */
5374static int
5375waitforjob(struct job *jp)
5376{
5377        int st;
5378
5379        TRACE(("waitforjob(%%%d) called\n", jp ? jobno(jp) : 0));
5380
5381        /* In non-interactive shells, we _can_ get
5382         * a keyboard signal here and be EINTRed, but we just loop
5383         * inside dowait(), waiting for command to complete.
5384         *
5385         * man bash:
5386         * "If bash is waiting for a command to complete and receives
5387         * a signal for which a trap has been set, the trap
5388         * will not be executed until the command completes."
5389         *
5390         * Reality is that even if trap is not set, bash
5391         * will not act on the signal until command completes.
5392         * Try this. sleep5intoff.c:
5393         * #include <signal.h>
5394         * #include <unistd.h>
5395         * int main() {
5396         *         sigset_t set;
5397         *         sigemptyset(&set);
5398         *         sigaddset(&set, SIGINT);
5399         *         sigaddset(&set, SIGQUIT);
5400         *         sigprocmask(SIG_BLOCK, &set, NULL);
5401         *         sleep(5);
5402         *         return 0;
5403         * }
5404         * $ bash -c './sleep5intoff; echo hi'
5405         * ^C^C^C^C <--- pressing ^C once a second
5406         * $ _
5407         * $ bash -c './sleep5intoff; echo hi'
5408         * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5409         * $ _
5410         */
5411        dowait(jp ? DOWAIT_BLOCK : DOWAIT_NONBLOCK, jp);
5412        if (!jp)
5413                return exitstatus;
5414
5415        st = getstatus(jp);
5416#if JOBS
5417        if (jp->jobctl) {
5418                xtcsetpgrp(ttyfd, rootpid);
5419                restore_tty_if_stopped_or_signaled(jp);
5420
5421                /*
5422                 * This is truly gross.
5423                 * If we're doing job control, then we did a TIOCSPGRP which
5424                 * caused us (the shell) to no longer be in the controlling
5425                 * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5426                 * intuit from the subprocess exit status whether a SIGINT
5427                 * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5428                 */
5429                if (jp->sigint) /* TODO: do the same with all signals */
5430                        raise(SIGINT); /* ... by raise(jp->sig) instead? */
5431        }
5432        if (jp->state == JOBDONE)
5433#endif
5434                freejob(jp);
5435        return st;
5436}
5437
5438/*
5439 * return 1 if there are stopped jobs, otherwise 0
5440 */
5441static int
5442stoppedjobs(void)
5443{
5444        struct job *jp;
5445        int retval;
5446
5447        retval = 0;
5448        if (!iflag || job_warning)
5449                goto out;
5450        jp = curjob;
5451        if (jp && jp->state == JOBSTOPPED) {
5452                out2str("You have stopped jobs.\n");
5453                job_warning = 2;
5454                retval++;
5455        }
5456 out:
5457        return retval;
5458}
5459
5460
5461/*
5462 * Code for dealing with input/output redirection.
5463 */
5464
5465#undef EMPTY
5466#undef CLOSED
5467#define EMPTY -2                /* marks an unused slot in redirtab */
5468#define CLOSED -1               /* marks a slot of previously-closed fd */
5469
5470/*
5471 * Handle here documents.  Normally we fork off a process to write the
5472 * data to a pipe.  If the document is short, we can stuff the data in
5473 * the pipe without forking.
5474 */
5475/* openhere needs this forward reference */
5476static void expandhere(union node *arg);
5477static int
5478openhere(union node *redir)
5479{
5480        char *p;
5481        int pip[2];
5482        size_t len = 0;
5483
5484        if (pipe(pip) < 0)
5485                ash_msg_and_raise_perror("can't create pipe");
5486
5487        p = redir->nhere.doc->narg.text;
5488        if (redir->type == NXHERE) {
5489                expandhere(redir->nhere.doc);
5490                p = stackblock();
5491        }
5492
5493        len = strlen(p);
5494        if (len <= PIPE_BUF) {
5495                xwrite(pip[1], p, len);
5496                goto out;
5497        }
5498
5499        if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5500                /* child */
5501                close(pip[0]);
5502                ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5503                ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5504                ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5505                ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5506                signal(SIGPIPE, SIG_DFL);
5507                xwrite(pip[1], p, len);
5508                _exit(EXIT_SUCCESS);
5509        }
5510 out:
5511        close(pip[1]);
5512        return pip[0];
5513}
5514
5515static int
5516openredirect(union node *redir)
5517{
5518        struct stat sb;
5519        char *fname;
5520        int f;
5521
5522        switch (redir->nfile.type) {
5523/* Can't happen, our single caller does this itself */
5524//      case NTOFD:
5525//      case NFROMFD:
5526//              return -1;
5527        case NHERE:
5528        case NXHERE:
5529                return openhere(redir);
5530        }
5531
5532        /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5533         * allocated space. Do it only when we know it is safe.
5534         */
5535        fname = redir->nfile.expfname;
5536
5537        switch (redir->nfile.type) {
5538        default:
5539#if DEBUG
5540                abort();
5541#endif
5542        case NFROM:
5543                f = open(fname, O_RDONLY);
5544                if (f < 0)
5545                        goto eopen;
5546                break;
5547        case NFROMTO:
5548                f = open(fname, O_RDWR|O_CREAT, 0666);
5549                if (f < 0)
5550                        goto ecreate;
5551                break;
5552        case NTO:
5553#if BASH_REDIR_OUTPUT
5554        case NTO2:
5555#endif
5556                /* Take care of noclobber mode. */
5557                if (Cflag) {
5558                        if (stat(fname, &sb) < 0) {
5559                                f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5560                                if (f < 0)
5561                                        goto ecreate;
5562                        } else if (!S_ISREG(sb.st_mode)) {
5563                                f = open(fname, O_WRONLY, 0666);
5564                                if (f < 0)
5565                                        goto ecreate;
5566                                if (!fstat(f, &sb) && S_ISREG(sb.st_mode)) {
5567                                        close(f);
5568                                        errno = EEXIST;
5569                                        goto ecreate;
5570                                }
5571                        } else {
5572                                errno = EEXIST;
5573                                goto ecreate;
5574                        }
5575                        break;
5576                }
5577                /* FALLTHROUGH */
5578        case NCLOBBER:
5579                f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5580                if (f < 0)
5581                        goto ecreate;
5582                break;
5583        case NAPPEND:
5584                f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5585                if (f < 0)
5586                        goto ecreate;
5587                break;
5588        }
5589
5590        return f;
5591 ecreate:
5592        ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5593 eopen:
5594        ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5595}
5596
5597/*
5598 * Copy a file descriptor to be >= 10. Throws exception on error.
5599 */
5600static int
5601savefd(int from)
5602{
5603        int newfd;
5604        int err;
5605
5606        newfd = fcntl(from, F_DUPFD_CLOEXEC, 10);
5607        err = newfd < 0 ? errno : 0;
5608        if (err != EBADF) {
5609                if (err)
5610                        ash_msg_and_raise_perror("%d", from);
5611                close(from);
5612                if (F_DUPFD_CLOEXEC == F_DUPFD)
5613                        close_on_exec_on(newfd);
5614        }
5615
5616        return newfd;
5617}
5618static int
5619dup2_or_raise(int from, int to)
5620{
5621        int newfd;
5622
5623        newfd = (from != to) ? dup2(from, to) : to;
5624        if (newfd < 0) {
5625                /* Happens when source fd is not open: try "echo >&99" */
5626                ash_msg_and_raise_perror("%d", from);
5627        }
5628        return newfd;
5629}
5630static int
5631dup_CLOEXEC(int fd, int avoid_fd)
5632{
5633        int newfd;
5634 repeat:
5635        newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5636        if (newfd >= 0) {
5637                if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
5638                        close_on_exec_on(newfd);
5639        } else { /* newfd < 0 */
5640                if (errno == EBUSY)
5641                        goto repeat;
5642                if (errno == EINTR)
5643                        goto repeat;
5644        }
5645        return newfd;
5646}
5647static int
5648xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5649{
5650        int newfd;
5651 repeat:
5652        newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5653        if (newfd < 0) {
5654                if (errno == EBUSY)
5655                        goto repeat;
5656                if (errno == EINTR)
5657                        goto repeat;
5658                /* fd was not open? */
5659                if (errno == EBADF)
5660                        return fd;
5661                ash_msg_and_raise_perror("%d", newfd);
5662        }
5663        if (F_DUPFD_CLOEXEC == F_DUPFD)
5664                close_on_exec_on(newfd);
5665        close(fd);
5666        return newfd;
5667}
5668
5669/* Struct def and variable are moved down to the first usage site */
5670struct squirrel {
5671        int orig_fd;
5672        int moved_to;
5673};
5674struct redirtab {
5675        struct redirtab *next;
5676        int pair_count;
5677        struct squirrel two_fd[];
5678};
5679#define redirlist (G_var.redirlist)
5680
5681static void
5682add_squirrel_closed(struct redirtab *sq, int fd)
5683{
5684        int i;
5685
5686        if (!sq)
5687                return;
5688
5689        for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5690                /* If we collide with an already moved fd... */
5691                if (fd == sq->two_fd[i].orig_fd) {
5692                        /* Examples:
5693                         * "echo 3>FILE 3>&- 3>FILE"
5694                         * "echo 3>&- 3>FILE"
5695                         * No need for last redirect to insert
5696                         * another "need to close 3" indicator.
5697                         */
5698                        TRACE(("redirect_fd %d: already moved or closed\n", fd));
5699                        return;
5700                }
5701        }
5702        TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5703        sq->two_fd[i].orig_fd = fd;
5704        sq->two_fd[i].moved_to = CLOSED;
5705}
5706
5707static int
5708save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5709{
5710        int i, new_fd;
5711
5712        if (avoid_fd < 9) /* the important case here is that it can be -1 */
5713                avoid_fd = 9;
5714
5715#if JOBS
5716        if (fd == ttyfd) {
5717                /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5718                ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5719                TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5720                return 1; /* "we closed fd" */
5721        }
5722#endif
5723        /* Are we called from redirect(0)? E.g. redirect
5724         * in a forked child. No need to save fds,
5725         * we aren't going to use them anymore, ok to trash.
5726         */
5727        if (!sq)
5728                return 0;
5729
5730        /* If this one of script's fds? */
5731        if (fd != 0) {
5732                struct parsefile *pf = g_parsefile;
5733                while (pf) {
5734                        /* We skip fd == 0 case because of the following:
5735                         * $ ash  # running ash interactively
5736                         * $ . ./script.sh
5737                         * and in script.sh: "exec 9>&0".
5738                         * Even though top-level pf_fd _is_ 0,
5739                         * it's still ok to use it: "read" builtin uses it,
5740                         * why should we cripple "exec" builtin?
5741                         */
5742                        if (fd == pf->pf_fd) {
5743                                pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5744                                return 1; /* "we closed fd" */
5745                        }
5746                        pf = pf->prev;
5747                }
5748        }
5749
5750        /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5751
5752        /* First: do we collide with some already moved fds? */
5753        for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5754                /* If we collide with an already moved fd... */
5755                if (fd == sq->two_fd[i].moved_to) {
5756                        new_fd = dup_CLOEXEC(fd, avoid_fd);
5757                        sq->two_fd[i].moved_to = new_fd;
5758                        TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5759                        if (new_fd < 0) /* what? */
5760                                xfunc_die();
5761                        return 0; /* "we did not close fd" */
5762                }
5763                if (fd == sq->two_fd[i].orig_fd) {
5764                        /* Example: echo Hello >/dev/null 1>&2 */
5765                        TRACE(("redirect_fd %d: already moved\n", fd));
5766                        return 0; /* "we did not close fd" */
5767                }
5768        }
5769
5770        /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5771        new_fd = dup_CLOEXEC(fd, avoid_fd);
5772        TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5773        if (new_fd < 0) {
5774                if (errno != EBADF)
5775                        xfunc_die();
5776                /* new_fd = CLOSED; - already is -1 */
5777        }
5778        sq->two_fd[i].moved_to = new_fd;
5779        sq->two_fd[i].orig_fd = fd;
5780
5781        /* if we move stderr, let "set -x" code know */
5782        if (fd == preverrout_fd)
5783                preverrout_fd = new_fd;
5784
5785        return 0; /* "we did not close fd" */
5786}
5787
5788static int
5789internally_opened_fd(int fd, struct redirtab *sq)
5790{
5791        int i;
5792#if JOBS
5793        if (fd == ttyfd)
5794                return 1;
5795#endif
5796        /* If this one of script's fds? */
5797        if (fd != 0) {
5798                struct parsefile *pf = g_parsefile;
5799                while (pf) {
5800                        if (fd == pf->pf_fd)
5801                                return 1;
5802                        pf = pf->prev;
5803                }
5804        }
5805
5806        if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5807                if (fd == sq->two_fd[i].moved_to)
5808                        return 1;
5809        }
5810        return 0;
5811}
5812
5813/*
5814 * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5815 * old file descriptors are stashed away so that the redirection can be
5816 * undone by calling popredir.
5817 */
5818/* flags passed to redirect */
5819#define REDIR_PUSH    01        /* save previous values of file descriptors */
5820static void
5821redirect(union node *redir, int flags)
5822{
5823        struct redirtab *sv;
5824
5825        if (!redir)
5826                return;
5827
5828        sv = NULL;
5829        INT_OFF;
5830        if (flags & REDIR_PUSH)
5831                sv = redirlist;
5832        do {
5833                int fd;
5834                int newfd;
5835                int close_fd;
5836                int closed;
5837
5838                fd = redir->nfile.fd;
5839                if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5840                        //bb_error_msg("doing %d > %d", fd, newfd);
5841                        newfd = redir->ndup.dupfd;
5842                        close_fd = -1;
5843                } else {
5844                        newfd = openredirect(redir); /* always >= 0 */
5845                        if (fd == newfd) {
5846                                /* open() gave us precisely the fd we wanted.
5847                                 * This means that this fd was not busy
5848                                 * (not opened to anywhere).
5849                                 * Remember to close it on restore:
5850                                 */
5851                                add_squirrel_closed(sv, fd);
5852                                continue;
5853                        }
5854                        close_fd = newfd;
5855                }
5856
5857                if (fd == newfd)
5858                        continue;
5859
5860                /* if "N>FILE": move newfd to fd */
5861                /* if "N>&M": dup newfd to fd */
5862                /* if "N>&-": close fd (newfd is -1) */
5863
5864 IF_BASH_REDIR_OUTPUT(redirect_more:)
5865
5866                closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5867                if (newfd == -1) {
5868                        /* "N>&-" means "close me" */
5869                        if (!closed) {
5870                                /* ^^^ optimization: saving may already
5871                                 * have closed it. If not... */
5872                                close(fd);
5873                        }
5874                } else {
5875                        /* if newfd is a script fd or saved fd, simulate EBADF */
5876                        if (internally_opened_fd(newfd, sv)) {
5877                                errno = EBADF;
5878                                ash_msg_and_raise_perror("%d", newfd);
5879                        }
5880                        dup2_or_raise(newfd, fd);
5881                        if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5882                                close(close_fd);
5883#if BASH_REDIR_OUTPUT
5884                        if (redir->nfile.type == NTO2 && fd == 1) {
5885                                /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5886                                fd = 2;
5887                                newfd = 1;
5888                                close_fd = -1;
5889                                goto redirect_more;
5890                        }
5891#endif
5892                }
5893        } while ((redir = redir->nfile.next) != NULL);
5894        INT_ON;
5895
5896//dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5897#define REDIR_SAVEFD2 0
5898        // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5899        // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5900        // not only for calls with flags containing REDIR_SAVEFD2.
5901        // We do this unconditionally (see save_fd_on_redirect()).
5902        //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5903        //      preverrout_fd = copied_fd2;
5904}
5905
5906static int
5907redirectsafe(union node *redir, int flags)
5908{
5909        int err;
5910        volatile int saveint;
5911        struct jmploc *volatile savehandler = exception_handler;
5912        struct jmploc jmploc;
5913
5914        SAVE_INT(saveint);
5915        /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5916        err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5917        if (!err) {
5918                exception_handler = &jmploc;
5919                redirect(redir, flags);
5920        }
5921        exception_handler = savehandler;
5922        if (err && exception_type != EXERROR)
5923                longjmp(exception_handler->loc, 1);
5924        RESTORE_INT(saveint);
5925        return err;
5926}
5927
5928#if BASH_PROCESS_SUBST
5929static void
5930pushfd(int fd)
5931{
5932        struct redirtab *sv;
5933
5934        sv = ckzalloc(sizeof(*sv) + sizeof(sv->two_fd[0]));
5935        sv->pair_count = 1;
5936        sv->two_fd[0].orig_fd = fd;
5937        sv->two_fd[0].moved_to = CLOSED;
5938        sv->next = redirlist;
5939        redirlist = sv;
5940}
5941#endif
5942
5943static struct redirtab*
5944pushredir(union node *redir)
5945{
5946        struct redirtab *sv;
5947        int i;
5948
5949        if (!redir)
5950                return redirlist;
5951
5952        i = 0;
5953        do {
5954                i++;
5955#if BASH_REDIR_OUTPUT
5956                if (redir->nfile.type == NTO2)
5957                        i++;
5958#endif
5959                redir = redir->nfile.next;
5960        } while (redir);
5961
5962        sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5963        sv->pair_count = i;
5964        while (--i >= 0)
5965                sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5966        sv->next = redirlist;
5967        redirlist = sv;
5968        return sv->next;
5969}
5970
5971/*
5972 * Undo the effects of the last redirection.
5973 */
5974static void
5975popredir(int drop)
5976{
5977        struct redirtab *rp;
5978        int i;
5979
5980        if (redirlist == NULL)
5981                return;
5982        INT_OFF;
5983        rp = redirlist;
5984        for (i = 0; i < rp->pair_count; i++) {
5985                int fd = rp->two_fd[i].orig_fd;
5986                int copy = rp->two_fd[i].moved_to;
5987                if (copy == CLOSED) {
5988                        if (!drop)
5989                                close(fd);
5990                        continue;
5991                }
5992                if (copy != EMPTY) {
5993                        if (!drop) {
5994                                /*close(fd);*/
5995                                dup2_or_raise(copy, fd);
5996                        }
5997                        close(copy);
5998                }
5999        }
6000        redirlist = rp->next;
6001        free(rp);
6002        INT_ON;
6003}
6004
6005static void
6006unwindredir(struct redirtab *stop)
6007{
6008        while (redirlist != stop)
6009                popredir(/*drop:*/ 0);
6010}
6011
6012
6013/* ============ Routines to expand arguments to commands
6014 *
6015 * We have to deal with backquotes, shell variables, and file metacharacters.
6016 */
6017
6018#if ENABLE_FEATURE_SH_MATH
6019static arith_t
6020ash_arith(const char *s)
6021{
6022        arith_state_t math_state;
6023        arith_t result;
6024
6025        math_state.lookupvar = lookupvar;
6026        math_state.setvar    = setvar0;
6027        //math_state.endofname = endofname;
6028
6029        INT_OFF;
6030        result = arith(&math_state, s);
6031        if (math_state.errmsg)
6032                ash_msg_and_raise_error(math_state.errmsg);
6033        INT_ON;
6034
6035        return result;
6036}
6037#endif
6038#if BASH_SUBSTR
6039# if ENABLE_FEATURE_SH_MATH
6040static int substr_atoi(const char *s)
6041{
6042        arith_t t = ash_arith(s);
6043        if (sizeof(t) > sizeof(int)) {
6044                /* clamp very large or very large negative nums for ${v:N:M}:
6045                 * else "${v:0:0x100000001}" would work as "${v:0:1}"
6046                 */
6047                if (t > INT_MAX)
6048                        t = INT_MAX;
6049                if (t < INT_MIN)
6050                        t = INT_MIN;
6051        }
6052        return t;
6053}
6054# else
6055#  define substr_atoi(s) number(s)
6056# endif
6057#endif
6058
6059/*
6060 * expandarg flags
6061 */
6062#define EXP_FULL        0x1     /* perform word splitting & file globbing */
6063#define EXP_TILDE       0x2     /* do normal tilde expansion */
6064#define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
6065#define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
6066/* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
6067 * POSIX says for this case:
6068 *  Pathname expansion shall not be performed on the word by a
6069 *  non-interactive shell; an interactive shell may perform it, but shall
6070 *  do so only when the expansion would result in one word.
6071 * Currently, our code complies to the above rule by never globbing
6072 * redirection filenames.
6073 * Bash performs globbing, unless it is non-interactive and in POSIX mode.
6074 * (this means that on a typical Linux distro, bash almost always
6075 * performs globbing, and thus diverges from what we do).
6076 */
6077#define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
6078#define EXP_VARTILDE2   0x20    /* expand tildes after colons only */
6079#define EXP_WORD        0x40    /* expand word in parameter expansion */
6080#define EXP_QUOTED      0x100   /* expand word in double quotes */
6081#define EXP_KEEPNUL     0x200   /* do not skip NUL characters */
6082#define EXP_DISCARD     0x400   /* discard result of expansion */
6083
6084/*
6085 * rmescape() flags
6086 */
6087#define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
6088#define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
6089#define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
6090#define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
6091
6092/* Add CTLESC when necessary. */
6093#define QUOTES_ESC     (EXP_FULL | EXP_CASE)
6094
6095/*
6096 * Structure specifying which parts of the string should be searched
6097 * for IFS characters.
6098 */
6099struct ifsregion {
6100        struct ifsregion *next; /* next region in list */
6101        int begoff;             /* offset of start of region */
6102        int endoff;             /* offset of end of region */
6103        int nulonly;            /* search for nul bytes only */
6104};
6105
6106struct arglist {
6107        struct strlist *list;
6108        struct strlist **lastp;
6109};
6110
6111/* output of current string */
6112static char *expdest;
6113/* list of back quote expressions */
6114static struct nodelist *argbackq;
6115/* first struct in list of ifs regions */
6116static struct ifsregion ifsfirst;
6117/* last struct in list */
6118static struct ifsregion *ifslastp;
6119/* holds expanded arg list */
6120static struct arglist exparg;
6121
6122/*
6123 * Break the argument string into pieces based upon IFS and add the
6124 * strings to the argument list.  The regions of the string to be
6125 * searched for IFS characters have been stored by recordregion.
6126 */
6127static void
6128ifsbreakup(char *string, struct arglist *arglist)
6129{
6130        struct ifsregion *ifsp;
6131        struct strlist *sp;
6132        char *start;
6133        char *p;
6134        char *q;
6135        const char *ifs, *realifs;
6136        int ifsspc;
6137        int nulonly;
6138
6139        start = string;
6140        if (ifslastp != NULL) {
6141                ifsspc = 0;
6142                nulonly = 0;
6143                realifs = ifsset() ? ifsval() : defifs;
6144                ifsp = &ifsfirst;
6145                do {
6146                        int afternul;
6147
6148                        p = string + ifsp->begoff;
6149                        afternul = nulonly;
6150                        nulonly = ifsp->nulonly;
6151                        ifs = nulonly ? nullstr : realifs;
6152                        ifsspc = 0;
6153                        while (p < string + ifsp->endoff) {
6154                                q = p;
6155                                if ((unsigned char)*p == CTLESC)
6156                                        p++;
6157                                if (!strchr(ifs, *p)) {
6158                                        p++;
6159                                        continue;
6160                                }
6161                                if (!(afternul || nulonly))
6162                                        ifsspc = (strchr(defifs, *p) != NULL);
6163                                /* Ignore IFS whitespace at start */
6164                                if (q == start && ifsspc) {
6165                                        p++;
6166                                        start = p;
6167                                        continue;
6168                                }
6169                                *q = '\0';
6170                                sp = stzalloc(sizeof(*sp));
6171                                sp->text = start;
6172                                *arglist->lastp = sp;
6173                                arglist->lastp = &sp->next;
6174                                p++;
6175                                if (!nulonly) {
6176                                        for (;;) {
6177                                                if (p >= string + ifsp->endoff) {
6178                                                        break;
6179                                                }
6180                                                q = p;
6181                                                if ((unsigned char)*p == CTLESC)
6182                                                        p++;
6183                                                if (strchr(ifs, *p) == NULL) {
6184                                                        p = q;
6185                                                        break;
6186                                                }
6187                                                if (strchr(defifs, *p) == NULL) {
6188                                                        if (ifsspc) {
6189                                                                p++;
6190                                                                ifsspc = 0;
6191                                                        } else {
6192                                                                p = q;
6193                                                                break;
6194                                                        }
6195                                                } else
6196                                                        p++;
6197                                        }
6198                                }
6199                                start = p;
6200                        } /* while */
6201                        ifsp = ifsp->next;
6202                } while (ifsp != NULL);
6203                if (nulonly)
6204                        goto add;
6205        }
6206
6207        if (!*start)
6208                return;
6209
6210 add:
6211        sp = stzalloc(sizeof(*sp));
6212        sp->text = start;
6213        *arglist->lastp = sp;
6214        arglist->lastp = &sp->next;
6215}
6216
6217static void
6218ifsfree(void)
6219{
6220        struct ifsregion *p = ifsfirst.next;
6221
6222        if (!p)
6223                goto out;
6224
6225        INT_OFF;
6226        do {
6227                struct ifsregion *ifsp;
6228                ifsp = p->next;
6229                free(p);
6230                p = ifsp;
6231        } while (p);
6232        ifsfirst.next = NULL;
6233        INT_ON;
6234 out:
6235        ifslastp = NULL;
6236}
6237
6238static size_t
6239esclen(const char *start, const char *p)
6240{
6241        size_t esc = 0;
6242
6243        while (p > start && (unsigned char)*--p == CTLESC) {
6244                esc++;
6245        }
6246        return esc;
6247}
6248
6249/*
6250 * Remove any CTLESC characters from a string.
6251 */
6252#if !BASH_PATTERN_SUBST
6253#define rmescapes(str, flag, slash_position) \
6254        rmescapes(str, flag)
6255#endif
6256static char *
6257rmescapes(char *str, int flag, int *slash_position)
6258{
6259        static const char qchars[] ALIGN1 = {
6260                IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
6261
6262        char *p, *q, *r;
6263        unsigned protect_against_glob;
6264        unsigned globbing;
6265
6266        p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash_position));
6267        if (!p)
6268                return str;
6269
6270        q = p;
6271        r = str;
6272        if (flag & RMESCAPE_ALLOC) {
6273                size_t len = p - str;
6274                size_t fulllen = len + strlen(p) + 1;
6275
6276                if (flag & RMESCAPE_GROW) {
6277                        int strloc = str - (char *)stackblock();
6278                        r = makestrspace(fulllen, expdest);
6279                        /* p and str may be invalidated by makestrspace */
6280                        str = (char *)stackblock() + strloc;
6281                        p = str + len;
6282                } else if (flag & RMESCAPE_HEAP) {
6283                        r = ckmalloc(fulllen);
6284                } else {
6285                        r = stalloc(fulllen);
6286                }
6287                q = r;
6288                if (len > 0) {
6289                        q = (char *)mempcpy(q, str, len);
6290                }
6291        }
6292
6293        globbing = flag & RMESCAPE_GLOB;
6294        protect_against_glob = globbing;
6295        while (*p) {
6296                if ((unsigned char)*p == CTLQUOTEMARK) {
6297// Note: protect_against_glob only affect whether
6298// CTLESC,<ch> gets converted to <ch> or to \<ch>
6299                        p++;
6300                        protect_against_glob = globbing;
6301                        continue;
6302                }
6303                if (*p == '\\') {
6304                        /* naked back slash */
6305                        protect_against_glob = 0;
6306                        goto copy;
6307                }
6308                if ((unsigned char)*p == CTLESC) {
6309                        p++;
6310#if DEBUG
6311                        if (*p == '\0')
6312                                ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6313#endif
6314                        if (protect_against_glob) {
6315                                /*
6316                                 * We used to trust glob() and fnmatch() to eat
6317                                 * superfluous escapes (\z where z has no
6318                                 * special meaning anyway). But this causes
6319                                 * bugs such as string of one greek letter rho
6320                                 * (unicode-encoded as two bytes "cf,81")
6321                                 * getting encoded as "cf,CTLESC,81"
6322                                 * and here, converted to "cf,\,81" -
6323                                 * which does not go well with some flavors
6324                                 * of fnmatch() in unicode locales
6325                                 * (for example, glibc <= 2.22).
6326                                 *
6327                                 * Lets add "\" only on the chars which need it.
6328                                 * Testcases for less obvious chars are shown.
6329                                 */
6330                                if (*p == '*'
6331                                 || *p == '?'
6332                                 || *p == '['
6333                                 || *p == '\\' /* case '\' in \\    ) echo ok;; *) echo WRONG;; esac */
6334                                 || *p == ']'  /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6335                                 || *p == '-'  /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6336                                 || *p == '!'  /* case '!' in [\!]  ) echo ok;; *) echo WRONG;; esac */
6337                                /* Some libc support [^negate], that's why "^" also needs love */
6338                                 || *p == '^'  /* case '^' in [\^]  ) echo ok;; *) echo WRONG;; esac */
6339                                ) {
6340                                        *q++ = '\\';
6341                                }
6342                        }
6343                }
6344#if BASH_PATTERN_SUBST
6345                else if (slash_position && p == str + *slash_position) {
6346                        /* stop handling globbing */
6347                        globbing = 0;
6348                        *slash_position = q - r;
6349                        slash_position = NULL;
6350                }
6351#endif
6352                protect_against_glob = globbing;
6353 copy:
6354                *q++ = *p++;
6355        }
6356        *q = '\0';
6357        if (flag & RMESCAPE_GROW) {
6358                expdest = r;
6359                STADJUST(q - r + 1, expdest);
6360        }
6361        return r;
6362}
6363#define pmatch(a, b) !fnmatch((a), (b), 0)
6364
6365/*
6366 * Prepare a pattern for a expmeta (internal glob(3)) call.
6367 *
6368 * Returns an stalloced string.
6369 */
6370static char *
6371preglob(const char *pattern, int flag)
6372{
6373        return rmescapes((char *)pattern, flag | RMESCAPE_GLOB, NULL);
6374}
6375
6376/*
6377 * Put a string on the stack.
6378 */
6379static size_t
6380memtodest(const char *p, size_t len, int flags)
6381{
6382        int syntax = flags & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6383        char *q;
6384        char *s;
6385
6386        if (!len)
6387                return 0;
6388
6389        q = makestrspace(len * 2, expdest);
6390        s = q;
6391
6392        do {
6393                unsigned char c = *p++;
6394                if (c) {
6395                        if (flags & QUOTES_ESC) {
6396                                int n = SIT(c, syntax);
6397                                if (n == CCTL
6398                                 || ((flags & EXP_QUOTED) && n == CBACK)
6399                                ) {
6400                                        USTPUTC(CTLESC, q);
6401                                }
6402                        }
6403                } else if (!(flags & EXP_KEEPNUL))
6404                        continue;
6405                USTPUTC(c, q);
6406        } while (--len);
6407
6408        expdest = q;
6409        return q - s;
6410}
6411
6412static size_t
6413strtodest(const char *p, int flags)
6414{
6415        size_t len = strlen(p);
6416        memtodest(p, len, flags);
6417        return len;
6418}
6419
6420/*
6421 * Our own itoa().
6422 * cvtnum() is used even if math support is off (to prepare $? values and such).
6423 */
6424static int
6425cvtnum(arith_t num, int flags)
6426{
6427        /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
6428        /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
6429        int len = (sizeof(arith_t) >= 4) ? sizeof(arith_t) * 3 : sizeof(arith_t) * 3 + 2;
6430        char buf[len];
6431
6432        len = fmtstr(buf, len, ARITH_FMT, num);
6433        return memtodest(buf, len, flags);
6434}
6435
6436/*
6437 * Record the fact that we have to scan this region of the
6438 * string for IFS characters.
6439 */
6440static void
6441recordregion(int start, int end, int nulonly)
6442{
6443        struct ifsregion *ifsp;
6444
6445        if (ifslastp == NULL) {
6446