2b13786943735bfe93f22ac425d4a33bf1dd7589
[oweals/busybox.git] / shell / ash.c
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 ASH
19 //config:       bool "ash (78 kb)"
20 //config:       default y
21 //config:       depends on !NOMMU
22 //config:       help
23 //config:       The most complete and most pedantically correct shell included with
24 //config:       busybox. This shell is actually a derivative of the Debian 'dash'
25 //config:       shell (by Herbert Xu), which was created by porting the 'ash' shell
26 //config:       (written by Kenneth Almquist) from NetBSD.
27 //config:
28 //config:# ash options
29 //config:# note: Don't remove !NOMMU part in the next line; it would break
30 //config:# menuconfig's indenting.
31 //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
32 //config:
33 //config:config ASH_OPTIMIZE_FOR_SIZE
34 //config:       bool "Optimize for size instead of speed"
35 //config:       default y
36 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
37 //config:
38 //config:config ASH_INTERNAL_GLOB
39 //config:       bool "Use internal glob() implementation"
40 //config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
41 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
42 //config:       help
43 //config:       Do not use glob() function from libc, use internal implementation.
44 //config:       Use this if you are getting "glob.h: No such file or directory"
45 //config:       or similar build errors.
46 //config:       Note that as of now (2017-01), uclibc and musl glob() both have bugs
47 //config:       which would break ash if you select N here.
48 //config:
49 //config:config ASH_BASH_COMPAT
50 //config:       bool "bash-compatible extensions"
51 //config:       default y
52 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
53 //config:
54 //config:config ASH_BASH_SOURCE_CURDIR
55 //config:       bool "'source' and '.' builtins search current directory after $PATH"
56 //config:       default n   # do not encourage non-standard behavior
57 //config:       depends on ASH_BASH_COMPAT
58 //config:       help
59 //config:       This is not compliant with standards. Avoid if possible.
60 //config:
61 //config:config ASH_BASH_NOT_FOUND_HOOK
62 //config:       bool "command_not_found_handle hook support"
63 //config:       default y
64 //config:       depends on ASH_BASH_COMPAT
65 //config:       help
66 //config:       Enable support for the 'command_not_found_handle' hook function,
67 //config:       from GNU bash, which allows for alternative command not found
68 //config:       handling.
69 //config:
70 //config:config ASH_JOB_CONTROL
71 //config:       bool "Job control"
72 //config:       default y
73 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
74 //config:
75 //config:config ASH_ALIAS
76 //config:       bool "Alias support"
77 //config:       default y
78 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
79 //config:
80 //config:config ASH_RANDOM_SUPPORT
81 //config:       bool "Pseudorandom generator and $RANDOM variable"
82 //config:       default y
83 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
84 //config:       help
85 //config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
86 //config:       Each read of "$RANDOM" will generate a new pseudorandom value.
87 //config:       You can reset the generator by using a specified start value.
88 //config:       After "unset RANDOM" the generator will switch off and this
89 //config:       variable will no longer have special treatment.
90 //config:
91 //config:config ASH_EXPAND_PRMT
92 //config:       bool "Expand prompt string"
93 //config:       default y
94 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
95 //config:       help
96 //config:       $PS# may contain volatile content, such as backquote commands.
97 //config:       This option recreates the prompt string from the environment
98 //config:       variable each time it is displayed.
99 //config:
100 //config:config ASH_IDLE_TIMEOUT
101 //config:       bool "Idle timeout variable $TMOUT"
102 //config:       default y
103 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
104 //config:       help
105 //config:       Enable bash-like auto-logout after $TMOUT seconds of idle time.
106 //config:
107 //config:config ASH_MAIL
108 //config:       bool "Check for new mail in interactive shell"
109 //config:       default y
110 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
111 //config:       help
112 //config:       Enable "check for new mail" function:
113 //config:       if set, $MAIL file and $MAILPATH list of files
114 //config:       are checked for mtime changes, and "you have mail"
115 //config:       message is printed if change is detected.
116 //config:
117 //config:config ASH_ECHO
118 //config:       bool "echo builtin"
119 //config:       default y
120 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
121 //config:
122 //config:config ASH_PRINTF
123 //config:       bool "printf builtin"
124 //config:       default y
125 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
126 //config:
127 //config:config ASH_TEST
128 //config:       bool "test builtin"
129 //config:       default y
130 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
131 //config:
132 //config:config ASH_HELP
133 //config:       bool "help builtin"
134 //config:       default y
135 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
136 //config:
137 //config:config ASH_GETOPTS
138 //config:       bool "getopts builtin"
139 //config:       default y
140 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
141 //config:
142 //config:config ASH_CMDCMD
143 //config:       bool "command builtin"
144 //config:       default y
145 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
146 //config:       help
147 //config:       Enable support for the 'command' builtin, which allows
148 //config:       you to run the specified command or builtin,
149 //config:       even when there is a function with the same name.
150 //config:
151 //config:endif # ash options
152
153 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
154 //                      APPLET_ODDNAME:name  main location    suid_type     help
155 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
156 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
157
158 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
159 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
160 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
161 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
162
163 /*
164  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
165  * DEBUG=2 to compile in and turn on debugging.
166  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
167  * debugging info is written to ./trace, quit signal generates core dump.
168  */
169 #define DEBUG 0
170 /* Tweak debug output verbosity here */
171 #define DEBUG_TIME 0
172 #define DEBUG_PID 1
173 #define DEBUG_SIG 1
174 #define DEBUG_INTONOFF 0
175
176 #define PROFILE 0
177
178 #define JOBS ENABLE_ASH_JOB_CONTROL
179
180 #include <fnmatch.h>
181 #include <sys/times.h>
182 #include <sys/utsname.h> /* for setting $HOSTNAME */
183 #include "busybox.h" /* for applet_names */
184 #if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS
185 # include "embedded_scripts.h"
186 #else
187 # define NUM_SCRIPTS 0
188 #endif
189
190 /* So far, all bash compat is controlled by one config option */
191 /* Separate defines document which part of code implements what */
192 /* function keyword */
193 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
194 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
195 /* &>file */
196 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
197 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
198 /* $'...' */
199 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
200 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
201 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
202 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
203 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
204 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
205 /* BASH_TEST2: [[ EXPR ]]
206  * Status of [[ support:
207  * We replace && and || with -a and -o
208  * TODO:
209  * singleword+noglob expansion:
210  *   v='a b'; [[ $v = 'a b' ]]; echo 0:$?
211  *   [[ /bin/n* ]]; echo 0:$?
212  * -a/-o are not AND/OR ops! (they are just strings)
213  * quoting needs to be considered (-f is an operator, "-f" and ""-f are not; etc)
214  * = is glob match operator, not equality operator: STR = GLOB
215  * (in GLOB, quoting is significant on char-by-char basis: a*cd"*")
216  * == same as =
217  * add =~ regex match operator: STR =~ REGEX
218  */
219 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
220 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
221 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
222 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
223 #define    BASH_EPOCH_VARS      ENABLE_ASH_BASH_COMPAT
224 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
225 #define    BASH_XTRACEFD        ENABLE_ASH_BASH_COMPAT
226 #define    BASH_READ_D          ENABLE_ASH_BASH_COMPAT
227 #define IF_BASH_READ_D              IF_ASH_BASH_COMPAT
228 #define    BASH_WAIT_N          ENABLE_ASH_BASH_COMPAT
229
230 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
231 /* Bionic at least up to version 24 has no glob() */
232 # undef  ENABLE_ASH_INTERNAL_GLOB
233 # define ENABLE_ASH_INTERNAL_GLOB 1
234 #endif
235
236 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
237 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
238 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
239 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
240 # error glob() should unbackslash them and match. uClibc does not unbackslash,
241 # error fails to match dirname, subsequently not expanding <pattern> in it.
242 // Testcase:
243 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
244 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
245 #endif
246
247 #if !ENABLE_ASH_INTERNAL_GLOB
248 # include <glob.h>
249 #endif
250
251 #include "unicode.h"
252 #include "shell_common.h"
253 #if ENABLE_FEATURE_SH_MATH
254 # include "math.h"
255 #else
256 typedef long arith_t;
257 # define ARITH_FMT "%ld"
258 #endif
259 #if ENABLE_ASH_RANDOM_SUPPORT
260 # include "random.h"
261 #else
262 # define CLEAR_RANDOM_T(rnd) ((void)0)
263 #endif
264
265 #include "NUM_APPLETS.h"
266 #if NUM_APPLETS == 1
267 /* STANDALONE does not make sense, and won't compile */
268 # undef CONFIG_FEATURE_SH_STANDALONE
269 # undef ENABLE_FEATURE_SH_STANDALONE
270 # undef IF_FEATURE_SH_STANDALONE
271 # undef IF_NOT_FEATURE_SH_STANDALONE
272 # define ENABLE_FEATURE_SH_STANDALONE 0
273 # define IF_FEATURE_SH_STANDALONE(...)
274 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
275 #endif
276
277 #ifndef F_DUPFD_CLOEXEC
278 # define F_DUPFD_CLOEXEC F_DUPFD
279 #endif
280 #ifndef O_CLOEXEC
281 # define O_CLOEXEC 0
282 #endif
283 #ifndef PIPE_BUF
284 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
285 #endif
286
287 #if !BB_MMU
288 # error "Do not even bother, ash will not run on NOMMU machine"
289 #endif
290
291 /* We use a trick to have more optimized code (fewer pointer reloads):
292  *  ash.c:   extern struct globals *const ash_ptr_to_globals;
293  *  ash_ptr_hack.c: struct globals *ash_ptr_to_globals;
294  * This way, compiler in ash.c knows the pointer can not change.
295  *
296  * However, this may break on weird arches or toolchains. In this case,
297  * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable
298  * this optimization.
299  */
300 #ifndef BB_GLOBAL_CONST
301 # define BB_GLOBAL_CONST const
302 #endif
303
304
305 /* ============ Hash table sizes. Configurable. */
306
307 #define VTABSIZE 39
308 #define ATABSIZE 39
309 #define CMDTABLESIZE 31         /* should be prime */
310
311
312 /* ============ Shell options */
313
314 static const char *const optletters_optnames[] = {
315         "e"   "errexit",
316         "f"   "noglob",
317         "I"   "ignoreeof",
318 /* The below allowed this invocation:
319  * ash -c 'set -i; echo $-; sleep 5; echo $-'
320  * to be ^C-ed and get to interactive ash prompt.
321  * bash does not support such "set -i".
322  * In our code, this is denoted by empty long name:
323  */
324         "i"   "",
325         "m"   "monitor",
326         "n"   "noexec",
327 /* Ditto: bash has no "set -s" */
328         "s"   "",
329         "c"   "",
330         "x"   "xtrace",
331         "v"   "verbose",
332         "C"   "noclobber",
333         "a"   "allexport",
334         "b"   "notify",
335         "u"   "nounset",
336         "\0"  "vi"
337 #if BASH_PIPEFAIL
338         ,"\0"  "pipefail"
339 #endif
340 #if DEBUG
341         ,"\0"  "nolog"
342         ,"\0"  "debug"
343 #endif
344 };
345 //bash 4.4.23 also has these opts (with these defaults):
346 //braceexpand           on
347 //emacs                 on
348 //errtrace              off
349 //functrace             off
350 //hashall               on
351 //histexpand            off
352 //history               on
353 //interactive-comments  on
354 //keyword               off
355 //onecmd                off
356 //physical              off
357 //posix                 off
358 //privileged            off
359
360 #define optletters(n)  optletters_optnames[n][0]
361 #define optnames(n)   (optletters_optnames[n] + 1)
362
363 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
364
365
366 /* ============ Misc data */
367
368 #define msg_illnum "Illegal number: %s"
369
370 /*
371  * We enclose jmp_buf in a structure so that we can declare pointers to
372  * jump locations.  The global variable handler contains the location to
373  * jump to when an exception occurs, and the global variable exception_type
374  * contains a code identifying the exception.  To implement nested
375  * exception handlers, the user should save the value of handler on entry
376  * to an inner scope, set handler to point to a jmploc structure for the
377  * inner scope, and restore handler on exit from the scope.
378  */
379 struct jmploc {
380         jmp_buf loc;
381 };
382
383 struct globals_misc {
384         uint8_t exitstatus;     /* exit status of last command */
385         uint8_t back_exitstatus;/* exit status of backquoted command */
386         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
387         int savestatus;         /* exit status of last command outside traps */
388         int rootpid;            /* pid of main shell */
389         /* shell level: 0 for the main shell, 1 for its children, and so on */
390         int shlvl;
391 #define rootshell (!shlvl)
392         int errlinno;
393
394         char *minusc;  /* argument to -c option */
395
396         char *curdir; // = nullstr;     /* current working directory */
397         char *physdir; // = nullstr;    /* physical working directory */
398
399         char *arg0; /* value of $0 */
400
401         struct jmploc *exception_handler;
402
403         volatile int suppress_int; /* counter */
404         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
405         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
406         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
407         smallint exception_type; /* kind of exception (0..5) */
408         /* exceptions */
409 #define EXINT 0         /* SIGINT received */
410 #define EXERROR 1       /* a generic error */
411 #define EXEXIT 4        /* exit the shell */
412
413         char nullstr[1];        /* zero length string */
414
415         char optlist[NOPTS];
416 #define eflag optlist[0]
417 #define fflag optlist[1]
418 #define Iflag optlist[2]
419 #define iflag optlist[3]
420 #define mflag optlist[4]
421 #define nflag optlist[5]
422 #define sflag optlist[6]
423 #define cflag optlist[7]
424 #define xflag optlist[8]
425 #define vflag optlist[9]
426 #define Cflag optlist[10]
427 #define aflag optlist[11]
428 #define bflag optlist[12]
429 #define uflag optlist[13]
430 #define viflag optlist[14]
431 #if BASH_PIPEFAIL
432 # define pipefail optlist[15]
433 #else
434 # define pipefail 0
435 #endif
436 #if DEBUG
437 # define nolog optlist[15 + BASH_PIPEFAIL]
438 # define debug optlist[16 + BASH_PIPEFAIL]
439 #endif
440
441         /* trap handler commands */
442         /*
443          * Sigmode records the current value of the signal handlers for the various
444          * modes.  A value of zero means that the current handler is not known.
445          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
446          */
447         char sigmode[NSIG - 1];
448 #define S_DFL      1            /* default signal handling (SIG_DFL) */
449 #define S_CATCH    2            /* signal is caught */
450 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
451 #define S_HARD_IGN 4            /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
452
453         /* indicates specified signal received */
454         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
455         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
456         char *trap[NSIG];
457         char **trap_ptr;        /* used only by "trap hack" */
458
459         /* Rarely referenced stuff */
460 #if ENABLE_ASH_RANDOM_SUPPORT
461         random_t random_gen;
462 #endif
463         pid_t backgndpid;        /* pid of last background process */
464 };
465 extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc;
466 #define G_misc (*ash_ptr_to_globals_misc)
467 #define exitstatus        (G_misc.exitstatus )
468 #define back_exitstatus   (G_misc.back_exitstatus )
469 #define job_warning       (G_misc.job_warning)
470 #define savestatus  (G_misc.savestatus )
471 #define rootpid     (G_misc.rootpid    )
472 #define shlvl       (G_misc.shlvl      )
473 #define errlinno    (G_misc.errlinno   )
474 #define minusc      (G_misc.minusc     )
475 #define curdir      (G_misc.curdir     )
476 #define physdir     (G_misc.physdir    )
477 #define arg0        (G_misc.arg0       )
478 #define exception_handler (G_misc.exception_handler)
479 #define exception_type    (G_misc.exception_type   )
480 #define suppress_int      (G_misc.suppress_int     )
481 #define pending_int       (G_misc.pending_int      )
482 #define got_sigchld       (G_misc.got_sigchld      )
483 #define pending_sig       (G_misc.pending_sig      )
484 #define nullstr     (G_misc.nullstr    )
485 #define optlist     (G_misc.optlist    )
486 #define sigmode     (G_misc.sigmode    )
487 #define gotsig      (G_misc.gotsig     )
488 #define may_have_traps    (G_misc.may_have_traps   )
489 #define trap        (G_misc.trap       )
490 #define trap_ptr    (G_misc.trap_ptr   )
491 #define random_gen  (G_misc.random_gen )
492 #define backgndpid  (G_misc.backgndpid )
493 #define INIT_G_misc() do { \
494         (*(struct globals_misc**)not_const_pp(&ash_ptr_to_globals_misc)) = xzalloc(sizeof(G_misc)); \
495         barrier(); \
496         savestatus = -1; \
497         curdir = nullstr; \
498         physdir = nullstr; \
499         trap_ptr = trap; \
500 } while (0)
501
502
503 /* ============ DEBUG */
504 #if DEBUG
505 static void trace_printf(const char *fmt, ...);
506 static void trace_vprintf(const char *fmt, va_list va);
507 # define TRACE(param)    trace_printf param
508 # define TRACEV(param)   trace_vprintf param
509 # define close(fd) do { \
510         int dfd = (fd); \
511         if (close(dfd) < 0) \
512                 bb_error_msg("bug on %d: closing %d(0x%x)", \
513                         __LINE__, dfd, dfd); \
514 } while (0)
515 #else
516 # define TRACE(param)
517 # define TRACEV(param)
518 #endif
519
520
521 /* ============ Utility functions */
522 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
523 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
524
525 static int
526 isdigit_str9(const char *str)
527 {
528         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
529         while (--maxlen && isdigit(*str))
530                 str++;
531         return (*str == '\0');
532 }
533
534 static const char *
535 var_end(const char *var)
536 {
537         while (*var)
538                 if (*var++ == '=')
539                         break;
540         return var;
541 }
542
543
544 /* ============ Interrupts / exceptions */
545
546 static void exitshell(void) NORETURN;
547
548 /*
549  * These macros allow the user to suspend the handling of interrupt signals
550  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
551  * much more efficient and portable.  (But hacking the kernel is so much
552  * more fun than worrying about efficiency and portability. :-))
553  */
554 #if DEBUG_INTONOFF
555 # define INT_OFF do { \
556         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
557         suppress_int++; \
558         barrier(); \
559 } while (0)
560 #else
561 # define INT_OFF do { \
562         suppress_int++; \
563         barrier(); \
564 } while (0)
565 #endif
566
567 /*
568  * Called to raise an exception.  Since C doesn't include exceptions, we
569  * just do a longjmp to the exception handler.  The type of exception is
570  * stored in the global variable "exception_type".
571  */
572 static void raise_exception(int) NORETURN;
573 static void
574 raise_exception(int e)
575 {
576 #if DEBUG
577         if (exception_handler == NULL)
578                 abort();
579 #endif
580         INT_OFF;
581         exception_type = e;
582         longjmp(exception_handler->loc, 1);
583 }
584 #if DEBUG
585 #define raise_exception(e) do { \
586         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
587         raise_exception(e); \
588 } while (0)
589 #endif
590
591 /*
592  * Called when a SIGINT is received.  (If the user specifies
593  * that SIGINT is to be trapped or ignored using the trap builtin, then
594  * this routine is not called.)  Suppressint is nonzero when interrupts
595  * are held using the INT_OFF macro.  (The test for iflag is just
596  * defensive programming.)
597  */
598 static void raise_interrupt(void) NORETURN;
599 static void
600 raise_interrupt(void)
601 {
602         pending_int = 0;
603         /* Signal is not automatically unmasked after it is raised,
604          * do it ourself - unmask all signals */
605         sigprocmask_allsigs(SIG_UNBLOCK);
606         /* pending_sig = 0; - now done in signal_handler() */
607
608         if (!(rootshell && iflag)) {
609                 /* Kill ourself with SIGINT */
610                 signal(SIGINT, SIG_DFL);
611                 raise(SIGINT);
612         }
613         /* bash: ^C even on empty command line sets $? */
614         exitstatus = SIGINT + 128;
615         raise_exception(EXINT);
616         /* NOTREACHED */
617 }
618 #if DEBUG
619 #define raise_interrupt() do { \
620         TRACE(("raising interrupt on line %d\n", __LINE__)); \
621         raise_interrupt(); \
622 } while (0)
623 #endif
624
625 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
626 int_on(void)
627 {
628         barrier();
629         if (--suppress_int == 0 && pending_int) {
630                 raise_interrupt();
631         }
632 }
633 #if DEBUG_INTONOFF
634 # define INT_ON do { \
635         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
636         int_on(); \
637 } while (0)
638 #else
639 # define INT_ON int_on()
640 #endif
641 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
642 force_int_on(void)
643 {
644         barrier();
645         suppress_int = 0;
646         if (pending_int)
647                 raise_interrupt();
648 }
649 #define FORCE_INT_ON force_int_on()
650
651 #define SAVE_INT(v) ((v) = suppress_int)
652
653 #define RESTORE_INT(v) do { \
654         barrier(); \
655         suppress_int = (v); \
656         if (suppress_int == 0 && pending_int) \
657                 raise_interrupt(); \
658 } while (0)
659
660
661 /* ============ Stdout/stderr output */
662
663 static void
664 outstr(const char *p, FILE *file)
665 {
666         INT_OFF;
667         fputs(p, file);
668         INT_ON;
669 }
670
671 static void
672 flush_stdout_stderr(void)
673 {
674         INT_OFF;
675         fflush_all();
676         INT_ON;
677 }
678
679 /* Was called outcslow(c,FILE*), but c was always '\n' */
680 static void
681 newline_and_flush(FILE *dest)
682 {
683         INT_OFF;
684         putc('\n', dest);
685         fflush(dest);
686         INT_ON;
687 }
688
689 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
690 static int
691 out1fmt(const char *fmt, ...)
692 {
693         va_list ap;
694         int r;
695
696         INT_OFF;
697         va_start(ap, fmt);
698         r = vprintf(fmt, ap);
699         va_end(ap);
700         INT_ON;
701         return r;
702 }
703
704 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
705 static int
706 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
707 {
708         va_list ap;
709         int ret;
710
711         INT_OFF;
712         va_start(ap, fmt);
713         ret = vsnprintf(outbuf, length, fmt, ap);
714         va_end(ap);
715         INT_ON;
716         return ret > (int)length ? length : ret;
717 }
718
719 static void
720 out1str(const char *p)
721 {
722         outstr(p, stdout);
723 }
724
725 static void
726 out2str(const char *p)
727 {
728         outstr(p, stderr);
729         flush_stdout_stderr();
730 }
731
732
733 /* ============ Parser structures */
734
735 /* control characters in argument strings */
736 #define CTL_FIRST CTLESC
737 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
738 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
739 #define CTLENDVAR    ((unsigned char)'\203')
740 #define CTLBACKQ     ((unsigned char)'\204')
741 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
742 #define CTLENDARI    ((unsigned char)'\207')
743 #define CTLQUOTEMARK ((unsigned char)'\210')
744 #define CTL_LAST CTLQUOTEMARK
745
746 /* variable substitution byte (follows CTLVAR) */
747 #define VSTYPE  0x0f            /* type of variable substitution */
748 #define VSNUL   0x10            /* colon--treat the empty string as unset */
749
750 /* values of VSTYPE field */
751 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
752 #define VSMINUS         0x2     /* ${var-text} */
753 #define VSPLUS          0x3     /* ${var+text} */
754 #define VSQUESTION      0x4     /* ${var?message} */
755 #define VSASSIGN        0x5     /* ${var=text} */
756 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
757 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
758 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
759 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
760 #define VSLENGTH        0xa     /* ${#var} */
761 #if BASH_SUBSTR
762 #define VSSUBSTR        0xc     /* ${var:position:length} */
763 #endif
764 #if BASH_PATTERN_SUBST
765 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
766 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
767 #endif
768
769 static const char dolatstr[] ALIGN1 = {
770         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
771 };
772 #define DOLATSTRLEN 6
773
774 #define NCMD      0
775 #define NPIPE     1
776 #define NREDIR    2
777 #define NBACKGND  3
778 #define NSUBSHELL 4
779 #define NAND      5
780 #define NOR       6
781 #define NSEMI     7
782 #define NIF       8
783 #define NWHILE    9
784 #define NUNTIL   10
785 #define NFOR     11
786 #define NCASE    12
787 #define NCLIST   13
788 #define NDEFUN   14
789 #define NARG     15
790 #define NTO      16
791 #if BASH_REDIR_OUTPUT
792 #define NTO2     17
793 #endif
794 #define NCLOBBER 18
795 #define NFROM    19
796 #define NFROMTO  20
797 #define NAPPEND  21
798 #define NTOFD    22
799 #define NFROMFD  23
800 #define NHERE    24
801 #define NXHERE   25
802 #define NNOT     26
803 #define N_NUMBER 27
804
805 union node;
806
807 struct ncmd {
808         smallint type; /* Nxxxx */
809         int linno;
810         union node *assign;
811         union node *args;
812         union node *redirect;
813 };
814
815 struct npipe {
816         smallint type;
817         smallint pipe_backgnd;
818         struct nodelist *cmdlist;
819 };
820
821 struct nredir {
822         smallint type;
823         int linno;
824         union node *n;
825         union node *redirect;
826 };
827
828 struct nbinary {
829         smallint type;
830         union node *ch1;
831         union node *ch2;
832 };
833
834 struct nif {
835         smallint type;
836         union node *test;
837         union node *ifpart;
838         union node *elsepart;
839 };
840
841 struct nfor {
842         smallint type;
843         int linno;
844         union node *args;
845         union node *body;
846         char *var;
847 };
848
849 struct ncase {
850         smallint type;
851         int linno;
852         union node *expr;
853         union node *cases;
854 };
855
856 struct nclist {
857         smallint type;
858         union node *next;
859         union node *pattern;
860         union node *body;
861 };
862
863 struct ndefun {
864         smallint type;
865         int linno;
866         char *text;
867         union node *body;
868 };
869
870 struct narg {
871         smallint type;
872         union node *next;
873         char *text;
874         struct nodelist *backquote;
875 };
876
877 /* nfile and ndup layout must match!
878  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
879  * that it is actually NTO2 (>&file), and change its type.
880  */
881 struct nfile {
882         smallint type;
883         union node *next;
884         int fd;
885         int _unused_dupfd;
886         union node *fname;
887         char *expfname;
888 };
889
890 struct ndup {
891         smallint type;
892         union node *next;
893         int fd;
894         int dupfd;
895         union node *vname;
896         char *_unused_expfname;
897 };
898
899 struct nhere {
900         smallint type;
901         union node *next;
902         int fd;
903         union node *doc;
904 };
905
906 struct nnot {
907         smallint type;
908         union node *com;
909 };
910
911 union node {
912         smallint type;
913         struct ncmd ncmd;
914         struct npipe npipe;
915         struct nredir nredir;
916         struct nbinary nbinary;
917         struct nif nif;
918         struct nfor nfor;
919         struct ncase ncase;
920         struct nclist nclist;
921         struct ndefun ndefun;
922         struct narg narg;
923         struct nfile nfile;
924         struct ndup ndup;
925         struct nhere nhere;
926         struct nnot nnot;
927 };
928
929 /*
930  * NODE_EOF is returned by parsecmd when it encounters an end of file.
931  * It must be distinct from NULL.
932  */
933 #define NODE_EOF ((union node *) -1L)
934
935 struct nodelist {
936         struct nodelist *next;
937         union node *n;
938 };
939
940 struct funcnode {
941         int count;
942         union node n;
943 };
944
945 /*
946  * Free a parse tree.
947  */
948 static void
949 freefunc(struct funcnode *f)
950 {
951         if (f && --f->count < 0)
952                 free(f);
953 }
954
955
956 /* ============ Debugging output */
957
958 #if DEBUG
959
960 static FILE *tracefile;
961
962 static void
963 trace_printf(const char *fmt, ...)
964 {
965         va_list va;
966
967         if (debug != 1)
968                 return;
969         if (DEBUG_TIME)
970                 fprintf(tracefile, "%u ", (int) time(NULL));
971         if (DEBUG_PID)
972                 fprintf(tracefile, "[%u] ", (int) getpid());
973         if (DEBUG_SIG)
974                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
975         va_start(va, fmt);
976         vfprintf(tracefile, fmt, va);
977         va_end(va);
978 }
979
980 static void
981 trace_vprintf(const char *fmt, va_list va)
982 {
983         if (debug != 1)
984                 return;
985         vfprintf(tracefile, fmt, va);
986         fprintf(tracefile, "\n");
987 }
988
989 static void
990 trace_puts(const char *s)
991 {
992         if (debug != 1)
993                 return;
994         fputs(s, tracefile);
995 }
996
997 static void
998 trace_puts_quoted(char *s)
999 {
1000         char *p;
1001         char c;
1002
1003         if (debug != 1)
1004                 return;
1005         putc('"', tracefile);
1006         for (p = s; *p; p++) {
1007                 switch ((unsigned char)*p) {
1008                 case '\n': c = 'n'; goto backslash;
1009                 case '\t': c = 't'; goto backslash;
1010                 case '\r': c = 'r'; goto backslash;
1011                 case '\"': c = '\"'; goto backslash;
1012                 case '\\': c = '\\'; goto backslash;
1013                 case CTLESC: c = 'e'; goto backslash;
1014                 case CTLVAR: c = 'v'; goto backslash;
1015                 case CTLBACKQ: c = 'q'; goto backslash;
1016  backslash:
1017                         putc('\\', tracefile);
1018                         putc(c, tracefile);
1019                         break;
1020                 default:
1021                         if (*p >= ' ' && *p <= '~')
1022                                 putc(*p, tracefile);
1023                         else {
1024                                 putc('\\', tracefile);
1025                                 putc((*p >> 6) & 03, tracefile);
1026                                 putc((*p >> 3) & 07, tracefile);
1027                                 putc(*p & 07, tracefile);
1028                         }
1029                         break;
1030                 }
1031         }
1032         putc('"', tracefile);
1033 }
1034
1035 static void
1036 trace_puts_args(char **ap)
1037 {
1038         if (debug != 1)
1039                 return;
1040         if (!*ap)
1041                 return;
1042         while (1) {
1043                 trace_puts_quoted(*ap);
1044                 if (!*++ap) {
1045                         putc('\n', tracefile);
1046                         break;
1047                 }
1048                 putc(' ', tracefile);
1049         }
1050 }
1051
1052 static void
1053 opentrace(void)
1054 {
1055         char s[100];
1056 #ifdef O_APPEND
1057         int flags;
1058 #endif
1059
1060         if (debug != 1) {
1061                 if (tracefile)
1062                         fflush(tracefile);
1063                 /* leave open because libedit might be using it */
1064                 return;
1065         }
1066         strcpy(s, "./trace");
1067         if (tracefile) {
1068                 if (!freopen(s, "a", tracefile)) {
1069                         fprintf(stderr, "Can't re-open %s\n", s);
1070                         debug = 0;
1071                         return;
1072                 }
1073         } else {
1074                 tracefile = fopen(s, "a");
1075                 if (tracefile == NULL) {
1076                         fprintf(stderr, "Can't open %s\n", s);
1077                         debug = 0;
1078                         return;
1079                 }
1080         }
1081 #ifdef O_APPEND
1082         flags = fcntl(fileno(tracefile), F_GETFL);
1083         if (flags >= 0)
1084                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
1085 #endif
1086         setlinebuf(tracefile);
1087         fputs("\nTracing started.\n", tracefile);
1088 }
1089
1090 static void
1091 indent(int amount, char *pfx, FILE *fp)
1092 {
1093         int i;
1094
1095         for (i = 0; i < amount; i++) {
1096                 if (pfx && i == amount - 1)
1097                         fputs(pfx, fp);
1098                 putc('\t', fp);
1099         }
1100 }
1101
1102 /* little circular references here... */
1103 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1104
1105 static void
1106 sharg(union node *arg, FILE *fp)
1107 {
1108         char *p;
1109         struct nodelist *bqlist;
1110         unsigned char subtype;
1111
1112         if (arg->type != NARG) {
1113                 out1fmt("<node type %d>\n", arg->type);
1114                 abort();
1115         }
1116         bqlist = arg->narg.backquote;
1117         for (p = arg->narg.text; *p; p++) {
1118                 switch ((unsigned char)*p) {
1119                 case CTLESC:
1120                         p++;
1121                         putc(*p, fp);
1122                         break;
1123                 case CTLVAR:
1124                         putc('$', fp);
1125                         putc('{', fp);
1126                         subtype = *++p;
1127                         if (subtype == VSLENGTH)
1128                                 putc('#', fp);
1129
1130                         while (*p != '=') {
1131                                 putc(*p, fp);
1132                                 p++;
1133                         }
1134
1135                         if (subtype & VSNUL)
1136                                 putc(':', fp);
1137
1138                         switch (subtype & VSTYPE) {
1139                         case VSNORMAL:
1140                                 putc('}', fp);
1141                                 break;
1142                         case VSMINUS:
1143                                 putc('-', fp);
1144                                 break;
1145                         case VSPLUS:
1146                                 putc('+', fp);
1147                                 break;
1148                         case VSQUESTION:
1149                                 putc('?', fp);
1150                                 break;
1151                         case VSASSIGN:
1152                                 putc('=', fp);
1153                                 break;
1154                         case VSTRIMLEFT:
1155                                 putc('#', fp);
1156                                 break;
1157                         case VSTRIMLEFTMAX:
1158                                 putc('#', fp);
1159                                 putc('#', fp);
1160                                 break;
1161                         case VSTRIMRIGHT:
1162                                 putc('%', fp);
1163                                 break;
1164                         case VSTRIMRIGHTMAX:
1165                                 putc('%', fp);
1166                                 putc('%', fp);
1167                                 break;
1168                         case VSLENGTH:
1169                                 break;
1170                         default:
1171                                 out1fmt("<subtype %d>", subtype);
1172                         }
1173                         break;
1174                 case CTLENDVAR:
1175                         putc('}', fp);
1176                         break;
1177                 case CTLBACKQ:
1178                         putc('$', fp);
1179                         putc('(', fp);
1180                         shtree(bqlist->n, -1, NULL, fp);
1181                         putc(')', fp);
1182                         break;
1183                 default:
1184                         putc(*p, fp);
1185                         break;
1186                 }
1187         }
1188 }
1189
1190 static void
1191 shcmd(union node *cmd, FILE *fp)
1192 {
1193         union node *np;
1194         int first;
1195         const char *s;
1196         int dftfd;
1197
1198         first = 1;
1199         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1200                 if (!first)
1201                         putc(' ', fp);
1202                 sharg(np, fp);
1203                 first = 0;
1204         }
1205         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1206                 if (!first)
1207                         putc(' ', fp);
1208                 dftfd = 0;
1209                 switch (np->nfile.type) {
1210                 case NTO:      s = ">>"+1; dftfd = 1; break;
1211                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1212                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1213 #if BASH_REDIR_OUTPUT
1214                 case NTO2:
1215 #endif
1216                 case NTOFD:    s = ">&"; dftfd = 1; break;
1217                 case NFROM:    s = "<"; break;
1218                 case NFROMFD:  s = "<&"; break;
1219                 case NFROMTO:  s = "<>"; break;
1220                 default:       s = "*error*"; break;
1221                 }
1222                 if (np->nfile.fd != dftfd)
1223                         fprintf(fp, "%d", np->nfile.fd);
1224                 fputs(s, fp);
1225                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1226                         fprintf(fp, "%d", np->ndup.dupfd);
1227                 } else {
1228                         sharg(np->nfile.fname, fp);
1229                 }
1230                 first = 0;
1231         }
1232 }
1233
1234 static void
1235 shtree(union node *n, int ind, char *pfx, FILE *fp)
1236 {
1237         struct nodelist *lp;
1238         const char *s;
1239
1240         if (n == NULL)
1241                 return;
1242
1243         indent(ind, pfx, fp);
1244
1245         if (n == NODE_EOF) {
1246                 fputs("<EOF>", fp);
1247                 return;
1248         }
1249
1250         switch (n->type) {
1251         case NSEMI:
1252                 s = "; ";
1253                 goto binop;
1254         case NAND:
1255                 s = " && ";
1256                 goto binop;
1257         case NOR:
1258                 s = " || ";
1259  binop:
1260                 shtree(n->nbinary.ch1, ind, NULL, fp);
1261                 /* if (ind < 0) */
1262                         fputs(s, fp);
1263                 shtree(n->nbinary.ch2, ind, NULL, fp);
1264                 break;
1265         case NCMD:
1266                 shcmd(n, fp);
1267                 if (ind >= 0)
1268                         putc('\n', fp);
1269                 break;
1270         case NPIPE:
1271                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1272                         shtree(lp->n, 0, NULL, fp);
1273                         if (lp->next)
1274                                 fputs(" | ", fp);
1275                 }
1276                 if (n->npipe.pipe_backgnd)
1277                         fputs(" &", fp);
1278                 if (ind >= 0)
1279                         putc('\n', fp);
1280                 break;
1281         default:
1282                 fprintf(fp, "<node type %d>", n->type);
1283                 if (ind >= 0)
1284                         putc('\n', fp);
1285                 break;
1286         }
1287 }
1288
1289 static void
1290 showtree(union node *n)
1291 {
1292         trace_puts("showtree called\n");
1293         shtree(n, 1, NULL, stderr);
1294 }
1295
1296 #endif /* DEBUG */
1297
1298
1299 /* ============ Parser data */
1300
1301 /*
1302  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1303  */
1304 struct strlist {
1305         struct strlist *next;
1306         char *text;
1307 };
1308
1309 struct alias;
1310
1311 struct strpush {
1312         struct strpush *prev;   /* preceding string on stack */
1313         char *prev_string;
1314         int prev_left_in_line;
1315 #if ENABLE_ASH_ALIAS
1316         struct alias *ap;       /* if push was associated with an alias */
1317 #endif
1318         char *string;           /* remember the string since it may change */
1319
1320         /* Remember last two characters for pungetc. */
1321         int lastc[2];
1322
1323         /* Number of outstanding calls to pungetc. */
1324         int unget;
1325 };
1326
1327 /*
1328  * The parsefile structure pointed to by the global variable parsefile
1329  * contains information about the current file being read.
1330  */
1331 struct parsefile {
1332         struct parsefile *prev; /* preceding file on stack */
1333         int linno;              /* current line */
1334         int pf_fd;              /* file descriptor (or -1 if string) */
1335         int left_in_line;       /* number of chars left in this line */
1336         int left_in_buffer;     /* number of chars left in this buffer past the line */
1337         char *next_to_pgetc;    /* next char in buffer */
1338         char *buf;              /* input buffer */
1339         struct strpush *strpush; /* for pushing strings at this level */
1340         struct strpush basestrpush; /* so pushing one is fast */
1341
1342         /* Remember last two characters for pungetc. */
1343         int lastc[2];
1344
1345         /* Number of outstanding calls to pungetc. */
1346         int unget;
1347 };
1348
1349 static struct parsefile basepf;        /* top level input file */
1350 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1351 static char *commandname;              /* currently executing command */
1352
1353
1354 /* ============ Message printing */
1355
1356 static void
1357 ash_vmsg(const char *msg, va_list ap)
1358 {
1359         fprintf(stderr, "%s: ", arg0);
1360         if (commandname) {
1361                 if (strcmp(arg0, commandname))
1362                         fprintf(stderr, "%s: ", commandname);
1363                 if (!iflag || g_parsefile->pf_fd > 0)
1364                         fprintf(stderr, "line %d: ", errlinno);
1365         }
1366         vfprintf(stderr, msg, ap);
1367         newline_and_flush(stderr);
1368 }
1369
1370 /*
1371  * Exverror is called to raise the error exception.  If the second argument
1372  * is not NULL then error prints an error message using printf style
1373  * formatting.  It then raises the error exception.
1374  */
1375 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1376 static void
1377 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1378 {
1379 #if DEBUG
1380         if (msg) {
1381                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1382                 TRACEV((msg, ap));
1383         } else
1384                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1385         if (msg)
1386 #endif
1387                 ash_vmsg(msg, ap);
1388
1389         flush_stdout_stderr();
1390         raise_exception(cond);
1391         /* NOTREACHED */
1392 }
1393
1394 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1395 static void
1396 ash_msg_and_raise_error(const char *msg, ...)
1397 {
1398         va_list ap;
1399
1400         exitstatus = 2;
1401
1402         va_start(ap, msg);
1403         ash_vmsg_and_raise(EXERROR, msg, ap);
1404         /* NOTREACHED */
1405         va_end(ap);
1406 }
1407
1408 /*
1409  * 'fmt' must be a string literal.
1410  */
1411 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": "STRERROR_FMT, ##__VA_ARGS__ STRERROR_ERRNO)
1412
1413 static void raise_error_syntax(const char *) NORETURN;
1414 static void
1415 raise_error_syntax(const char *msg)
1416 {
1417         errlinno = g_parsefile->linno;
1418         ash_msg_and_raise_error("syntax error: %s", msg);
1419         /* NOTREACHED */
1420 }
1421
1422 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1423 static void
1424 ash_msg_and_raise(int cond, const char *msg, ...)
1425 {
1426         va_list ap;
1427
1428         va_start(ap, msg);
1429         ash_vmsg_and_raise(cond, msg, ap);
1430         /* NOTREACHED */
1431         va_end(ap);
1432 }
1433
1434 /*
1435  * error/warning routines for external builtins
1436  */
1437 static void
1438 ash_msg(const char *fmt, ...)
1439 {
1440         va_list ap;
1441
1442         va_start(ap, fmt);
1443         ash_vmsg(fmt, ap);
1444         va_end(ap);
1445 }
1446
1447 /*
1448  * Return a string describing an error.  The returned string may be a
1449  * pointer to a static buffer that will be overwritten on the next call.
1450  * Action describes the operation that got the error.
1451  */
1452 static const char *
1453 errmsg(int e, const char *em)
1454 {
1455         if (e == ENOENT || e == ENOTDIR) {
1456                 return em;
1457         }
1458         return strerror(e);
1459 }
1460
1461
1462 /* ============ Memory allocation */
1463
1464 #if 0
1465 /* I consider these wrappers nearly useless:
1466  * ok, they return you to nearest exception handler, but
1467  * how much memory do you leak in the process, making
1468  * memory starvation worse?
1469  */
1470 static void *
1471 ckrealloc(void * p, size_t nbytes)
1472 {
1473         p = realloc(p, nbytes);
1474         if (!p)
1475                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1476         return p;
1477 }
1478
1479 static void *
1480 ckmalloc(size_t nbytes)
1481 {
1482         return ckrealloc(NULL, nbytes);
1483 }
1484
1485 static void *
1486 ckzalloc(size_t nbytes)
1487 {
1488         return memset(ckmalloc(nbytes), 0, nbytes);
1489 }
1490
1491 static char *
1492 ckstrdup(const char *s)
1493 {
1494         char *p = strdup(s);
1495         if (!p)
1496                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1497         return p;
1498 }
1499 #else
1500 /* Using bbox equivalents. They exit if out of memory */
1501 # define ckrealloc xrealloc
1502 # define ckmalloc  xmalloc
1503 # define ckzalloc  xzalloc
1504 # define ckstrdup  xstrdup
1505 #endif
1506
1507 /*
1508  * It appears that grabstackstr() will barf with such alignments
1509  * because stalloc() will return a string allocated in a new stackblock.
1510  */
1511 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1512 enum {
1513         /* Most machines require the value returned from malloc to be aligned
1514          * in some way.  The following macro will get this right
1515          * on many machines.  */
1516         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1517         /* Minimum size of a block */
1518         MINSIZE = SHELL_ALIGN(504),
1519 };
1520
1521 struct stack_block {
1522         struct stack_block *prev;
1523         char space[MINSIZE];
1524 };
1525
1526 struct stackmark {
1527         struct stack_block *stackp;
1528         char *stacknxt;
1529         size_t stacknleft;
1530 };
1531
1532
1533 struct globals_memstack {
1534         struct stack_block *g_stackp; // = &stackbase;
1535         char *g_stacknxt; // = stackbase.space;
1536         char *sstrend; // = stackbase.space + MINSIZE;
1537         size_t g_stacknleft; // = MINSIZE;
1538         struct stack_block stackbase;
1539 };
1540 extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack;
1541 #define G_memstack (*ash_ptr_to_globals_memstack)
1542 #define g_stackp     (G_memstack.g_stackp    )
1543 #define g_stacknxt   (G_memstack.g_stacknxt  )
1544 #define sstrend      (G_memstack.sstrend     )
1545 #define g_stacknleft (G_memstack.g_stacknleft)
1546 #define stackbase    (G_memstack.stackbase   )
1547 #define INIT_G_memstack() do { \
1548         (*(struct globals_memstack**)not_const_pp(&ash_ptr_to_globals_memstack)) = xzalloc(sizeof(G_memstack)); \
1549         barrier(); \
1550         g_stackp = &stackbase; \
1551         g_stacknxt = stackbase.space; \
1552         g_stacknleft = MINSIZE; \
1553         sstrend = stackbase.space + MINSIZE; \
1554 } while (0)
1555
1556
1557 #define stackblock()     ((void *)g_stacknxt)
1558 #define stackblocksize() g_stacknleft
1559
1560 /*
1561  * Parse trees for commands are allocated in lifo order, so we use a stack
1562  * to make this more efficient, and also to avoid all sorts of exception
1563  * handling code to handle interrupts in the middle of a parse.
1564  *
1565  * The size 504 was chosen because the Ultrix malloc handles that size
1566  * well.
1567  */
1568 static void *
1569 stalloc(size_t nbytes)
1570 {
1571         char *p;
1572         size_t aligned;
1573
1574         aligned = SHELL_ALIGN(nbytes);
1575         if (aligned > g_stacknleft) {
1576                 size_t len;
1577                 size_t blocksize;
1578                 struct stack_block *sp;
1579
1580                 blocksize = aligned;
1581                 if (blocksize < MINSIZE)
1582                         blocksize = MINSIZE;
1583                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1584                 if (len < blocksize)
1585                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1586                 INT_OFF;
1587                 sp = ckmalloc(len);
1588                 sp->prev = g_stackp;
1589                 g_stacknxt = sp->space;
1590                 g_stacknleft = blocksize;
1591                 sstrend = g_stacknxt + blocksize;
1592                 g_stackp = sp;
1593                 INT_ON;
1594         }
1595         p = g_stacknxt;
1596         g_stacknxt += aligned;
1597         g_stacknleft -= aligned;
1598         return p;
1599 }
1600
1601 static void *
1602 stzalloc(size_t nbytes)
1603 {
1604         return memset(stalloc(nbytes), 0, nbytes);
1605 }
1606
1607 static void
1608 stunalloc(void *p)
1609 {
1610 #if DEBUG
1611         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1612                 write(STDERR_FILENO, "stunalloc\n", 10);
1613                 abort();
1614         }
1615 #endif
1616         g_stacknleft += g_stacknxt - (char *)p;
1617         g_stacknxt = p;
1618 }
1619
1620 /*
1621  * Like strdup but works with the ash stack.
1622  */
1623 static char *
1624 sstrdup(const char *p)
1625 {
1626         size_t len = strlen(p) + 1;
1627         return memcpy(stalloc(len), p, len);
1628 }
1629
1630 static ALWAYS_INLINE void
1631 grabstackblock(size_t len)
1632 {
1633         stalloc(len);
1634 }
1635
1636 static void
1637 pushstackmark(struct stackmark *mark, size_t len)
1638 {
1639         mark->stackp = g_stackp;
1640         mark->stacknxt = g_stacknxt;
1641         mark->stacknleft = g_stacknleft;
1642         grabstackblock(len);
1643 }
1644
1645 static void
1646 setstackmark(struct stackmark *mark)
1647 {
1648         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1649 }
1650
1651 static void
1652 popstackmark(struct stackmark *mark)
1653 {
1654         struct stack_block *sp;
1655
1656         if (!mark->stackp)
1657                 return;
1658
1659         INT_OFF;
1660         while (g_stackp != mark->stackp) {
1661                 sp = g_stackp;
1662                 g_stackp = sp->prev;
1663                 free(sp);
1664         }
1665         g_stacknxt = mark->stacknxt;
1666         g_stacknleft = mark->stacknleft;
1667         sstrend = mark->stacknxt + mark->stacknleft;
1668         INT_ON;
1669 }
1670
1671 /*
1672  * When the parser reads in a string, it wants to stick the string on the
1673  * stack and only adjust the stack pointer when it knows how big the
1674  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1675  * of space on top of the stack and stackblocklen returns the length of
1676  * this block.  Growstackblock will grow this space by at least one byte,
1677  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1678  * part of the block that has been used.
1679  */
1680 static void
1681 growstackblock(void)
1682 {
1683         size_t newlen;
1684
1685         newlen = g_stacknleft * 2;
1686         if (newlen < g_stacknleft)
1687                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1688         if (newlen < 128)
1689                 newlen += 128;
1690
1691         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1692                 struct stack_block *sp;
1693                 struct stack_block *prevstackp;
1694                 size_t grosslen;
1695
1696                 INT_OFF;
1697                 sp = g_stackp;
1698                 prevstackp = sp->prev;
1699                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1700                 sp = ckrealloc(sp, grosslen);
1701                 sp->prev = prevstackp;
1702                 g_stackp = sp;
1703                 g_stacknxt = sp->space;
1704                 g_stacknleft = newlen;
1705                 sstrend = sp->space + newlen;
1706                 INT_ON;
1707         } else {
1708                 char *oldspace = g_stacknxt;
1709                 size_t oldlen = g_stacknleft;
1710                 char *p = stalloc(newlen);
1711
1712                 /* free the space we just allocated */
1713                 g_stacknxt = memcpy(p, oldspace, oldlen);
1714                 g_stacknleft += newlen;
1715         }
1716 }
1717
1718 /*
1719  * The following routines are somewhat easier to use than the above.
1720  * The user declares a variable of type STACKSTR, which may be declared
1721  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1722  * the user uses the macro STPUTC to add characters to the string.  In
1723  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1724  * grown as necessary.  When the user is done, she can just leave the
1725  * string there and refer to it using stackblock().  Or she can allocate
1726  * the space for it using grabstackstr().  If it is necessary to allow
1727  * someone else to use the stack temporarily and then continue to grow
1728  * the string, the user should use grabstack to allocate the space, and
1729  * then call ungrabstr(p) to return to the previous mode of operation.
1730  *
1731  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1732  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1733  * is space for at least one character.
1734  */
1735 static void *
1736 growstackstr(void)
1737 {
1738         size_t len = stackblocksize();
1739         growstackblock();
1740         return (char *)stackblock() + len;
1741 }
1742
1743 static char *
1744 growstackto(size_t len)
1745 {
1746         while (stackblocksize() < len)
1747                 growstackblock();
1748
1749         return stackblock();
1750 }
1751
1752 /*
1753  * Called from CHECKSTRSPACE.
1754  */
1755 static char *
1756 makestrspace(size_t newlen, char *p)
1757 {
1758         size_t len = p - g_stacknxt;
1759
1760         return growstackto(len + newlen) + len;
1761 }
1762
1763 static char *
1764 stack_nputstr(const char *s, size_t n, char *p)
1765 {
1766         p = makestrspace(n, p);
1767         p = (char *)mempcpy(p, s, n);
1768         return p;
1769 }
1770
1771 static char *
1772 stack_putstr(const char *s, char *p)
1773 {
1774         return stack_nputstr(s, strlen(s), p);
1775 }
1776
1777 static char *
1778 _STPUTC(int c, char *p)
1779 {
1780         if (p == sstrend)
1781                 p = growstackstr();
1782         *p++ = c;
1783         return p;
1784 }
1785
1786 #define STARTSTACKSTR(p)        ((p) = stackblock())
1787 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1788 #define CHECKSTRSPACE(n, p) do { \
1789         char *q = (p); \
1790         size_t l = (n); \
1791         size_t m = sstrend - q; \
1792         if (l > m) \
1793                 (p) = makestrspace(l, q); \
1794 } while (0)
1795 #define USTPUTC(c, p)           (*(p)++ = (c))
1796 #define STACKSTRNUL(p) do { \
1797         if ((p) == sstrend) \
1798                 (p) = growstackstr(); \
1799         *(p) = '\0'; \
1800 } while (0)
1801 #define STUNPUTC(p)             (--(p))
1802 #define STTOPC(p)               ((p)[-1])
1803 #define STADJUST(amount, p)     ((p) += (amount))
1804
1805 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1806 #define ungrabstackstr(s, p)    stunalloc(s)
1807 #define stackstrend()           ((void *)sstrend)
1808
1809
1810 /* ============ String helpers */
1811
1812 /*
1813  * prefix -- see if pfx is a prefix of string.
1814  */
1815 static char *
1816 prefix(const char *string, const char *pfx)
1817 {
1818         while (*pfx) {
1819                 if (*pfx++ != *string++)
1820                         return NULL;
1821         }
1822         return (char *) string;
1823 }
1824
1825 /*
1826  * Check for a valid number.  This should be elsewhere.
1827  */
1828 static int
1829 is_number(const char *p)
1830 {
1831         do {
1832                 if (!isdigit(*p))
1833                         return 0;
1834         } while (*++p != '\0');
1835         return 1;
1836 }
1837
1838 /*
1839  * Convert a string of digits to an integer, printing an error message on
1840  * failure.
1841  */
1842 static int
1843 number(const char *s)
1844 {
1845         if (!is_number(s))
1846                 ash_msg_and_raise_error(msg_illnum, s);
1847         return atoi(s);
1848 }
1849
1850 /*
1851  * Produce a single quoted string suitable as input to the shell.
1852  * The return string is allocated on the stack.
1853  */
1854 static char *
1855 single_quote(const char *s)
1856 {
1857         char *p;
1858
1859         STARTSTACKSTR(p);
1860
1861         do {
1862                 char *q;
1863                 size_t len;
1864
1865                 len = strchrnul(s, '\'') - s;
1866
1867                 q = p = makestrspace(len + 3, p);
1868
1869                 *q++ = '\'';
1870                 q = (char *)mempcpy(q, s, len);
1871                 *q++ = '\'';
1872                 s += len;
1873
1874                 STADJUST(q - p, p);
1875
1876                 if (*s != '\'')
1877                         break;
1878                 len = 0;
1879                 do len++; while (*++s == '\'');
1880
1881                 q = p = makestrspace(len + 3, p);
1882
1883                 *q++ = '"';
1884                 q = (char *)mempcpy(q, s - len, len);
1885                 *q++ = '"';
1886
1887                 STADJUST(q - p, p);
1888         } while (*s);
1889
1890         USTPUTC('\0', p);
1891
1892         return stackblock();
1893 }
1894
1895 /*
1896  * Produce a possibly single quoted string suitable as input to the shell.
1897  * If quoting was done, the return string is allocated on the stack,
1898  * otherwise a pointer to the original string is returned.
1899  */
1900 static const char *
1901 maybe_single_quote(const char *s)
1902 {
1903         const char *p = s;
1904
1905         while (*p) {
1906                 /* Assuming ACSII */
1907                 /* quote ctrl_chars space !"#$%&'()* */
1908                 if (*p < '+')
1909                         goto need_quoting;
1910                 /* quote ;<=>? */
1911                 if (*p >= ';' && *p <= '?')
1912                         goto need_quoting;
1913                 /* quote `[\ */
1914                 if (*p == '`')
1915                         goto need_quoting;
1916                 if (*p == '[')
1917                         goto need_quoting;
1918                 if (*p == '\\')
1919                         goto need_quoting;
1920                 /* quote {|}~ DEL and high bytes */
1921                 if (*p > 'z')
1922                         goto need_quoting;
1923                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1924                 /* TODO: maybe avoid quoting % */
1925                 p++;
1926         }
1927         return s;
1928
1929  need_quoting:
1930         return single_quote(s);
1931 }
1932
1933
1934 /* ============ nextopt */
1935
1936 static char **argptr;                  /* argument list for builtin commands */
1937 static char *optionarg;                /* set by nextopt (like getopt) */
1938 static char *optptr;                   /* used by nextopt */
1939
1940 /*
1941  * XXX - should get rid of. Have all builtins use getopt(3).
1942  * The library getopt must have the BSD extension static variable
1943  * "optreset", otherwise it can't be used within the shell safely.
1944  *
1945  * Standard option processing (a la getopt) for builtin routines.
1946  * The only argument that is passed to nextopt is the option string;
1947  * the other arguments are unnecessary. It returns the character,
1948  * or '\0' on end of input.
1949  */
1950 static int
1951 nextopt(const char *optstring)
1952 {
1953         char *p;
1954         const char *q;
1955         char c;
1956
1957         p = optptr;
1958         if (p == NULL || *p == '\0') {
1959                 /* We ate entire "-param", take next one */
1960                 p = *argptr;
1961                 if (p == NULL)
1962                         return '\0';
1963                 if (*p != '-')
1964                         return '\0';
1965                 if (*++p == '\0') /* just "-" ? */
1966                         return '\0';
1967                 argptr++;
1968                 if (LONE_DASH(p)) /* "--" ? */
1969                         return '\0';
1970                 /* p => next "-param" */
1971         }
1972         /* p => some option char in the middle of a "-param" */
1973         c = *p++;
1974         for (q = optstring; *q != c;) {
1975                 if (*q == '\0')
1976                         ash_msg_and_raise_error("illegal option -%c", c);
1977                 if (*++q == ':')
1978                         q++;
1979         }
1980         if (*++q == ':') {
1981                 if (*p == '\0') {
1982                         p = *argptr++;
1983                         if (p == NULL)
1984                                 ash_msg_and_raise_error("no arg for -%c option", c);
1985                 }
1986                 optionarg = p;
1987                 p = NULL;
1988         }
1989         optptr = p;
1990         return c;
1991 }
1992
1993
1994 /* ============ Shell variables */
1995
1996 struct shparam {
1997         int nparam;             /* # of positional parameters (without $0) */
1998 #if ENABLE_ASH_GETOPTS
1999         int optind;             /* next parameter to be processed by getopts */
2000         int optoff;             /* used by getopts */
2001 #endif
2002         unsigned char malloced; /* if parameter list dynamically allocated */
2003         char **p;               /* parameter list */
2004 };
2005
2006 /*
2007  * Free the list of positional parameters.
2008  */
2009 static void
2010 freeparam(volatile struct shparam *param)
2011 {
2012         if (param->malloced) {
2013                 char **ap, **ap1;
2014                 ap = ap1 = param->p;
2015                 while (*ap)
2016                         free(*ap++);
2017                 free(ap1);
2018         }
2019 }
2020
2021 #if ENABLE_ASH_GETOPTS
2022 static void FAST_FUNC getoptsreset(const char *value);
2023 #endif
2024
2025 struct var {
2026         struct var *next;               /* next entry in hash list */
2027         int flags;                      /* flags are defined above */
2028         const char *var_text;           /* name=value */
2029         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
2030                                         /* the variable gets set/unset */
2031 };
2032
2033 struct localvar {
2034         struct localvar *next;          /* next local variable in list */
2035         struct var *vp;                 /* the variable that was made local */
2036         int flags;                      /* saved flags */
2037         const char *text;               /* saved text */
2038 };
2039
2040 /* flags */
2041 #define VEXPORT         0x01    /* variable is exported */
2042 #define VREADONLY       0x02    /* variable cannot be modified */
2043 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
2044 #define VTEXTFIXED      0x08    /* text is statically allocated */
2045 #define VSTACK          0x10    /* text is allocated on the stack */
2046 #define VUNSET          0x20    /* the variable is not set */
2047 #define VNOFUNC         0x40    /* don't call the callback function */
2048 #define VNOSET          0x80    /* do not set variable - just readonly test */
2049 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
2050 #if ENABLE_ASH_RANDOM_SUPPORT
2051 # define VDYNAMIC       0x200   /* dynamic variable */
2052 #else
2053 # define VDYNAMIC       0
2054 #endif
2055
2056
2057 /* Need to be before varinit_data[] */
2058 #if ENABLE_LOCALE_SUPPORT
2059 static void FAST_FUNC
2060 change_lc_all(const char *value)
2061 {
2062         if (value && *value != '\0')
2063                 setlocale(LC_ALL, value);
2064 }
2065 static void FAST_FUNC
2066 change_lc_ctype(const char *value)
2067 {
2068         if (value && *value != '\0')
2069                 setlocale(LC_CTYPE, value);
2070 }
2071 #endif
2072 #if ENABLE_ASH_MAIL
2073 static void chkmail(void);
2074 static void changemail(const char *var_value) FAST_FUNC;
2075 #else
2076 # define chkmail()  ((void)0)
2077 #endif
2078 static void changepath(const char *) FAST_FUNC;
2079 #if ENABLE_ASH_RANDOM_SUPPORT
2080 static void change_random(const char *) FAST_FUNC;
2081 #endif
2082 #if BASH_EPOCH_VARS
2083 static void change_seconds(const char *) FAST_FUNC;
2084 static void change_realtime(const char *) FAST_FUNC;
2085 #endif
2086
2087 static const struct {
2088         int flags;
2089         const char *var_text;
2090         void (*var_func)(const char *) FAST_FUNC;
2091 } varinit_data[] = {
2092         /*
2093          * Note: VEXPORT would not work correctly here for NOFORK applets:
2094          * some environment strings may be constant.
2095          */
2096         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2097 #if ENABLE_ASH_MAIL
2098         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2099         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2100 #endif
2101         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2102         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2103         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2104         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2105 #if ENABLE_ASH_GETOPTS
2106         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2107 #endif
2108         { VSTRFIXED|VTEXTFIXED       , NULL /* inited to linenovar */, NULL },
2109 #if ENABLE_ASH_RANDOM_SUPPORT
2110         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2111 #endif
2112 #if BASH_EPOCH_VARS
2113         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "EPOCHSECONDS", change_seconds },
2114         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "EPOCHREALTIME", change_realtime },
2115 #endif
2116 #if ENABLE_LOCALE_SUPPORT
2117         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2118         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2119 #endif
2120 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2121         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2122 #endif
2123 };
2124
2125 struct redirtab;
2126
2127 struct globals_var {
2128         struct shparam shellparam;      /* $@ current positional parameters */
2129         struct redirtab *redirlist;
2130         int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2131         struct var *vartab[VTABSIZE];
2132         struct var varinit[ARRAY_SIZE(varinit_data)];
2133         int lineno;
2134         char linenovar[sizeof("LINENO=") + sizeof(int)*3];
2135 };
2136 extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var;
2137 #define G_var (*ash_ptr_to_globals_var)
2138 #define shellparam    (G_var.shellparam   )
2139 //#define redirlist     (G_var.redirlist    )
2140 #define preverrout_fd (G_var.preverrout_fd)
2141 #define vartab        (G_var.vartab       )
2142 #define varinit       (G_var.varinit      )
2143 #define lineno        (G_var.lineno       )
2144 #define linenovar     (G_var.linenovar    )
2145 #define vifs      varinit[0]
2146 #if ENABLE_ASH_MAIL
2147 # define vmail    varinit[1]
2148 # define vmpath   varinit[2]
2149 #endif
2150 #define VAR_OFFSET1 (ENABLE_ASH_MAIL*2)
2151 #define vpath     varinit[VAR_OFFSET1 + 1]
2152 #define vps1      varinit[VAR_OFFSET1 + 2]
2153 #define vps2      varinit[VAR_OFFSET1 + 3]
2154 #define vps4      varinit[VAR_OFFSET1 + 4]
2155 #if ENABLE_ASH_GETOPTS
2156 # define voptind  varinit[VAR_OFFSET1 + 5]
2157 #endif
2158 #define VAR_OFFSET2 (VAR_OFFSET1 + ENABLE_ASH_GETOPTS)
2159 #define vlineno   varinit[VAR_OFFSET2 + 5]
2160 #if ENABLE_ASH_RANDOM_SUPPORT
2161 # define vrandom  varinit[VAR_OFFSET2 + 6]
2162 #endif
2163 #define VAR_OFFSET3 (VAR_OFFSET2 + ENABLE_ASH_RANDOM_SUPPORT)
2164 #if BASH_EPOCH_VARS
2165 # define vepochs  varinit[VAR_OFFSET3 + 6]
2166 # define vepochr  varinit[VAR_OFFSET3 + 7]
2167 #endif
2168 #define INIT_G_var() do { \
2169         unsigned i; \
2170         (*(struct globals_var**)not_const_pp(&ash_ptr_to_globals_var)) = xzalloc(sizeof(G_var)); \
2171         barrier(); \
2172         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2173                 varinit[i].flags    = varinit_data[i].flags; \
2174                 varinit[i].var_text = varinit_data[i].var_text; \
2175                 varinit[i].var_func = varinit_data[i].var_func; \
2176         } \
2177         strcpy(linenovar, "LINENO="); \
2178         vlineno.var_text = linenovar; \
2179 } while (0)
2180
2181 /*
2182  * The following macros access the values of the above variables.
2183  * They have to skip over the name.  They return the null string
2184  * for unset variables.
2185  */
2186 #define ifsval()        (vifs.var_text + 4)
2187 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2188 #if ENABLE_ASH_MAIL
2189 # define mailval()      (vmail.var_text + 5)
2190 # define mpathval()     (vmpath.var_text + 9)
2191 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2192 #endif
2193 #define pathval()       (vpath.var_text + 5)
2194 #define ps1val()        (vps1.var_text + 4)
2195 #define ps2val()        (vps2.var_text + 4)
2196 #define ps4val()        (vps4.var_text + 4)
2197 #if ENABLE_ASH_GETOPTS
2198 # define optindval()    (voptind.var_text + 7)
2199 #endif
2200
2201 #if ENABLE_ASH_GETOPTS
2202 static void FAST_FUNC
2203 getoptsreset(const char *value)
2204 {
2205         shellparam.optind = 1;
2206         if (is_number(value))
2207                 shellparam.optind = number(value) ?: 1;
2208         shellparam.optoff = -1;
2209 }
2210 #endif
2211
2212 /*
2213  * Compares two strings up to the first = or '\0'.  The first
2214  * string must be terminated by '='; the second may be terminated by
2215  * either '=' or '\0'.
2216  */
2217 static int
2218 varcmp(const char *p, const char *q)
2219 {
2220         int c, d;
2221
2222         while ((c = *p) == (d = *q)) {
2223                 if (c == '\0' || c == '=')
2224                         goto out;
2225                 p++;
2226                 q++;
2227         }
2228         if (c == '=')
2229                 c = '\0';
2230         if (d == '=')
2231                 d = '\0';
2232  out:
2233         return c - d;
2234 }
2235
2236 /*
2237  * Find the appropriate entry in the hash table from the name.
2238  */
2239 static struct var **
2240 hashvar(const char *p)
2241 {
2242         unsigned hashval;
2243
2244         hashval = ((unsigned char) *p) << 4;
2245         while (*p && *p != '=')
2246                 hashval += (unsigned char) *p++;
2247         return &vartab[hashval % VTABSIZE];
2248 }
2249
2250 static int
2251 vpcmp(const void *a, const void *b)
2252 {
2253         return varcmp(*(const char **)a, *(const char **)b);
2254 }
2255
2256 /*
2257  * This routine initializes the builtin variables.
2258  */
2259 static void
2260 initvar(void)
2261 {
2262         struct var *vp;
2263         struct var *end;
2264         struct var **vpp;
2265
2266         /*
2267          * PS1 depends on uid
2268          */
2269 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2270         vps1.var_text = "PS1=\\w \\$ ";
2271 #else
2272         if (!geteuid())
2273                 vps1.var_text = "PS1=# ";
2274 #endif
2275         vp = varinit;
2276         end = vp + ARRAY_SIZE(varinit);
2277         do {
2278                 vpp = hashvar(vp->var_text);
2279                 vp->next = *vpp;
2280                 *vpp = vp;
2281         } while (++vp < end);
2282 }
2283
2284 static struct var **
2285 findvar(struct var **vpp, const char *name)
2286 {
2287         for (; *vpp; vpp = &(*vpp)->next) {
2288                 if (varcmp((*vpp)->var_text, name) == 0) {
2289                         break;
2290                 }
2291         }
2292         return vpp;
2293 }
2294
2295 /*
2296  * Find the value of a variable.  Returns NULL if not set.
2297  */
2298 static const char* FAST_FUNC
2299 lookupvar(const char *name)
2300 {
2301         struct var *v;
2302
2303         v = *findvar(hashvar(name), name);
2304         if (v) {
2305 #if ENABLE_ASH_RANDOM_SUPPORT || BASH_EPOCH_VARS
2306         /*
2307          * Dynamic variables are implemented roughly the same way they are
2308          * in bash. Namely, they're "special" so long as they aren't unset.
2309          * As soon as they're unset, they're no longer dynamic, and dynamic
2310          * lookup will no longer happen at that point. -- PFM.
2311          */
2312                 if (v->flags & VDYNAMIC)
2313                         v->var_func(NULL);
2314 #endif
2315                 if (!(v->flags & VUNSET)) {
2316                         if (v == &vlineno && v->var_text == linenovar) {
2317                                 fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno);
2318                         }
2319                         return var_end(v->var_text);
2320                 }
2321         }
2322         return NULL;
2323 }
2324
2325 #if ENABLE_UNICODE_SUPPORT
2326 static void
2327 reinit_unicode_for_ash(void)
2328 {
2329         /* Unicode support should be activated even if LANG is set
2330          * _during_ shell execution, not only if it was set when
2331          * shell was started. Therefore, re-check LANG every time:
2332          */
2333         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2334          || ENABLE_UNICODE_USING_LOCALE
2335         ) {
2336                 const char *s = lookupvar("LC_ALL");
2337                 if (!s) s = lookupvar("LC_CTYPE");
2338                 if (!s) s = lookupvar("LANG");
2339                 reinit_unicode(s);
2340         }
2341 }
2342 #else
2343 # define reinit_unicode_for_ash() ((void)0)
2344 #endif
2345
2346 /*
2347  * Search the environment of a builtin command.
2348  */
2349 static ALWAYS_INLINE const char *
2350 bltinlookup(const char *name)
2351 {
2352         return lookupvar(name);
2353 }
2354
2355 /*
2356  * Same as setvar except that the variable and value are passed in
2357  * the first argument as name=value.  Since the first argument will
2358  * be actually stored in the table, it should not be a string that
2359  * will go away.
2360  * Called with interrupts off.
2361  */
2362 static struct var *
2363 setvareq(char *s, int flags)
2364 {
2365         struct var *vp, **vpp;
2366
2367         vpp = hashvar(s);
2368         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2369         vpp = findvar(vpp, s);
2370         vp = *vpp;
2371         if (vp) {
2372                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2373                         const char *n;
2374
2375                         if (flags & VNOSAVE)
2376                                 free(s);
2377                         n = vp->var_text;
2378                         exitstatus = 1;
2379                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2380                 }
2381
2382                 if (flags & VNOSET)
2383                         goto out;
2384
2385                 if (vp->var_func && !(flags & VNOFUNC))
2386                         vp->var_func(var_end(s));
2387
2388                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2389                         free((char*)vp->var_text);
2390
2391                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2392                         *vpp = vp->next;
2393                         free(vp);
2394  out_free:
2395                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2396                                 free(s);
2397                         goto out;
2398                 }
2399
2400                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2401 #if ENABLE_ASH_RANDOM_SUPPORT || BASH_EPOCH_VARS
2402                 if (flags & VUNSET)
2403                         flags &= ~VDYNAMIC;
2404 #endif
2405         } else {
2406                 /* variable s is not found */
2407                 if (flags & VNOSET)
2408                         goto out;
2409                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2410                         goto out_free;
2411                 vp = ckzalloc(sizeof(*vp));
2412                 vp->next = *vpp;
2413                 /*vp->func = NULL; - ckzalloc did it */
2414                 *vpp = vp;
2415         }
2416         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2417                 s = ckstrdup(s);
2418         vp->var_text = s;
2419         vp->flags = flags;
2420
2421  out:
2422         return vp;
2423 }
2424
2425 /*
2426  * Set the value of a variable.  The flags argument is ored with the
2427  * flags of the variable.  If val is NULL, the variable is unset.
2428  */
2429 static struct var *
2430 setvar(const char *name, const char *val, int flags)
2431 {
2432         const char *q;
2433         char *p;
2434         char *nameeq;
2435         size_t namelen;
2436         size_t vallen;
2437         struct var *vp;
2438
2439         q = endofname(name);
2440         p = strchrnul(q, '=');
2441         namelen = p - name;
2442         if (!namelen || p != q)
2443                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2444         vallen = 0;
2445         if (val == NULL) {
2446                 flags |= VUNSET;
2447         } else {
2448                 vallen = strlen(val);
2449         }
2450
2451         INT_OFF;
2452         nameeq = ckzalloc(namelen + vallen + 2);
2453         p = mempcpy(nameeq, name, namelen);
2454         if (val) {
2455                 *p++ = '=';
2456                 memcpy(p, val, vallen);
2457         }
2458         vp = setvareq(nameeq, flags | VNOSAVE);
2459         INT_ON;
2460
2461         return vp;
2462 }
2463
2464 static void FAST_FUNC
2465 setvar0(const char *name, const char *val)
2466 {
2467         setvar(name, val, 0);
2468 }
2469
2470 /*
2471  * Unset the specified variable.
2472  */
2473 static void
2474 unsetvar(const char *s)
2475 {
2476         setvar(s, NULL, 0);
2477 }
2478
2479 /*
2480  * Process a linked list of variable assignments.
2481  */
2482 static void
2483 listsetvar(struct strlist *list_set_var, int flags)
2484 {
2485         struct strlist *lp = list_set_var;
2486
2487         if (!lp)
2488                 return;
2489         INT_OFF;
2490         do {
2491                 setvareq(lp->text, flags);
2492                 lp = lp->next;
2493         } while (lp);
2494         INT_ON;
2495 }
2496
2497 /*
2498  * Generate a list of variables satisfying the given conditions.
2499  */
2500 #if !ENABLE_FEATURE_SH_NOFORK
2501 # define listvars(on, off, lp, end) listvars(on, off, end)
2502 #endif
2503 static char **
2504 listvars(int on, int off, struct strlist *lp, char ***end)
2505 {
2506         struct var **vpp;
2507         struct var *vp;
2508         char **ep;
2509         int mask;
2510
2511         STARTSTACKSTR(ep);
2512         vpp = vartab;
2513         mask = on | off;
2514         do {
2515                 for (vp = *vpp; vp; vp = vp->next) {
2516                         if ((vp->flags & mask) == on) {
2517 #if ENABLE_FEATURE_SH_NOFORK
2518                                 /* If variable with the same name is both
2519                                  * exported and temporarily set for a command:
2520                                  *  export ZVAR=5
2521                                  *  ZVAR=6 printenv
2522                                  * then "ZVAR=6" will be both in vartab and
2523                                  * lp lists. Do not pass it twice to printenv.
2524                                  */
2525                                 struct strlist *lp1 = lp;
2526                                 while (lp1) {
2527                                         if (strcmp(lp1->text, vp->var_text) == 0)
2528                                                 goto skip;
2529                                         lp1 = lp1->next;
2530                                 }
2531 #endif
2532                                 if (ep == stackstrend())
2533                                         ep = growstackstr();
2534                                 *ep++ = (char*)vp->var_text;
2535 #if ENABLE_FEATURE_SH_NOFORK
2536  skip: ;
2537 #endif
2538                         }
2539                 }
2540         } while (++vpp < vartab + VTABSIZE);
2541
2542 #if ENABLE_FEATURE_SH_NOFORK
2543         while (lp) {
2544                 if (ep == stackstrend())
2545                         ep = growstackstr();
2546                 *ep++ = lp->text;
2547                 lp = lp->next;
2548         }
2549 #endif
2550
2551         if (ep == stackstrend())
2552                 ep = growstackstr();
2553         if (end)
2554                 *end = ep;
2555         *ep++ = NULL;
2556         return grabstackstr(ep);
2557 }
2558
2559
2560 /* ============ Path search helper */
2561 static const char *
2562 legal_pathopt(const char *opt, const char *term, int magic)
2563 {
2564         switch (magic) {
2565         case 0:
2566                 opt = NULL;
2567                 break;
2568
2569         case 1:
2570                 opt = prefix(opt, "builtin") ?: prefix(opt, "func");
2571                 break;
2572
2573         default:
2574                 opt += strcspn(opt, term);
2575                 break;
2576         }
2577
2578         if (opt && *opt == '%')
2579                 opt++;
2580
2581         return opt;
2582 }
2583
2584 /*
2585  * The variable path (passed by reference) should be set to the start
2586  * of the path before the first call; padvance will update
2587  * this value as it proceeds.  Successive calls to padvance will return
2588  * the possible path expansions in sequence.  If an option (indicated by
2589  * a percent sign) appears in the path entry then the global variable
2590  * pathopt will be set to point to it; otherwise pathopt will be set to
2591  * NULL.
2592  *
2593  * If magic is 0 then pathopt recognition will be disabled.  If magic is
2594  * 1 we shall recognise %builtin/%func.  Otherwise we shall accept any
2595  * pathopt.
2596  */
2597 static const char *pathopt;     /* set by padvance */
2598
2599 static int
2600 padvance_magic(const char **path, const char *name, int magic)
2601 {
2602         const char *term = "%:";
2603         const char *lpathopt;
2604         const char *p;
2605         char *q;
2606         const char *start;
2607         size_t qlen;
2608         size_t len;
2609
2610         if (*path == NULL)
2611                 return -1;
2612
2613         lpathopt = NULL;
2614         start = *path;
2615
2616         if (*start == '%' && (p = legal_pathopt(start + 1, term, magic))) {
2617                 lpathopt = start + 1;
2618                 start = p;
2619                 term = ":";
2620         }
2621
2622         len = strcspn(start, term);
2623         p = start + len;
2624
2625         if (*p == '%') {
2626                 size_t extra = strchrnul(p, ':') - p;
2627
2628                 if (legal_pathopt(p + 1, term, magic))
2629                         lpathopt = p + 1;
2630                 else
2631                         len += extra;
2632
2633                 p += extra;
2634         }
2635
2636         pathopt = lpathopt;
2637         *path = *p == ':' ? p + 1 : NULL;
2638
2639         /* "2" is for '/' and '\0' */
2640         qlen = len + strlen(name) + 2;
2641         q = growstackto(qlen);
2642
2643         if (len) {
2644                 q = mempcpy(q, start, len);
2645                 *q++ = '/';
2646         }
2647         strcpy(q, name);
2648
2649         return qlen;
2650 }
2651
2652 static int
2653 padvance(const char **path, const char *name)
2654 {
2655         return padvance_magic(path, name, 1);
2656 }
2657
2658
2659 /* ============ Prompt */
2660
2661 static smallint doprompt;                   /* if set, prompt the user */
2662 static smallint needprompt;                 /* true if interactive and at start of line */
2663
2664 #if ENABLE_FEATURE_EDITING
2665 static line_input_t *line_input_state;
2666 static const char *cmdedit_prompt;
2667 static void
2668 putprompt(const char *s)
2669 {
2670         if (ENABLE_ASH_EXPAND_PRMT) {
2671                 free((char*)cmdedit_prompt);
2672                 cmdedit_prompt = ckstrdup(s);
2673                 return;
2674         }
2675         cmdedit_prompt = s;
2676 }
2677 #else
2678 static void
2679 putprompt(const char *s)
2680 {
2681         out2str(s);
2682 }
2683 #endif
2684
2685 /* expandstr() needs parsing machinery, so it is far away ahead... */
2686 static const char *expandstr(const char *ps, int syntax_type);
2687 /* Values for syntax param */
2688 #define BASESYNTAX 0    /* not in quotes */
2689 #define DQSYNTAX   1    /* in double quotes */
2690 #define SQSYNTAX   2    /* in single quotes */
2691 #define ARISYNTAX  3    /* in arithmetic */
2692 #if ENABLE_ASH_EXPAND_PRMT
2693 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2694 #endif
2695 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2696
2697 /*
2698  * called by editline -- any expansions to the prompt should be added here.
2699  */
2700 static void
2701 setprompt_if(smallint do_set, int whichprompt)
2702 {
2703         const char *prompt;
2704         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2705
2706         if (!do_set)
2707                 return;
2708
2709         needprompt = 0;
2710
2711         switch (whichprompt) {
2712         case 1:
2713                 prompt = ps1val();
2714                 break;
2715         case 2:
2716                 prompt = ps2val();
2717                 break;
2718         default:                        /* 0 */
2719                 prompt = nullstr;
2720         }
2721 #if ENABLE_ASH_EXPAND_PRMT
2722         pushstackmark(&smark, stackblocksize());
2723         putprompt(expandstr(prompt, PSSYNTAX));
2724         popstackmark(&smark);
2725 #else
2726         putprompt(prompt);
2727 #endif
2728 }
2729
2730
2731 /* ============ The cd and pwd commands */
2732
2733 #define CD_PHYSICAL 1
2734 #define CD_PRINT 2
2735
2736 static int
2737 cdopt(void)
2738 {
2739         int flags = 0;
2740         int i, j;
2741
2742         j = 'L';
2743         while ((i = nextopt("LP")) != '\0') {
2744                 if (i != j) {
2745                         flags ^= CD_PHYSICAL;
2746                         j = i;
2747                 }
2748         }
2749
2750         return flags;
2751 }
2752
2753 /*
2754  * Update curdir (the name of the current directory) in response to a
2755  * cd command.
2756  */
2757 static const char *
2758 updatepwd(const char *dir)
2759 {
2760         char *new;
2761         char *p;
2762         char *cdcomppath;
2763         const char *lim;
2764
2765         cdcomppath = sstrdup(dir);
2766         STARTSTACKSTR(new);
2767         if (*dir != '/') {
2768                 if (curdir == nullstr)
2769                         return 0;
2770                 new = stack_putstr(curdir, new);
2771         }
2772         new = makestrspace(strlen(dir) + 2, new);
2773         lim = (char *)stackblock() + 1;
2774         if (*dir != '/') {
2775                 if (new[-1] != '/')
2776                         USTPUTC('/', new);
2777                 if (new > lim && *lim == '/')
2778                         lim++;
2779         } else {
2780                 USTPUTC('/', new);
2781                 cdcomppath++;
2782                 if (dir[1] == '/' && dir[2] != '/') {
2783                         USTPUTC('/', new);
2784                         cdcomppath++;
2785                         lim++;
2786                 }
2787         }
2788         p = strtok(cdcomppath, "/");
2789         while (p) {
2790                 switch (*p) {
2791                 case '.':
2792                         if (p[1] == '.' && p[2] == '\0') {
2793                                 while (new > lim) {
2794                                         STUNPUTC(new);
2795                                         if (new[-1] == '/')
2796                                                 break;
2797                                 }
2798                                 break;
2799                         }
2800                         if (p[1] == '\0')
2801                                 break;
2802                         /* fall through */
2803                 default:
2804                         new = stack_putstr(p, new);
2805                         USTPUTC('/', new);
2806                 }
2807                 p = strtok(NULL, "/");
2808         }
2809         if (new > lim)
2810                 STUNPUTC(new);
2811         *new = 0;
2812         return stackblock();
2813 }
2814
2815 /*
2816  * Find out what the current directory is. If we already know the current
2817  * directory, this routine returns immediately.
2818  */
2819 static char *
2820 getpwd(void)
2821 {
2822         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2823         return dir ? dir : nullstr;
2824 }
2825
2826 static void
2827 setpwd(const char *val, int setold)
2828 {
2829         char *oldcur, *dir;
2830
2831         oldcur = dir = curdir;
2832
2833         if (setold) {
2834                 setvar("OLDPWD", oldcur, VEXPORT);
2835         }
2836         INT_OFF;
2837         if (physdir != nullstr) {
2838                 if (physdir != oldcur)
2839                         free(physdir);
2840                 physdir = nullstr;
2841         }
2842         if (oldcur == val || !val) {
2843                 char *s = getpwd();
2844                 physdir = s;
2845                 if (!val)
2846                         dir = s;
2847         } else
2848                 dir = ckstrdup(val);
2849         if (oldcur != dir && oldcur != nullstr) {
2850                 free(oldcur);
2851         }
2852         curdir = dir;
2853         INT_ON;
2854         setvar("PWD", dir, VEXPORT);
2855 }
2856
2857 static void hashcd(void);
2858
2859 /*
2860  * Actually do the chdir.  We also call hashcd to let other routines
2861  * know that the current directory has changed.
2862  */
2863 static int
2864 docd(const char *dest, int flags)
2865 {
2866         const char *dir = NULL;
2867         int err;
2868
2869         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2870
2871         INT_OFF;
2872         if (!(flags & CD_PHYSICAL)) {
2873                 dir = updatepwd(dest);
2874                 if (dir)
2875                         dest = dir;
2876         }
2877         err = chdir(dest);
2878         if (err)
2879                 goto out;
2880         setpwd(dir, 1);
2881         hashcd();
2882  out:
2883         INT_ON;
2884         return err;
2885 }
2886
2887 static int FAST_FUNC
2888 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2889 {
2890         const char *dest;
2891         const char *path;
2892         const char *p;
2893         char c;
2894         struct stat statb;
2895         int flags;
2896         int len;
2897
2898         flags = cdopt();
2899         dest = *argptr;
2900         if (!dest)
2901                 dest = bltinlookup("HOME");
2902         else if (LONE_DASH(dest)) {
2903                 dest = bltinlookup("OLDPWD");
2904                 flags |= CD_PRINT;
2905         }
2906         if (!dest)
2907                 dest = nullstr;
2908         if (*dest == '/')
2909                 goto step6;
2910         if (*dest == '.') {
2911                 c = dest[1];
2912  dotdot:
2913                 switch (c) {
2914                 case '\0':
2915                 case '/':
2916                         goto step6;
2917                 case '.':
2918                         c = dest[2];
2919                         if (c != '.')
2920                                 goto dotdot;
2921                 }
2922         }
2923         if (!*dest)
2924                 dest = ".";
2925         path = bltinlookup("CDPATH");
2926         while (p = path, (len = padvance(&path, dest)) >= 0) {
2927                 c = *p;
2928                 p = stalloc(len);
2929
2930                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2931                         if (c && c != ':')
2932                                 flags |= CD_PRINT;
2933  docd:
2934                         if (!docd(p, flags))
2935                                 goto out;
2936                         goto err;
2937                 }
2938         }
2939
2940  step6:
2941         p = dest;
2942         goto docd;
2943
2944  err:
2945         ash_msg_and_raise_perror("can't cd to %s", dest);
2946         /* NOTREACHED */
2947  out:
2948         if (flags & CD_PRINT)
2949                 out1fmt("%s\n", curdir);
2950         return 0;
2951 }
2952
2953 static int FAST_FUNC
2954 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2955 {
2956         int flags;
2957         const char *dir = curdir;
2958
2959         flags = cdopt();
2960         if (flags) {
2961                 if (physdir == nullstr)
2962                         setpwd(dir, 0);
2963                 dir = physdir;
2964         }
2965         out1fmt("%s\n", dir);
2966         return 0;
2967 }
2968
2969
2970 /* ============ ... */
2971
2972
2973 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2974
2975 /* Syntax classes */
2976 #define CWORD     0             /* character is nothing special */
2977 #define CNL       1             /* newline character */
2978 #define CBACK     2             /* a backslash character */
2979 #define CSQUOTE   3             /* single quote */
2980 #define CDQUOTE   4             /* double quote */
2981 #define CENDQUOTE 5             /* a terminating quote */
2982 #define CBQUOTE   6             /* backwards single quote */
2983 #define CVAR      7             /* a dollar sign */
2984 #define CENDVAR   8             /* a '}' character */
2985 #define CLP       9             /* a left paren in arithmetic */
2986 #define CRP      10             /* a right paren in arithmetic */
2987 #define CENDFILE 11             /* end of file */
2988 #define CCTL     12             /* like CWORD, except it must be escaped */
2989 #define CSPCL    13             /* these terminate a word */
2990 #define CIGN     14             /* character should be ignored */
2991
2992 #define PEOF     256
2993 #if ENABLE_ASH_ALIAS
2994 # define PEOA    257
2995 #endif
2996
2997 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2998
2999 #if ENABLE_FEATURE_SH_MATH
3000 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
3001 #else
3002 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
3003 #endif
3004 static const uint16_t S_I_T[] ALIGN2 = {
3005 #if ENABLE_ASH_ALIAS
3006         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
3007 #endif
3008         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
3009         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
3010         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
3011         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
3012         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
3013         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
3014         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
3015         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
3016         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
3017         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
3018         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
3019 #if !USE_SIT_FUNCTION
3020         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
3021         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
3022         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
3023 #endif
3024 #undef SIT_ITEM
3025 };
3026 /* Constants below must match table above */
3027 enum {
3028 #if ENABLE_ASH_ALIAS
3029         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
3030 #endif
3031         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
3032         CNL_CNL_CNL_CNL                    , /*  2 */
3033         CWORD_CCTL_CCTL_CWORD              , /*  3 */
3034         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
3035         CVAR_CVAR_CWORD_CVAR               , /*  5 */
3036         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
3037         CSPCL_CWORD_CWORD_CLP              , /*  7 */
3038         CSPCL_CWORD_CWORD_CRP              , /*  8 */
3039         CBACK_CBACK_CCTL_CBACK             , /*  9 */
3040         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
3041         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
3042         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
3043         CWORD_CWORD_CWORD_CWORD            , /* 13 */
3044         CCTL_CCTL_CCTL_CCTL                , /* 14 */
3045 };
3046
3047 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
3048  * caller must ensure proper cast on it if c is *char_ptr!
3049  */
3050 #if USE_SIT_FUNCTION
3051
3052 static int
3053 SIT(int c, int syntax)
3054 {
3055         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
3056         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
3057         /*
3058          * This causes '/' to be prepended with CTLESC in dquoted string,
3059          * making "./file"* treated incorrectly because we feed
3060          * ".\/file*" string to glob(), confusing it (see expandmeta func).
3061          * The "homegrown" glob implementation is okay with that,
3062          * but glibc one isn't. With '/' always treated as CWORD,
3063          * both work fine.
3064          */
3065 # if ENABLE_ASH_ALIAS
3066         static const uint8_t syntax_index_table[] ALIGN1 = {
3067                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
3068                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
3069                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
3070                 11, 3                           /* "}~" */
3071         };
3072 # else
3073         static const uint8_t syntax_index_table[] ALIGN1 = {
3074                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
3075                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
3076                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
3077                 10, 2                           /* "}~" */
3078         };
3079 # endif
3080         const char *s;
3081         int indx;
3082
3083         if (c == PEOF)
3084                 return CENDFILE;
3085 # if ENABLE_ASH_ALIAS
3086         if (c == PEOA)
3087                 indx = 0;
3088         else
3089 # endif
3090         {
3091                 /* Cast is purely for paranoia here,
3092                  * just in case someone passed signed char to us */
3093                 if ((unsigned char)c >= CTL_FIRST
3094                  && (unsigned char)c <= CTL_LAST
3095                 ) {
3096                         return CCTL;
3097                 }
3098                 s = strchrnul(spec_symbls, c);
3099                 if (*s == '\0')
3100                         return CWORD;
3101                 indx = syntax_index_table[s - spec_symbls];
3102         }
3103         return (S_I_T[indx] >> (syntax*4)) & 0xf;
3104 }
3105
3106 #else   /* !USE_SIT_FUNCTION */
3107
3108 static const uint8_t syntax_index_table[] ALIGN1 = {
3109         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
3110         /*   0      */ CWORD_CWORD_CWORD_CWORD,
3111         /*   1      */ CWORD_CWORD_CWORD_CWORD,
3112         /*   2      */ CWORD_CWORD_CWORD_CWORD,
3113         /*   3      */ CWORD_CWORD_CWORD_CWORD,
3114         /*   4      */ CWORD_CWORD_CWORD_CWORD,
3115         /*   5      */ CWORD_CWORD_CWORD_CWORD,
3116         /*   6      */ CWORD_CWORD_CWORD_CWORD,
3117         /*   7      */ CWORD_CWORD_CWORD_CWORD,
3118         /*   8      */ CWORD_CWORD_CWORD_CWORD,
3119         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
3120         /*  10 "\n" */ CNL_CNL_CNL_CNL,
3121         /*  11      */ CWORD_CWORD_CWORD_CWORD,
3122         /*  12      */ CWORD_CWORD_CWORD_CWORD,
3123         /*  13      */ CWORD_CWORD_CWORD_CWORD,
3124         /*  14      */ CWORD_CWORD_CWORD_CWORD,
3125         /*  15      */ CWORD_CWORD_CWORD_CWORD,
3126         /*  16      */ CWORD_CWORD_CWORD_CWORD,
3127         /*  17      */ CWORD_CWORD_CWORD_CWORD,
3128         /*  18      */ CWORD_CWORD_CWORD_CWORD,
3129         /*  19      */ CWORD_CWORD_CWORD_CWORD,
3130         /*  20      */ CWORD_CWORD_CWORD_CWORD,
3131         /*  21      */ CWORD_CWORD_CWORD_CWORD,
3132         /*  22      */ CWORD_CWORD_CWORD_CWORD,
3133         /*  23      */ CWORD_CWORD_CWORD_CWORD,
3134         /*  24      */ CWORD_CWORD_CWORD_CWORD,
3135         /*  25      */ CWORD_CWORD_CWORD_CWORD,
3136         /*  26      */ CWORD_CWORD_CWORD_CWORD,
3137         /*  27      */ CWORD_CWORD_CWORD_CWORD,
3138         /*  28      */ CWORD_CWORD_CWORD_CWORD,
3139         /*  29      */ CWORD_CWORD_CWORD_CWORD,
3140         /*  30      */ CWORD_CWORD_CWORD_CWORD,
3141         /*  31      */ CWORD_CWORD_CWORD_CWORD,
3142         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
3143         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
3144         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
3145         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
3146         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
3147         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
3148         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
3149         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
3150         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
3151         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
3152         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
3153         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
3154         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
3155         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
3156         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
3157 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
3158         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
3159         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
3160         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
3161         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
3162         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
3163         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
3164         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
3165         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
3166         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
3167         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
3168         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
3169         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
3170         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
3171         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
3172         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
3173         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
3174         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
3175         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
3176         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
3177         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
3178         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
3179         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
3180         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
3181         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
3182         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
3183         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
3184         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
3185         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
3186         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
3187         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
3188         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
3189         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
3190         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
3191         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
3192         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
3193         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
3194         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3195         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3196         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3197         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3198         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3199         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3200         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3201         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3202         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3203         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3204         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3205         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3206         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3207         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3208         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3209         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3210         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3211         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3212         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3213         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3214         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3215         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3216         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3217         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3218         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3219         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3220         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3221         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3222         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3223         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3224         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3225         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3226         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3227         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3228         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3229         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3230         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3231         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3232         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3233         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3234         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3235         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3236         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3237         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3238         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3239         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3240         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3241         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3242         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3243         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3244         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3245         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3246         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3247         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3248         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3249         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3250         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3251         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3252         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3253         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3254         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3255         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3256         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3257         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3258         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3259         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3260         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3261         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3262         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3263         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3264         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3265         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3266         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3267         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3268         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3269         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3270         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3271         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3272         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3273         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3274         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3275         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3276         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3277         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3278         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3279         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3280         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3281         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3282         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3283         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3284         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3285         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3286         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3287         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3288         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3289         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3290         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3291         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3292         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3293         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3294         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3295         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3296         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3297         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3298         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3299         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3300         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3301         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3302         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3303         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3304         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3305         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3306         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3307         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3308         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3309         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3310         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3311         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3312         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3313         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3314         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3315         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3316         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3317         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3318         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3319         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3320         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3321         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3322         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3323         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3324         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3325         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3326         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3327         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3328         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3329         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3330         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3331         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3332         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3333         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3334         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3335         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3336         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3337         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3338         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3339         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3340         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3341         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3342         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3343         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3344         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3345         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3346         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3347         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3348         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3349         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3350         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3351         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3352         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3353         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3354         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3355         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3356         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3357         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3358         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3359         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3360         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3361         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3362         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3363         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3364         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3365         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3366         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3367         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3368 # if ENABLE_ASH_ALIAS
3369         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3370 # endif
3371 };
3372
3373 #if 1
3374 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3375 #else /* debug version, caught one signed char bug */
3376 # define SIT(c, syntax) \
3377         ({ \
3378                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3379                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3380                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3381                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3382                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3383         })
3384 #endif
3385
3386 #endif  /* !USE_SIT_FUNCTION */
3387
3388
3389 /* ============ Alias handling */
3390
3391 #if ENABLE_ASH_ALIAS
3392
3393 #define ALIASINUSE 1
3394 #define ALIASDEAD  2
3395
3396 struct alias {
3397         struct alias *next;
3398         char *name;
3399         char *val;
3400         int flag;
3401 };
3402
3403
3404 static struct alias **atab; // [ATABSIZE];
3405 #define INIT_G_alias() do { \
3406         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3407 } while (0)
3408
3409
3410 static struct alias **
3411 __lookupalias(const char *name)
3412 {
3413         unsigned int hashval;
3414         struct alias **app;
3415         const char *p;
3416         unsigned int ch;
3417
3418         p = name;
3419
3420         ch = (unsigned char)*p;
3421         hashval = ch << 4;
3422         while (ch) {
3423                 hashval += ch;
3424                 ch = (unsigned char)*++p;
3425         }
3426         app = &atab[hashval % ATABSIZE];
3427
3428         for (; *app; app = &(*app)->next) {
3429                 if (strcmp(name, (*app)->name) == 0) {
3430                         break;
3431                 }
3432         }
3433
3434         return app;
3435 }
3436
3437 static struct alias *
3438 lookupalias(const char *name, int check)
3439 {
3440         struct alias *ap = *__lookupalias(name);
3441
3442         if (check && ap && (ap->flag & ALIASINUSE))
3443                 return NULL;
3444         return ap;
3445 }
3446
3447 static struct alias *
3448 freealias(struct alias *ap)
3449 {
3450         struct alias *next;
3451
3452         if (ap->flag & ALIASINUSE) {
3453                 ap->flag |= ALIASDEAD;
3454                 return ap;
3455         }
3456
3457         next = ap->next;
3458         free(ap->name);
3459         free(ap->val);
3460         free(ap);
3461         return next;
3462 }
3463
3464 static void
3465 setalias(const char *name, const char *val)
3466 {
3467         struct alias *ap, **app;
3468
3469         app = __lookupalias(name);
3470         ap = *app;
3471         INT_OFF;
3472         if (ap) {
3473                 if (!(ap->flag & ALIASINUSE)) {
3474                         free(ap->val);
3475                 }
3476                 ap->val = ckstrdup(val);
3477                 ap->flag &= ~ALIASDEAD;
3478         } else {
3479                 /* not found */
3480                 ap = ckzalloc(sizeof(struct alias));
3481                 ap->name = ckstrdup(name);
3482                 ap->val = ckstrdup(val);
3483                 /*ap->flag = 0; - ckzalloc did it */
3484                 /*ap->next = NULL;*/
3485                 *app = ap;
3486         }
3487         INT_ON;
3488 }
3489
3490 static int
3491 unalias(const char *name)
3492 {
3493         struct alias **app;
3494
3495         app = __lookupalias(name);
3496
3497         if (*app) {
3498                 INT_OFF;
3499                 *app = freealias(*app);
3500                 INT_ON;
3501                 return 0;
3502         }
3503
3504         return 1;
3505 }
3506
3507 static void
3508 rmaliases(void)
3509 {
3510         struct alias *ap, **app;
3511         int i;
3512
3513         INT_OFF;
3514         for (i = 0; i < ATABSIZE; i++) {
3515                 app = &atab[i];
3516                 for (ap = *app; ap; ap = *app) {
3517                         *app = freealias(*app);
3518                         if (ap == *app) {
3519                                 app = &ap->next;
3520                         }
3521                 }
3522         }
3523         INT_ON;
3524 }
3525
3526 static void
3527 printalias(const struct alias *ap)
3528 {
3529         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3530 }
3531
3532 /*
3533  * TODO - sort output
3534  */
3535 static int FAST_FUNC
3536 aliascmd(int argc UNUSED_PARAM, char **argv)
3537 {
3538         char *n, *v;
3539         int ret = 0;
3540         struct alias *ap;
3541
3542         if (!argv[1]) {
3543                 int i;
3544
3545                 for (i = 0; i < ATABSIZE; i++) {
3546                         for (ap = atab[i]; ap; ap = ap->next) {
3547                                 printalias(ap);
3548                         }
3549                 }
3550                 return 0;
3551         }
3552         while ((n = *++argv) != NULL) {
3553                 v = strchr(n+1, '=');
3554                 if (v == NULL) { /* n+1: funny ksh stuff */
3555                         ap = *__lookupalias(n);
3556                         if (ap == NULL) {
3557                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3558                                 ret = 1;
3559                         } else
3560                                 printalias(ap);
3561                 } else {
3562                         *v++ = '\0';
3563                         setalias(n, v);
3564                 }
3565         }
3566
3567         return ret;
3568 }
3569
3570 static int FAST_FUNC
3571 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3572 {
3573         int i;
3574
3575         while (nextopt("a") != '\0') {
3576                 rmaliases();
3577                 return 0;
3578         }
3579         for (i = 0; *argptr; argptr++) {
3580                 if (unalias(*argptr)) {
3581                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3582                         i = 1;
3583                 }
3584         }
3585
3586         return i;
3587 }
3588
3589 #endif /* ASH_ALIAS */
3590
3591
3592 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3593 #define FORK_FG    0
3594 #define FORK_BG    1
3595 #define FORK_NOJOB 2
3596
3597 /* mode flags for showjob(s) */
3598 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3599 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3600 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3601 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3602
3603 /*
3604  * A job structure contains information about a job.  A job is either a
3605  * single process or a set of processes contained in a pipeline.  In the
3606  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3607  * array of pids.
3608  */
3609 struct procstat {
3610         pid_t   ps_pid;         /* process id */
3611         int     ps_status;      /* last process status from wait() */
3612         char    *ps_cmd;        /* text of command being run */
3613 };
3614
3615 struct job {
3616         struct procstat ps0;    /* status of process */
3617         struct procstat *ps;    /* status of processes when more than one */
3618 #if JOBS
3619         int stopstatus;         /* status of a stopped job */
3620 #endif
3621         unsigned nprocs;        /* number of processes */
3622
3623 #define JOBRUNNING      0       /* at least one proc running */
3624 #define JOBSTOPPED      1       /* all procs are stopped */
3625 #define JOBDONE         2       /* all procs are completed */
3626         unsigned
3627                 state: 8,
3628 #if JOBS
3629                 sigint: 1,      /* job was killed by SIGINT */
3630                 jobctl: 1,      /* job running under job control */
3631 #endif
3632                 waited: 1,      /* true if this entry has been waited for */
3633                 used: 1,        /* true if this entry is in used */
3634                 changed: 1;     /* true if status has changed */
3635         struct job *prev_job;   /* previous job */
3636 };
3637
3638 static struct job *makejob(/*union node *,*/ int);
3639 static int forkshell(struct job *, union node *, int);
3640 static int waitforjob(struct job *);
3641
3642 #if !JOBS
3643 enum { doing_jobctl = 0 };
3644 #define setjobctl(on) do {} while (0)
3645 #else
3646 static smallint doing_jobctl; //references:8
3647 static void setjobctl(int);
3648 #endif
3649
3650 /*
3651  * Ignore a signal.
3652  */
3653 static void
3654 ignoresig(int signo)
3655 {
3656         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3657         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3658                 /* No, need to do it */
3659                 signal(signo, SIG_IGN);
3660         }
3661         sigmode[signo - 1] = S_HARD_IGN;
3662 }
3663
3664 /*
3665  * Only one usage site - in setsignal()
3666  */
3667 static void
3668 signal_handler(int signo)
3669 {
3670         if (signo == SIGCHLD) {
3671                 got_sigchld = 1;
3672                 if (!trap[SIGCHLD])
3673                         return;
3674         }
3675
3676         gotsig[signo - 1] = 1;
3677         pending_sig = signo;
3678
3679         if (signo == SIGINT && !trap[SIGINT]) {
3680                 if (!suppress_int) {
3681                         pending_sig = 0;
3682                         raise_interrupt(); /* does not return */
3683                 }
3684                 pending_int = 1;
3685         }
3686 }
3687
3688 /*
3689  * Set the signal handler for the specified signal.  The routine figures
3690  * out what it should be set to.
3691  */
3692 static void
3693 setsignal(int signo)
3694 {
3695         char *t;
3696         char cur_act, new_act;
3697         struct sigaction act;
3698
3699         t = trap[signo];
3700         new_act = S_DFL;
3701         if (t != NULL) { /* trap for this sig is set */
3702                 new_act = S_CATCH;
3703                 if (t[0] == '\0') /* trap is "": ignore this sig */
3704                         new_act = S_IGN;
3705         }
3706
3707         if (rootshell && new_act == S_DFL) {
3708                 switch (signo) {
3709                 case SIGINT:
3710                         if (iflag || minusc || sflag == 0)
3711                                 new_act = S_CATCH;
3712                         break;
3713                 case SIGQUIT:
3714 #if DEBUG
3715                         if (debug)
3716                                 break;
3717 #endif
3718                         /* man bash:
3719                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3720                          * commands run by bash have signal handlers
3721                          * set to the values inherited by the shell
3722                          * from its parent". */
3723                         new_act = S_IGN;
3724                         break;
3725                 case SIGTERM:
3726                         if (iflag)
3727                                 new_act = S_IGN;
3728                         break;
3729 #if JOBS
3730                 case SIGTSTP:
3731                 case SIGTTOU:
3732                         if (mflag)
3733                                 new_act = S_IGN;
3734                         break;
3735 #endif
3736                 }
3737         }
3738         /* if !rootshell, we reset SIGQUIT to DFL,
3739          * whereas we have to restore it to what shell got on entry.
3740          * This is handled by the fact that if signal was IGNored on entry,
3741          * then cur_act is S_HARD_IGN and we never change its sigaction
3742          * (see code below).
3743          */
3744
3745         if (signo == SIGCHLD)
3746                 new_act = S_CATCH;
3747
3748         t = &sigmode[signo - 1];
3749         cur_act = *t;
3750         if (cur_act == 0) {
3751                 /* current setting is not yet known */
3752                 if (sigaction(signo, NULL, &act)) {
3753                         /* pretend it worked; maybe we should give a warning,
3754                          * but other shells don't. We don't alter sigmode,
3755                          * so we retry every time.
3756                          * btw, in Linux it never fails. --vda */
3757                         return;
3758                 }
3759                 if (act.sa_handler == SIG_IGN) {
3760                         cur_act = S_HARD_IGN;
3761                         if (mflag
3762                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3763                         ) {
3764                                 cur_act = S_IGN;   /* don't hard ignore these */
3765                         }
3766                 }
3767                 if (act.sa_handler == SIG_DFL && new_act == S_DFL) {
3768                         /* installing SIG_DFL over SIG_DFL is a no-op */
3769                         /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3770                         *t = S_DFL;
3771                         return;
3772                 }
3773         }
3774         if (cur_act == S_HARD_IGN || cur_act == new_act)
3775                 return;
3776
3777         *t = new_act;
3778
3779         act.sa_handler = SIG_DFL;
3780         switch (new_act) {
3781         case S_CATCH:
3782                 act.sa_handler = signal_handler;
3783                 break;
3784         case S_IGN:
3785                 act.sa_handler = SIG_IGN;
3786                 break;
3787         }
3788         /* flags and mask matter only if !DFL and !IGN, but we do it
3789          * for all cases for more deterministic behavior:
3790          */
3791         act.sa_flags = 0; //TODO: why not SA_RESTART?
3792         sigfillset(&act.sa_mask);
3793
3794         sigaction_set(signo, &act);
3795 }
3796
3797 /* mode flags for set_curjob */
3798 #define CUR_DELETE 2
3799 #define CUR_RUNNING 1
3800 #define CUR_STOPPED 0
3801
3802 #if JOBS
3803 /* pgrp of shell on invocation */
3804 static int initialpgrp; //references:2
3805 static int ttyfd = -1; //5
3806 #endif
3807 /* array of jobs */
3808 static struct job *jobtab; //5
3809 /* size of array */
3810 static unsigned njobs; //4
3811 /* current job */
3812 static struct job *curjob; //lots
3813 /* number of presumed living untracked jobs */
3814 static int jobless; //4
3815
3816 #if 0
3817 /* Bash has a feature: it restores termios after a successful wait for
3818  * a foreground job which had at least one stopped or sigkilled member.
3819  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3820  * properly restoring tty state. Should we do this too?
3821  * A reproducer: ^Z an interactive python:
3822  *
3823  * # python
3824  * Python 2.7.12 (...)
3825  * >>> ^Z
3826  *      { python leaves tty in -icanon -echo state. We do survive that... }
3827  *  [1]+  Stopped                    python
3828  *      { ...however, next program (python #2) does not survive it well: }
3829  * # python
3830  * Python 2.7.12 (...)
3831  * >>> Traceback (most recent call last):
3832  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3833  *   File "<stdin>", line 1, in <module>
3834  * NameError: name 'qwerty' is not defined
3835  *
3836  * The implementation below is modeled on bash code and seems to work.
3837  * However, I'm not sure we should do this. For one: what if I'd fg
3838  * the stopped python instead? It'll be confused by "restored" tty state.
3839  */
3840 static struct termios shell_tty_info;
3841 static void
3842 get_tty_state(void)
3843 {
3844         if (rootshell && ttyfd >= 0)
3845                 tcgetattr(ttyfd, &shell_tty_info);
3846 }
3847 static void
3848 set_tty_state(void)
3849 {
3850         /* if (rootshell) - caller ensures this */
3851         if (ttyfd >= 0)
3852                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3853 }
3854 static int
3855 job_signal_status(struct job *jp)
3856 {
3857         int status;
3858         unsigned i;
3859         struct procstat *ps = jp->ps;
3860         for (i = 0; i < jp->nprocs; i++) {
3861                 status = ps[i].ps_status;
3862                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3863                         return status;
3864         }
3865         return 0;
3866 }
3867 static void
3868 restore_tty_if_stopped_or_signaled(struct job *jp)
3869 {
3870 //TODO: check what happens if we come from waitforjob() in expbackq()
3871         if (rootshell) {
3872                 int s = job_signal_status(jp);
3873                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3874                         set_tty_state();
3875         }
3876 }
3877 #else
3878 # define get_tty_state() ((void)0)
3879 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3880 #endif
3881
3882 static void
3883 set_curjob(struct job *jp, unsigned mode)
3884 {
3885         struct job *jp1;
3886         struct job **jpp, **curp;
3887
3888         /* first remove from list */
3889         jpp = curp = &curjob;
3890         while (1) {
3891                 jp1 = *jpp;
3892                 if (jp1 == jp)
3893                         break;
3894                 jpp = &jp1->prev_job;
3895         }
3896         *jpp = jp1->prev_job;
3897
3898         /* Then re-insert in correct position */
3899         jpp = curp;
3900         switch (mode) {
3901         default:
3902 #if DEBUG
3903                 abort();
3904 #endif
3905         case CUR_DELETE:
3906                 /* job being deleted */
3907                 break;
3908         case CUR_RUNNING:
3909                 /* newly created job or backgrounded job,
3910                  * put after all stopped jobs.
3911                  */
3912                 while (1) {
3913                         jp1 = *jpp;
3914 #if JOBS
3915                         if (!jp1 || jp1->state != JOBSTOPPED)
3916 #endif
3917                                 break;
3918                         jpp = &jp1->prev_job;
3919                 }
3920                 /* FALLTHROUGH */
3921 #if JOBS
3922         case CUR_STOPPED:
3923 #endif
3924                 /* newly stopped job - becomes curjob */
3925                 jp->prev_job = *jpp;
3926                 *jpp = jp;
3927                 break;
3928         }
3929 }
3930
3931 #if JOBS || DEBUG
3932 static int
3933 jobno(const struct job *jp)
3934 {
3935         return jp - jobtab + 1;
3936 }
3937 #endif
3938
3939 /*
3940  * Convert a job name to a job structure.
3941  */
3942 #if !JOBS
3943 #define getjob(name, getctl) getjob(name)
3944 #endif
3945 static struct job *
3946 getjob(const char *name, int getctl)
3947 {
3948         struct job *jp;
3949         struct job *found;
3950         const char *err_msg = "%s: no such job";
3951         unsigned num;
3952         int c;
3953         const char *p;
3954         char *(*match)(const char *, const char *);
3955
3956         jp = curjob;
3957         p = name;
3958         if (!p)
3959                 goto currentjob;
3960
3961         if (*p != '%')
3962                 goto err;
3963
3964         c = *++p;
3965         if (!c)
3966                 goto currentjob;
3967
3968         if (!p[1]) {
3969                 if (c == '+' || c == '%') {
3970  currentjob:
3971                         err_msg = "No current job";
3972                         goto check;
3973                 }
3974                 if (c == '-') {
3975                         if (jp)
3976                                 jp = jp->prev_job;
3977                         err_msg = "No previous job";
3978  check:
3979                         if (!jp)
3980                                 goto err;
3981                         goto gotit;
3982                 }
3983         }
3984
3985         if (is_number(p)) {
3986                 num = atoi(p);
3987                 if (num > 0 && num <= njobs) {
3988                         jp = jobtab + num - 1;
3989                         if (jp->used)
3990                                 goto gotit;
3991                         goto err;
3992                 }
3993         }
3994
3995         match = prefix;
3996         if (*p == '?') {
3997                 match = strstr;
3998                 p++;
3999         }
4000
4001         found = NULL;
4002         while (jp) {
4003                 if (match(jp->ps[0].ps_cmd, p)) {
4004                         if (found)
4005                                 goto err;
4006                         found = jp;
4007                         err_msg = "%s: ambiguous";
4008                 }
4009                 jp = jp->prev_job;
4010         }
4011         if (!found)
4012                 goto err;
4013         jp = found;
4014
4015  gotit:
4016 #if JOBS
4017         err_msg = "job %s not created under job control";
4018         if (getctl && jp->jobctl == 0)
4019                 goto err;
4020 #endif
4021         return jp;
4022  err:
4023         ash_msg_and_raise_error(err_msg, name);
4024 }
4025
4026 /*
4027  * Mark a job structure as unused.
4028  */
4029 static void
4030 freejob(struct job *jp)
4031 {
4032         struct procstat *ps;
4033         int i;
4034
4035         INT_OFF;
4036         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
4037                 if (ps->ps_cmd != nullstr)
4038                         free(ps->ps_cmd);
4039         }
4040         if (jp->ps != &jp->ps0)
4041                 free(jp->ps);
4042         jp->used = 0;
4043         set_curjob(jp, CUR_DELETE);
4044         INT_ON;
4045 }
4046
4047 #if JOBS
4048 static void
4049 xtcsetpgrp(int fd, pid_t pgrp)
4050 {
4051         if (tcsetpgrp(fd, pgrp))
4052                 ash_msg_and_raise_perror("can't set tty process group");
4053 }
4054
4055 /*
4056  * Turn job control on and off.
4057  *
4058  * Note:  This code assumes that the third arg to ioctl is a character
4059  * pointer, which is true on Berkeley systems but not System V.  Since
4060  * System V doesn't have job control yet, this isn't a problem now.
4061  *
4062  * Called with interrupts off.
4063  */
4064 static void
4065 setjobctl(int on)
4066 {
4067         int fd;
4068         int pgrp;
4069
4070         if (on == doing_jobctl || rootshell == 0)
4071                 return;
4072         if (on) {
4073                 int ofd;
4074                 ofd = fd = open(_PATH_TTY, O_RDWR);
4075                 if (fd < 0) {
4076         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
4077          * That sometimes helps to acquire controlling tty.
4078          * Obviously, a workaround for bugs when someone
4079          * failed to provide a controlling tty to bash! :) */
4080                         fd = 2;
4081                         while (!isatty(fd))
4082                                 if (--fd < 0)
4083                                         goto out;
4084                 }
4085                 /* fd is a tty at this point */
4086                 fd = fcntl(fd, F_DUPFD_CLOEXEC, 10);
4087                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
4088                         close(ofd);
4089                 if (fd < 0)
4090                         goto out; /* F_DUPFD failed */
4091                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
4092                         close_on_exec_on(fd);
4093                 while (1) { /* while we are in the background */
4094                         pgrp = tcgetpgrp(fd);
4095                         if (pgrp < 0) {
4096  out:
4097                                 ash_msg("can't access tty; job control turned off");
4098                                 mflag = on = 0;
4099                                 goto close;
4100                         }
4101                         if (pgrp == getpgrp())
4102                                 break;
4103                         killpg(0, SIGTTIN);
4104                 }
4105                 initialpgrp = pgrp;
4106
4107                 setsignal(SIGTSTP);
4108                 setsignal(SIGTTOU);
4109                 setsignal(SIGTTIN);
4110                 pgrp = rootpid;
4111                 setpgid(0, pgrp);
4112                 xtcsetpgrp(fd, pgrp);
4113         } else {
4114                 /* turning job control off */
4115                 fd = ttyfd;
4116                 pgrp = initialpgrp;
4117                 /* was xtcsetpgrp, but this can make exiting ash
4118                  * loop forever if pty is already deleted */
4119                 tcsetpgrp(fd, pgrp);
4120                 setpgid(0, pgrp);
4121                 setsignal(SIGTSTP);
4122                 setsignal(SIGTTOU);
4123                 setsignal(SIGTTIN);
4124  close:
4125                 if (fd >= 0)
4126                         close(fd);
4127                 fd = -1;
4128         }
4129         ttyfd = fd;
4130         doing_jobctl = on;
4131 }
4132
4133 static int FAST_FUNC
4134 killcmd(int argc, char **argv)
4135 {
4136         if (argv[1] && strcmp(argv[1], "-l") != 0) {
4137                 int i = 1;
4138                 do {
4139                         if (argv[i][0] == '%') {
4140                                 /*
4141                                  * "kill %N" - job kill
4142                                  * Converting to pgrp / pid kill
4143                                  */
4144                                 struct job *jp;
4145                                 char *dst;
4146                                 int j, n;
4147
4148                                 jp = getjob(argv[i], 0);
4149                                 /*
4150                                  * In jobs started under job control, we signal
4151                                  * entire process group by kill -PGRP_ID.
4152                                  * This happens, f.e., in interactive shell.
4153                                  *
4154                                  * Otherwise, we signal each child via
4155                                  * kill PID1 PID2 PID3.
4156                                  * Testcases:
4157                                  * sh -c 'sleep 1|sleep 1 & kill %1'
4158                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
4159                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
4160                                  */
4161                                 n = jp->nprocs; /* can't be 0 (I hope) */
4162                                 if (jp->jobctl)
4163                                         n = 1;
4164                                 dst = alloca(n * sizeof(int)*4);
4165                                 argv[i] = dst;
4166                                 for (j = 0; j < n; j++) {
4167                                         struct procstat *ps = &jp->ps[j];
4168                                         /* Skip non-running and not-stopped members
4169                                          * (i.e. dead members) of the job
4170                                          */
4171                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
4172                                                 continue;
4173                                         /*
4174                                          * kill_main has matching code to expect
4175                                          * leading space. Needed to not confuse
4176                                          * negative pids with "kill -SIGNAL_NO" syntax
4177                                          */
4178                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
4179                                 }
4180                                 *dst = '\0';
4181                         }
4182                 } while (argv[++i]);
4183         }
4184         return kill_main(argc, argv);
4185 }
4186
4187 static void
4188 showpipe(struct job *jp /*, FILE *out*/)
4189 {
4190         struct procstat *ps;
4191         struct procstat *psend;
4192
4193         psend = jp->ps + jp->nprocs;
4194         for (ps = jp->ps + 1; ps < psend; ps++)
4195                 printf(" | %s", ps->ps_cmd);
4196         newline_and_flush(stdout);
4197         flush_stdout_stderr();
4198 }
4199
4200
4201 static int
4202 restartjob(struct job *jp, int mode)
4203 {
4204         struct procstat *ps;
4205         int i;
4206         int status;
4207         pid_t pgid;
4208
4209         INT_OFF;
4210         if (jp->state == JOBDONE)
4211                 goto out;
4212         jp->state = JOBRUNNING;
4213         pgid = jp->ps[0].ps_pid;
4214         if (mode == FORK_FG) {
4215                 get_tty_state();
4216                 xtcsetpgrp(ttyfd, pgid);
4217         }
4218         killpg(pgid, SIGCONT);
4219         ps = jp->ps;
4220         i = jp->nprocs;
4221         do {
4222                 if (WIFSTOPPED(ps->ps_status)) {
4223                         ps->ps_status = -1;
4224                 }
4225                 ps++;
4226         } while (--i);
4227  out:
4228         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4229         INT_ON;
4230         return status;
4231 }
4232
4233 static int FAST_FUNC
4234 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4235 {
4236         struct job *jp;
4237         int mode;
4238         int retval;
4239
4240         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4241         nextopt(nullstr);
4242         argv = argptr;
4243         do {
4244                 jp = getjob(*argv, 1);
4245                 if (mode == FORK_BG) {
4246                         set_curjob(jp, CUR_RUNNING);
4247                         printf("[%d] ", jobno(jp));
4248                 }
4249                 out1str(jp->ps[0].ps_cmd);
4250                 showpipe(jp /*, stdout*/);
4251                 retval = restartjob(jp, mode);
4252         } while (*argv && *++argv);
4253         return retval;
4254 }
4255 #endif
4256
4257 static int
4258 sprint_status48(char *os, int status, int sigonly)
4259 {
4260         char *s = os;
4261         int st;
4262
4263         if (!WIFEXITED(status)) {
4264 #if JOBS
4265                 if (WIFSTOPPED(status))
4266                         st = WSTOPSIG(status);
4267                 else
4268 #endif
4269                         st = WTERMSIG(status);
4270                 if (sigonly) {
4271                         if (st == SIGINT || st == SIGPIPE)
4272                                 goto out;
4273 #if JOBS
4274                         if (WIFSTOPPED(status))
4275                                 goto out;
4276 #endif
4277                 }
4278                 st &= 0x7f;
4279 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4280                 //s = stpncpy(s, strsignal(st), 32); //not all libc have stpncpy()
4281                 s += fmtstr(s, 32, strsignal(st));
4282                 if (WCOREDUMP(status)) {
4283                         s = stpcpy(s, " (core dumped)");
4284                 }
4285         } else if (!sigonly) {
4286                 st = WEXITSTATUS(status);
4287                 s += fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4288         }
4289  out:
4290         return s - os;
4291 }
4292
4293 static int
4294 wait_block_or_sig(int *status)
4295 {
4296         int pid;
4297
4298         do {
4299                 sigset_t mask;
4300
4301                 /* Poll all children for changes in their state */
4302                 got_sigchld = 0;
4303                 /* if job control is active, accept stopped processes too */
4304                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4305                 if (pid != 0)
4306                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4307
4308                 /* Children exist, but none are ready. Sleep until interesting signal */
4309 #if 1
4310                 sigfillset(&mask);
4311                 sigprocmask2(SIG_SETMASK, &mask); /* mask is updated */
4312                 while (!got_sigchld && !pending_sig)
4313                         sigsuspend(&mask);
4314                 sigprocmask(SIG_SETMASK, &mask, NULL);
4315 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4316                 while (!got_sigchld && !pending_sig)
4317                         pause();
4318 #endif
4319
4320                 /* If it was SIGCHLD, poll children again */
4321         } while (got_sigchld);
4322
4323         return pid;
4324 }
4325
4326 #define DOWAIT_NONBLOCK 0
4327 #define DOWAIT_BLOCK    1
4328 #define DOWAIT_BLOCK_OR_SIG 2
4329 #if BASH_WAIT_N
4330 # define DOWAIT_JOBSTATUS 0x10   /* OR this to get job's exitstatus instead of pid */
4331 #endif
4332
4333 static int
4334 dowait(int block, struct job *job)
4335 {
4336         int pid;
4337         int status;
4338         struct job *jp;
4339         struct job *thisjob;
4340 #if BASH_WAIT_N
4341         bool want_jobexitstatus = (block & DOWAIT_JOBSTATUS);
4342         block = (block & ~DOWAIT_JOBSTATUS);
4343 #endif
4344
4345         TRACE(("dowait(0x%x) called\n", block));
4346
4347         /* It's wrong to call waitpid() outside of INT_OFF region:
4348          * signal can arrive just after syscall return and handler can
4349          * longjmp away, losing stop/exit notification processing.
4350          * Thus, for "jobs" builtin, and for waiting for a fg job,
4351          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4352          *
4353          * However, for "wait" builtin it is wrong to simply call waitpid()
4354          * in INT_OFF region: "wait" needs to wait for any running job
4355          * to change state, but should exit on any trap too.
4356          * In INT_OFF region, a signal just before syscall entry can set
4357          * pending_sig variables, but we can't check them, and we would
4358          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4359          *
4360          * Because of this, we run inside INT_OFF, but use a special routine
4361          * which combines waitpid() and sigsuspend().
4362          * This is the reason why we need to have a handler for SIGCHLD:
4363          * SIG_DFL handler does not wake sigsuspend().
4364          */
4365         INT_OFF;
4366         if (block == DOWAIT_BLOCK_OR_SIG) {
4367                 pid = wait_block_or_sig(&status);
4368         } else {
4369                 int wait_flags = 0;
4370                 if (block == DOWAIT_NONBLOCK)
4371                         wait_flags = WNOHANG;
4372                 /* if job control is active, accept stopped processes too */
4373                 if (doing_jobctl)
4374                         wait_flags |= WUNTRACED;
4375                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4376                 pid = waitpid(-1, &status, wait_flags);
4377         }
4378         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4379                                 pid, status, errno, strerror(errno)));
4380         thisjob = NULL;
4381         if (pid <= 0)
4382                 goto out;
4383
4384         for (jp = curjob; jp; jp = jp->prev_job) {
4385                 int jobstate;
4386                 struct procstat *ps;
4387                 struct procstat *psend;
4388                 if (jp->state == JOBDONE)
4389                         continue;
4390                 jobstate = JOBDONE;
4391                 ps = jp->ps;
4392                 psend = ps + jp->nprocs;
4393                 do {
4394                         if (ps->ps_pid == pid) {
4395                                 TRACE(("Job %d: changing status of proc %d "
4396                                         "from 0x%x to 0x%x\n",
4397                                         jobno(jp), pid, ps->ps_status, status));
4398                                 ps->ps_status = status;
4399                                 thisjob = jp;
4400                         }
4401                         if (ps->ps_status == -1)
4402                                 jobstate = JOBRUNNING;
4403 #if JOBS
4404                         if (jobstate == JOBRUNNING)
4405                                 continue;
4406                         if (WIFSTOPPED(ps->ps_status)) {
4407                                 jp->stopstatus = ps->ps_status;
4408                                 jobstate = JOBSTOPPED;
4409                         }
4410 #endif
4411                 } while (++ps < psend);
4412                 if (!thisjob)
4413                         continue;
4414
4415                 /* Found the job where one of its processes changed its state.
4416                  * Is there at least one live and running process in this job? */
4417                 if (jobstate != JOBRUNNING) {
4418                         /* No. All live processes in the job are stopped
4419                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4420                          */
4421                         thisjob->changed = 1;
4422                         if (thisjob->state != jobstate) {
4423                                 TRACE(("Job %d: changing state from %d to %d\n",
4424                                         jobno(thisjob), thisjob->state, jobstate));
4425                                 thisjob->state = jobstate;
4426 #if JOBS
4427                                 if (jobstate == JOBSTOPPED)
4428                                         set_curjob(thisjob, CUR_STOPPED);
4429 #endif
4430                         }
4431                 }
4432                 goto out;
4433         }
4434         /* The process wasn't found in job list */
4435 #if JOBS
4436         if (!WIFSTOPPED(status))
4437                 jobless--;
4438 #endif
4439  out:
4440         INT_ON;
4441
4442 #if BASH_WAIT_N
4443         if (want_jobexitstatus) {
4444                 pid = -1;
4445                 if (thisjob && thisjob->state == JOBDONE)
4446                         pid = thisjob->ps[thisjob->nprocs - 1].ps_status;
4447         }
4448 #endif
4449         if (thisjob && thisjob == job) {
4450                 char s[48 + 1];
4451                 int len;
4452
4453                 len = sprint_status48(s, status, 1);
4454                 if (len) {
4455                         s[len] = '\n';
4456                         s[len + 1] = '\0';
4457                         out2str(s);
4458                 }
4459         }
4460         return pid;
4461 }
4462
4463 #if JOBS
4464 static void
4465 showjob(struct job *jp, int mode)
4466 {
4467         struct procstat *ps;
4468         struct procstat *psend;
4469         int col;
4470         int indent_col;
4471         char s[16 + 16 + 48];
4472         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4473
4474         ps = jp->ps;
4475
4476         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4477                 /* just output process (group) id of pipeline */
4478                 fprintf(out, "%d\n", ps->ps_pid);
4479                 return;
4480         }
4481
4482         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4483         indent_col = col;
4484
4485         if (jp == curjob)
4486                 s[col - 3] = '+';
4487         else if (curjob && jp == curjob->prev_job)
4488                 s[col - 3] = '-';
4489
4490         if (mode & SHOW_PIDS)
4491                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4492
4493         psend = ps + jp->nprocs;
4494
4495         if (jp->state == JOBRUNNING) {
4496                 strcpy(s + col, "Running");
4497                 col += sizeof("Running") - 1;
4498         } else {
4499                 int status = psend[-1].ps_status;
4500                 if (jp->state == JOBSTOPPED)
4501                         status = jp->stopstatus;
4502                 col += sprint_status48(s + col, status, 0);
4503         }
4504         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4505
4506         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4507          * or prints several "PID             | <cmdN>" lines,
4508          * depending on SHOW_PIDS bit.
4509          * We do not print status of individual processes
4510          * between PID and <cmdN>. bash does it, but not very well:
4511          * first line shows overall job status, not process status,
4512          * making it impossible to know 1st process status.
4513          */
4514         goto start;
4515         do {
4516                 /* for each process */
4517                 s[0] = '\0';
4518                 col = 33;
4519                 if (mode & SHOW_PIDS)
4520                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4521  start:
4522                 fprintf(out, "%s%*c%s%s",
4523                                 s,
4524                                 33 - col >= 0 ? 33 - col : 0, ' ',
4525                                 ps == jp->ps ? "" : "| ",
4526                                 ps->ps_cmd
4527                 );
4528         } while (++ps != psend);
4529         newline_and_flush(out);
4530
4531         jp->changed = 0;
4532
4533         if (jp->state == JOBDONE) {
4534                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4535                 freejob(jp);
4536         }
4537 }
4538
4539 /*
4540  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4541  * statuses have changed since the last call to showjobs.
4542  */
4543 static void
4544 showjobs(int mode)
4545 {
4546         struct job *jp;
4547
4548         TRACE(("showjobs(0x%x) called\n", mode));
4549
4550         /* Handle all finished jobs */
4551         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4552                 continue;
4553
4554         for (jp = curjob; jp; jp = jp->prev_job) {
4555                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4556                         showjob(jp, mode);
4557                 }
4558         }
4559 }
4560
4561 static int FAST_FUNC
4562 jobscmd(int argc UNUSED_PARAM, char **argv)
4563 {
4564         int mode, m;
4565
4566         mode = 0;
4567         while ((m = nextopt("lp")) != '\0') {
4568                 if (m == 'l')
4569                         mode |= SHOW_PIDS;
4570                 else
4571                         mode |= SHOW_ONLY_PGID;
4572         }
4573
4574         argv = argptr;
4575         if (*argv) {
4576                 do
4577                         showjob(getjob(*argv, 0), mode);
4578                 while (*++argv);
4579         } else {
4580                 showjobs(mode);
4581         }
4582
4583         return 0;
4584 }
4585 #endif /* JOBS */
4586
4587 /* Called only on finished or stopped jobs (no members are running) */
4588 static int
4589 getstatus(struct job *job)
4590 {
4591         int status;
4592         int retval;
4593         struct procstat *ps;
4594
4595         /* Fetch last member's status */
4596         ps = job->ps + job->nprocs - 1;
4597         status = ps->ps_status;
4598         if (pipefail) {
4599                 /* "set -o pipefail" mode: use last _nonzero_ status */
4600                 while (status == 0 && --ps >= job->ps)
4601                         status = ps->ps_status;
4602         }
4603
4604         retval = WEXITSTATUS(status);
4605         if (!WIFEXITED(status)) {
4606 #if JOBS
4607                 retval = WSTOPSIG(status);
4608                 if (!WIFSTOPPED(status))
4609 #endif
4610                 {
4611                         /* XXX: limits number of signals */
4612                         retval = WTERMSIG(status);
4613 #if JOBS
4614                         if (retval == SIGINT)
4615                                 job->sigint = 1;
4616 #endif
4617                 }
4618                 retval += 128;
4619         }
4620         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4621                 jobno(job), job->nprocs, status, retval));
4622         return retval;
4623 }
4624
4625 static int FAST_FUNC
4626 waitcmd(int argc UNUSED_PARAM, char **argv)
4627 {
4628         struct job *job;
4629         int retval;
4630         struct job *jp;
4631 #if BASH_WAIT_N
4632         int status;
4633         char one = nextopt("n");
4634 #else
4635         nextopt(nullstr);
4636 #endif
4637         retval = 0;
4638
4639         argv = argptr;
4640         if (!argv[0]) {
4641                 /* wait for all jobs / one job if -n */
4642                 for (;;) {
4643                         jp = curjob;
4644 #if BASH_WAIT_N
4645                         if (one && !jp)
4646                                 /* exitcode of "wait -n" with nothing to wait for is 127, not 0 */
4647                                 retval = 127;
4648 #endif
4649                         while (1) {
4650                                 if (!jp) /* no running procs */
4651                                         goto ret;
4652                                 if (jp->state == JOBRUNNING)
4653                                         break;
4654                                 jp->waited = 1;
4655                                 jp = jp->prev_job;
4656                         }
4657         /* man bash:
4658          * "When bash is waiting for an asynchronous command via
4659          * the wait builtin, the reception of a signal for which a trap
4660          * has been set will cause the wait builtin to return immediately
4661          * with an exit status greater than 128, immediately after which
4662          * the trap is executed."
4663          */
4664 #if BASH_WAIT_N
4665                         status = dowait(DOWAIT_BLOCK_OR_SIG | DOWAIT_JOBSTATUS, NULL);
4666 #else
4667                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4668 #endif
4669         /* if child sends us a signal *and immediately exits*,
4670          * dowait() returns pid > 0. Check this case,
4671          * not "if (dowait() < 0)"!
4672          */
4673                         if (pending_sig)
4674                                 goto sigout;
4675 #if BASH_WAIT_N
4676                         if (one) {
4677                                 /* wait -n waits for one _job_, not one _process_.
4678                                  *  date; sleep 3 & sleep 2 | sleep 1 & wait -n; date
4679                                  * should wait for 2 seconds. Not 1 or 3.
4680                                  */
4681                                 if (status != -1 && !WIFSTOPPED(status)) {
4682                                         retval = WEXITSTATUS(status);
4683                                         if (WIFSIGNALED(status))
4684                                                 retval = WTERMSIG(status) + 128;
4685                                         goto ret;
4686                                 }
4687                         }
4688 #endif
4689                 }
4690         }
4691
4692         retval = 127;
4693         do {
4694                 if (**argv != '%') {
4695                         pid_t pid = number(*argv);
4696                         job = curjob;
4697                         while (1) {
4698                                 if (!job)
4699                                         goto repeat;
4700                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4701                                         break;
4702                                 job = job->prev_job;
4703                         }
4704                 } else {
4705                         job = getjob(*argv, 0);
4706                 }
4707                 /* loop until process terminated or stopped */
4708                 while (job->state == JOBRUNNING) {
4709                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4710                         if (pending_sig)
4711                                 goto sigout;
4712                 }
4713                 job->waited = 1;
4714                 retval = getstatus(job);
4715  repeat: ;
4716         } while (*++argv);
4717
4718  ret:
4719         return retval;
4720  sigout:
4721         retval = 128 + pending_sig;
4722         return retval;
4723 }
4724
4725 static struct job *
4726 growjobtab(void)
4727 {
4728         size_t len;
4729         ptrdiff_t offset;
4730         struct job *jp, *jq;
4731
4732         len = njobs * sizeof(*jp);
4733         jq = jobtab;
4734         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4735
4736         offset = (char *)jp - (char *)jq;
4737         if (offset) {
4738                 /* Relocate pointers */
4739                 size_t l = len;
4740
4741                 jq = (struct job *)((char *)jq + l);
4742                 while (l) {
4743                         l -= sizeof(*jp);
4744                         jq--;
4745 #define joff(p) ((struct job *)((char *)(p) + l))
4746 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4747                         if (joff(jp)->ps == &jq->ps0)
4748                                 jmove(joff(jp)->ps);
4749                         if (joff(jp)->prev_job)
4750                                 jmove(joff(jp)->prev_job);
4751                 }
4752                 if (curjob)
4753                         jmove(curjob);
4754 #undef joff
4755 #undef jmove
4756         }
4757
4758         njobs += 4;
4759         jobtab = jp;
4760         jp = (struct job *)((char *)jp + len);
4761         jq = jp + 3;
4762         do {
4763                 jq->used = 0;
4764         } while (--jq >= jp);
4765         return jp;
4766 }
4767
4768 /*
4769  * Return a new job structure.
4770  * Called with interrupts off.
4771  */
4772 static struct job *
4773 makejob(/*union node *node,*/ int nprocs)
4774 {
4775         int i;
4776         struct job *jp;
4777
4778         for (i = njobs, jp = jobtab; ; jp++) {
4779                 if (--i < 0) {
4780                         jp = growjobtab();
4781                         break;
4782                 }
4783                 if (jp->used == 0)
4784                         break;
4785                 if (jp->state != JOBDONE || !jp->waited)
4786                         continue;
4787 #if JOBS
4788                 if (doing_jobctl)
4789                         continue;
4790 #endif
4791                 freejob(jp);
4792                 break;
4793         }
4794         memset(jp, 0, sizeof(*jp));
4795 #if JOBS
4796         /* jp->jobctl is a bitfield.
4797          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4798         if (doing_jobctl)
4799                 jp->jobctl = 1;
4800 #endif
4801         jp->prev_job = curjob;
4802         curjob = jp;
4803         jp->used = 1;
4804         jp->ps = &jp->ps0;
4805         if (nprocs > 1) {
4806                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4807         }
4808         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4809                                 jobno(jp)));
4810         return jp;
4811 }
4812
4813 #if JOBS
4814 /*
4815  * Return a string identifying a command (to be printed by the
4816  * jobs command).
4817  */
4818 static char *cmdnextc;
4819
4820 static void
4821 cmdputs(const char *s)
4822 {
4823         static const char vstype[VSTYPE + 1][3] = {
4824                 "", "}", "-", "+", "?", "=",
4825                 "%", "%%", "#", "##"
4826                 IF_BASH_SUBSTR(, ":")
4827                 IF_BASH_PATTERN_SUBST(, "/", "//")
4828         };
4829
4830         const char *p, *str;
4831         char cc[2];
4832         char *nextc;
4833         unsigned char c;
4834         unsigned char subtype = 0;
4835         int quoted = 0;
4836
4837         cc[1] = '\0';
4838         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4839         p = s;
4840         while ((c = *p++) != '\0') {
4841                 str = NULL;
4842                 switch (c) {
4843                 case CTLESC:
4844                         c = *p++;
4845                         break;
4846                 case CTLVAR:
4847                         subtype = *p++;
4848                         if ((subtype & VSTYPE) == VSLENGTH)
4849                                 str = "${#";
4850                         else
4851                                 str = "${";
4852                         goto dostr;
4853                 case CTLENDVAR:
4854                         str = "\"}";
4855                         str += !(quoted & 1);
4856                         quoted >>= 1;
4857                         subtype = 0;
4858                         goto dostr;
4859                 case CTLBACKQ:
4860                         str = "$(...)";
4861                         goto dostr;
4862 #if ENABLE_FEATURE_SH_MATH
4863                 case CTLARI:
4864                         str = "$((";
4865                         goto dostr;
4866                 case CTLENDARI:
4867                         str = "))";
4868                         goto dostr;
4869 #endif
4870                 case CTLQUOTEMARK:
4871                         quoted ^= 1;
4872                         c = '"';
4873                         break;
4874                 case '=':
4875                         if (subtype == 0)
4876                                 break;
4877                         if ((subtype & VSTYPE) != VSNORMAL)
4878                                 quoted <<= 1;
4879                         str = vstype[subtype & VSTYPE];
4880                         if (subtype & VSNUL)
4881                                 c = ':';
4882                         else
4883                                 goto checkstr;
4884                         break;
4885                 case '\'':
4886                 case '\\':
4887                 case '"':
4888                 case '$':
4889                         /* These can only happen inside quotes */
4890                         cc[0] = c;
4891                         str = cc;
4892 //FIXME:
4893 // $ true $$ &
4894 // $ <cr>
4895 // [1]+  Done    true ${\$}   <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4896                         c = '\\';
4897                         break;
4898                 default:
4899                         break;
4900                 }
4901                 USTPUTC(c, nextc);
4902  checkstr:
4903                 if (!str)
4904                         continue;
4905  dostr:
4906                 while ((c = *str++) != '\0') {
4907                         USTPUTC(c, nextc);
4908                 }
4909         } /* while *p++ not NUL */
4910
4911         if (quoted & 1) {
4912                 USTPUTC('"', nextc);
4913         }
4914         *nextc = 0;
4915         cmdnextc = nextc;
4916 }
4917
4918 /* cmdtxt() and cmdlist() call each other */
4919 static void cmdtxt(union node *n);
4920
4921 static void
4922 cmdlist(union node *np, int sep)
4923 {
4924         for (; np; np = np->narg.next) {
4925                 if (!sep)
4926                         cmdputs(" ");
4927                 cmdtxt(np);
4928                 if (sep && np->narg.next)
4929                         cmdputs(" ");
4930         }
4931 }
4932
4933 static void
4934 cmdtxt(union node *n)
4935 {
4936         union node *np;
4937         struct nodelist *lp;
4938         const char *p;
4939
4940         if (!n)
4941                 return;
4942         switch (n->type) {
4943         default:
4944 #if DEBUG
4945                 abort();
4946 #endif
4947         case NPIPE:
4948                 lp = n->npipe.cmdlist;
4949                 for (;;) {
4950                         cmdtxt(lp->n);
4951                         lp = lp->next;
4952                         if (!lp)
4953                                 break;
4954                         cmdputs(" | ");
4955                 }
4956                 break;
4957         case NSEMI:
4958                 p = "; ";
4959                 goto binop;
4960         case NAND:
4961                 p = " && ";
4962                 goto binop;
4963         case NOR:
4964                 p = " || ";
4965  binop:
4966                 cmdtxt(n->nbinary.ch1);
4967                 cmdputs(p);
4968                 n = n->nbinary.ch2;
4969                 goto donode;
4970         case NREDIR:
4971         case NBACKGND:
4972                 n = n->nredir.n;
4973                 goto donode;
4974         case NNOT:
4975                 cmdputs("!");
4976                 n = n->nnot.com;
4977  donode:
4978                 cmdtxt(n);
4979                 break;
4980         case NIF:
4981                 cmdputs("if ");
4982                 cmdtxt(n->nif.test);
4983                 cmdputs("; then ");
4984                 if (n->nif.elsepart) {
4985                         cmdtxt(n->nif.ifpart);
4986                         cmdputs("; else ");
4987                         n = n->nif.elsepart;
4988                 } else {
4989                         n = n->nif.ifpart;
4990                 }
4991                 p = "; fi";
4992                 goto dotail;
4993         case NSUBSHELL:
4994                 cmdputs("(");
4995                 n = n->nredir.n;
4996                 p = ")";
4997                 goto dotail;
4998         case NWHILE:
4999                 p = "while ";
5000                 goto until;
5001         case NUNTIL:
5002                 p = "until ";
5003  until:
5004                 cmdputs(p);
5005                 cmdtxt(n->nbinary.ch1);
5006                 n = n->nbinary.ch2;
5007                 p = "; done";
5008  dodo:
5009                 cmdputs("; do ");
5010  dotail:
5011                 cmdtxt(n);
5012                 goto dotail2;
5013         case NFOR:
5014                 cmdputs("for ");
5015                 cmdputs(n->nfor.var);
5016                 cmdputs(" in ");
5017                 cmdlist(n->nfor.args, 1);
5018                 n = n->nfor.body;
5019                 p = "; done";
5020                 goto dodo;
5021         case NDEFUN:
5022                 cmdputs(n->ndefun.text);
5023                 p = "() { ... }";
5024                 goto dotail2;
5025         case NCMD:
5026                 cmdlist(n->ncmd.args, 1);
5027                 cmdlist(n->ncmd.redirect, 0);
5028                 break;
5029         case NARG:
5030                 p = n->narg.text;
5031  dotail2:
5032                 cmdputs(p);
5033                 break;
5034         case NHERE:
5035         case NXHERE:
5036                 p = "<<...";
5037                 goto dotail2;
5038         case NCASE:
5039                 cmdputs("case ");
5040                 cmdputs(n->ncase.expr->narg.text);
5041                 cmdputs(" in ");
5042                 for (np = n->ncase.cases; np; np = np->nclist.next) {
5043                         cmdtxt(np->nclist.pattern);
5044                         cmdputs(") ");
5045                         cmdtxt(np->nclist.body);
5046                         cmdputs(";; ");
5047                 }
5048                 p = "esac";
5049                 goto dotail2;
5050         case NTO:
5051                 p = ">";
5052                 goto redir;
5053         case NCLOBBER:
5054                 p = ">|";
5055                 goto redir;
5056         case NAPPEND:
5057                 p = ">>";
5058                 goto redir;
5059 #if BASH_REDIR_OUTPUT
5060         case NTO2:
5061 #endif
5062         case NTOFD:
5063                 p = ">&";
5064                 goto redir;
5065         case NFROM:
5066                 p = "<";
5067                 goto redir;
5068         case NFROMFD:
5069                 p = "<&";
5070                 goto redir;
5071         case NFROMTO:
5072                 p = "<>";
5073  redir:
5074                 cmdputs(utoa(n->nfile.fd));
5075                 cmdputs(p);
5076                 if (n->type == NTOFD || n->type == NFROMFD) {
5077                         if (n->ndup.dupfd >= 0)
5078                                 cmdputs(utoa(n->ndup.dupfd));
5079                         else
5080                                 cmdputs("-");
5081                         break;
5082                 }
5083                 n = n->nfile.fname;
5084                 goto donode;
5085         }
5086 }
5087
5088 static char *
5089 commandtext(union node *n)
5090 {
5091         char *name;
5092
5093         STARTSTACKSTR(cmdnextc);
5094         cmdtxt(n);
5095         name = stackblock();
5096         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
5097         return ckstrdup(name);
5098 }
5099 #endif /* JOBS */
5100
5101 /*
5102  * Fork off a subshell.  If we are doing job control, give the subshell its
5103  * own process group.  Jp is a job structure that the job is to be added to.
5104  * N is the command that will be evaluated by the child.  Both jp and n may
5105  * be NULL.  The mode parameter can be one of the following:
5106  *      FORK_FG - Fork off a foreground process.
5107  *      FORK_BG - Fork off a background process.
5108  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
5109  *                   process group even if job control is on.
5110  *
5111  * When job control is turned off, background processes have their standard
5112  * input redirected to /dev/null (except for the second and later processes
5113  * in a pipeline).
5114  *
5115  * Called with interrupts off.
5116  */
5117 /*
5118  * Clear traps on a fork.
5119  */
5120 static void
5121 clear_traps(void)
5122 {
5123         char **tp;
5124
5125         INT_OFF;
5126         for (tp = trap; tp < &trap[NSIG]; tp++) {
5127                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
5128                         if (trap_ptr == trap)
5129                                 free(*tp);
5130                         /* else: it "belongs" to trap_ptr vector, don't free */
5131                         *tp = NULL;
5132                         if ((tp - trap) != 0)
5133                                 setsignal(tp - trap);
5134                 }
5135         }
5136         may_have_traps = 0;
5137         INT_ON;
5138 }
5139
5140 /* Lives far away from here, needed for forkchild */
5141 static void closescript(void);
5142
5143 /* Called after fork(), in child */
5144 /* jp and n are NULL when called by openhere() for heredoc support */
5145 static NOINLINE void
5146 forkchild(struct job *jp, union node *n, int mode)
5147 {
5148         int oldlvl;
5149
5150         TRACE(("Child shell %d\n", getpid()));
5151         oldlvl = shlvl;
5152         shlvl++;
5153
5154         /* man bash: "Non-builtin commands run by bash have signal handlers
5155          * set to the values inherited by the shell from its parent".
5156          * Do we do it correctly? */
5157
5158         closescript();
5159
5160         if (mode == FORK_NOJOB          /* is it `xxx` ? */
5161          && n && n->type == NCMD        /* is it single cmd? */
5162         /* && n->ncmd.args->type == NARG - always true? */
5163          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
5164          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
5165         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
5166         ) {
5167                 TRACE(("Trap hack\n"));
5168                 /* Awful hack for `trap` or $(trap).
5169                  *
5170                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
5171                  * contains an example where "trap" is executed in a subshell:
5172                  *
5173                  * save_traps=$(trap)
5174                  * ...
5175                  * eval "$save_traps"
5176                  *
5177                  * Standard does not say that "trap" in subshell shall print
5178                  * parent shell's traps. It only says that its output
5179                  * must have suitable form, but then, in the above example
5180                  * (which is not supposed to be normative), it implies that.
5181                  *
5182                  * bash (and probably other shell) does implement it
5183                  * (traps are reset to defaults, but "trap" still shows them),
5184                  * but as a result, "trap" logic is hopelessly messed up:
5185                  *
5186                  * # trap
5187                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
5188                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
5189                  * # true | trap   <--- trap is in subshell - no output (ditto)
5190                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
5191                  * trap -- 'echo Ho' SIGWINCH
5192                  * # echo `(trap)`         <--- in subshell in subshell - output
5193                  * trap -- 'echo Ho' SIGWINCH
5194                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
5195                  * trap -- 'echo Ho' SIGWINCH
5196                  *
5197                  * The rules when to forget and when to not forget traps
5198                  * get really complex and nonsensical.
5199                  *
5200                  * Our solution: ONLY bare $(trap) or `trap` is special.
5201                  */
5202                 /* Save trap handler strings for trap builtin to print */
5203                 trap_ptr = xmemdup(trap, sizeof(trap));
5204                 /* Fall through into clearing traps */
5205         }
5206         clear_traps();
5207 #if JOBS
5208         /* do job control only in root shell */
5209         doing_jobctl = 0;
5210         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
5211                 pid_t pgrp;
5212
5213                 if (jp->nprocs == 0)
5214                         pgrp = getpid();
5215                 else
5216                         pgrp = jp->ps[0].ps_pid;
5217                 /* this can fail because we are doing it in the parent also */
5218                 setpgid(0, pgrp);
5219                 if (mode == FORK_FG)
5220                         xtcsetpgrp(ttyfd, pgrp);
5221                 setsignal(SIGTSTP);
5222                 setsignal(SIGTTOU);
5223         } else
5224 #endif
5225         if (mode == FORK_BG) {
5226                 /* man bash: "When job control is not in effect,
5227                  * asynchronous commands ignore SIGINT and SIGQUIT" */
5228                 ignoresig(SIGINT);
5229                 ignoresig(SIGQUIT);
5230                 if (jp->nprocs == 0) {
5231                         close(0);
5232                         if (open(bb_dev_null, O_RDONLY) != 0)
5233                                 ash_msg_and_raise_perror("can't open '%s'", bb_dev_null);
5234                 }
5235         }
5236         if (oldlvl == 0) {
5237                 if (iflag) { /* why if iflag only? */
5238                         setsignal(SIGINT);
5239                         setsignal(SIGTERM);
5240                 }
5241                 /* man bash:
5242                  * "In all cases, bash ignores SIGQUIT. Non-builtin
5243                  * commands run by bash have signal handlers
5244                  * set to the values inherited by the shell
5245                  * from its parent".
5246                  * Take care of the second rule: */
5247                 setsignal(SIGQUIT);
5248         }
5249 #if JOBS
5250         if (n && n->type == NCMD
5251          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5252         ) {
5253                 TRACE(("Job hack\n"));
5254                 /* "jobs": we do not want to clear job list for it,
5255                  * instead we remove only _its_ own_ job from job list.
5256                  * This makes "jobs .... | cat" more useful.
5257                  */
5258                 freejob(curjob);
5259                 return;
5260         }
5261 #endif
5262         for (jp = curjob; jp; jp = jp->prev_job)
5263                 freejob(jp);
5264         jobless = 0;
5265 }
5266
5267 /* Called after fork(), in parent */
5268 #if !JOBS
5269 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5270 #endif
5271 static void
5272 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5273 {
5274         TRACE(("In parent shell: child = %d\n", pid));
5275         if (!jp) {
5276                 /* jp is NULL when called by openhere() for heredoc support */
5277                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5278                         continue;
5279                 jobless++;
5280                 return;
5281         }
5282 #if JOBS
5283         if (mode != FORK_NOJOB && jp->jobctl) {
5284                 int pgrp;
5285
5286                 if (jp->nprocs == 0)
5287                         pgrp = pid;
5288                 else
5289                         pgrp = jp->ps[0].ps_pid;
5290                 /* This can fail because we are doing it in the child also */
5291                 setpgid(pid, pgrp);
5292         }
5293 #endif
5294         if (mode == FORK_BG) {
5295                 backgndpid = pid;               /* set $! */
5296                 set_curjob(jp, CUR_RUNNING);
5297         }
5298         if (jp) {
5299                 struct procstat *ps = &jp->ps[jp->nprocs++];
5300                 ps->ps_pid = pid;
5301                 ps->ps_status = -1;
5302                 ps->ps_cmd = nullstr;
5303 #if JOBS
5304                 if (doing_jobctl && n)
5305                         ps->ps_cmd = commandtext(n);
5306 #endif
5307         }
5308 }
5309
5310 /* jp and n are NULL when called by openhere() for heredoc support */
5311 static int
5312 forkshell(struct job *jp, union node *n, int mode)
5313 {
5314         int pid;
5315
5316         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5317         pid = fork();
5318         if (pid < 0) {
5319                 TRACE(("Fork failed, errno=%d", errno));
5320                 if (jp)
5321                         freejob(jp);
5322                 ash_msg_and_raise_perror("can't fork");
5323         }
5324         if (pid == 0) {
5325                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5326                 forkchild(jp, n, mode);
5327         } else {
5328                 forkparent(jp, n, mode, pid);
5329         }
5330         return pid;
5331 }
5332
5333 /*
5334  * Wait for job to finish.
5335  *
5336  * Under job control we have the problem that while a child process
5337  * is running interrupts generated by the user are sent to the child
5338  * but not to the shell.  This means that an infinite loop started by
5339  * an interactive user may be hard to kill.  With job control turned off,
5340  * an interactive user may place an interactive program inside a loop.
5341  * If the interactive program catches interrupts, the user doesn't want
5342  * these interrupts to also abort the loop.  The approach we take here
5343  * is to have the shell ignore interrupt signals while waiting for a
5344  * foreground process to terminate, and then send itself an interrupt
5345  * signal if the child process was terminated by an interrupt signal.
5346  * Unfortunately, some programs want to do a bit of cleanup and then
5347  * exit on interrupt; unless these processes terminate themselves by
5348  * sending a signal to themselves (instead of calling exit) they will
5349  * confuse this approach.
5350  *
5351  * Called with interrupts off.
5352  */
5353 static int
5354 waitforjob(struct job *jp)
5355 {
5356         int st;
5357
5358         TRACE(("waitforjob(%%%d) called\n", jp ? jobno(jp) : 0));
5359
5360         if (!jp) {
5361                 int pid = got_sigchld;
5362
5363                 while (pid > 0)
5364                         pid = dowait(DOWAIT_NONBLOCK, NULL);
5365
5366                 return exitstatus;
5367         }
5368
5369         while (jp->state == JOBRUNNING) {
5370                 /* In non-interactive shells, we _can_ get
5371                  * a keyboard signal here and be EINTRed,
5372                  * but we just loop back, waiting for command to complete.
5373                  *
5374                  * man bash:
5375                  * "If bash is waiting for a command to complete and receives
5376                  * a signal for which a trap has been set, the trap
5377                  * will not be executed until the command completes."
5378                  *
5379                  * Reality is that even if trap is not set, bash
5380                  * will not act on the signal until command completes.
5381                  * Try this. sleep5intoff.c:
5382                  * #include <signal.h>
5383                  * #include <unistd.h>
5384                  * int main() {
5385                  *         sigset_t set;
5386                  *         sigemptyset(&set);
5387                  *         sigaddset(&set, SIGINT);
5388                  *         sigaddset(&set, SIGQUIT);
5389                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5390                  *         sleep(5);
5391                  *         return 0;
5392                  * }
5393                  * $ bash -c './sleep5intoff; echo hi'
5394                  * ^C^C^C^C <--- pressing ^C once a second
5395                  * $ _
5396                  * $ bash -c './sleep5intoff; echo hi'
5397                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5398                  * $ _
5399                  */
5400                 dowait(DOWAIT_BLOCK, jp);
5401         }
5402
5403         st = getstatus(jp);
5404 #if JOBS
5405         if (jp->jobctl) {
5406                 xtcsetpgrp(ttyfd, rootpid);
5407                 restore_tty_if_stopped_or_signaled(jp);
5408
5409                 /*
5410                  * This is truly gross.
5411                  * If we're doing job control, then we did a TIOCSPGRP which
5412                  * caused us (the shell) to no longer be in the controlling
5413                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5414                  * intuit from the subprocess exit status whether a SIGINT
5415                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5416                  */
5417                 if (jp->sigint) /* TODO: do the same with all signals */
5418                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5419         }
5420         if (jp->state == JOBDONE)
5421 #endif
5422                 freejob(jp);
5423         return st;
5424 }
5425
5426 /*
5427  * return 1 if there are stopped jobs, otherwise 0
5428  */
5429 static int
5430 stoppedjobs(void)
5431 {
5432         struct job *jp;
5433         int retval;
5434
5435         retval = 0;
5436         if (job_warning)
5437                 goto out;
5438         jp = curjob;
5439         if (jp && jp->state == JOBSTOPPED) {
5440                 out2str("You have stopped jobs.\n");
5441                 job_warning = 2;
5442                 retval++;
5443         }
5444  out:
5445         return retval;
5446 }
5447
5448
5449 /*
5450  * Code for dealing with input/output redirection.
5451  */
5452
5453 #undef EMPTY
5454 #undef CLOSED
5455 #define EMPTY -2                /* marks an unused slot in redirtab */
5456 #define CLOSED -1               /* marks a slot of previously-closed fd */
5457
5458 /*
5459  * Handle here documents.  Normally we fork off a process to write the
5460  * data to a pipe.  If the document is short, we can stuff the data in
5461  * the pipe without forking.
5462  */
5463 /* openhere needs this forward reference */
5464 static void expandhere(union node *arg, int fd);
5465 static int
5466 openhere(union node *redir)
5467 {
5468         int pip[2];
5469         size_t len = 0;
5470
5471         if (pipe(pip) < 0)
5472                 ash_msg_and_raise_perror("can't create pipe");
5473         if (redir->type == NHERE) {
5474                 len = strlen(redir->nhere.doc->narg.text);
5475                 if (len <= PIPE_BUF) {
5476                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5477                         goto out;
5478                 }
5479         }
5480         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5481                 /* child */
5482                 close(pip[0]);
5483                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5484                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5485                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5486                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5487                 signal(SIGPIPE, SIG_DFL);
5488                 if (redir->type == NHERE)
5489                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5490                 else /* NXHERE */
5491                         expandhere(redir->nhere.doc, pip[1]);
5492                 _exit(EXIT_SUCCESS);
5493         }
5494  out:
5495         close(pip[1]);
5496         return pip[0];
5497 }
5498
5499 static int
5500 openredirect(union node *redir)
5501 {
5502         struct stat sb;
5503         char *fname;
5504         int f;
5505
5506         switch (redir->nfile.type) {
5507 /* Can't happen, our single caller does this itself */
5508 //      case NTOFD:
5509 //      case NFROMFD:
5510 //              return -1;
5511         case NHERE:
5512         case NXHERE:
5513                 return openhere(redir);
5514         }
5515
5516         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5517          * allocated space. Do it only when we know it is safe.
5518          */
5519         fname = redir->nfile.expfname;
5520
5521         switch (redir->nfile.type) {
5522         default:
5523 #if DEBUG
5524                 abort();
5525 #endif
5526         case NFROM:
5527                 f = open(fname, O_RDONLY);
5528                 if (f < 0)
5529                         goto eopen;
5530                 break;
5531         case NFROMTO:
5532                 f = open(fname, O_RDWR|O_CREAT, 0666);
5533                 if (f < 0)
5534                         goto ecreate;
5535                 break;
5536         case NTO:
5537 #if BASH_REDIR_OUTPUT
5538         case NTO2:
5539 #endif
5540                 /* Take care of noclobber mode. */
5541                 if (Cflag) {
5542                         if (stat(fname, &sb) < 0) {
5543                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5544                                 if (f < 0)
5545                                         goto ecreate;
5546                         } else if (!S_ISREG(sb.st_mode)) {
5547                                 f = open(fname, O_WRONLY, 0666);
5548                                 if (f < 0)
5549                                         goto ecreate;
5550                                 if (!fstat(f, &sb) && S_ISREG(sb.st_mode)) {
5551                                         close(f);
5552                                         errno = EEXIST;
5553                                         goto ecreate;
5554                                 }
5555                         } else {
5556                                 errno = EEXIST;
5557                                 goto ecreate;
5558                         }
5559                         break;
5560                 }
5561                 /* FALLTHROUGH */
5562         case NCLOBBER:
5563                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5564                 if (f < 0)
5565                         goto ecreate;
5566                 break;
5567         case NAPPEND:
5568                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5569                 if (f < 0)
5570                         goto ecreate;
5571                 break;
5572         }
5573
5574         return f;
5575  ecreate:
5576         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5577  eopen:
5578         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5579 }
5580
5581 /*
5582  * Copy a file descriptor to be >= 10. Throws exception on error.
5583  */
5584 static int
5585 savefd(int from)
5586 {
5587         int newfd;
5588         int err;
5589
5590         newfd = fcntl(from, F_DUPFD_CLOEXEC, 10);
5591         err = newfd < 0 ? errno : 0;
5592         if (err != EBADF) {
5593                 if (err)
5594                         ash_msg_and_raise_perror("%d", from);
5595                 close(from);
5596                 if (F_DUPFD_CLOEXEC == F_DUPFD)
5597                         close_on_exec_on(newfd);
5598         }
5599
5600         return newfd;
5601 }
5602 static int
5603 dup2_or_raise(int from, int to)
5604 {
5605         int newfd;
5606
5607         newfd = (from != to) ? dup2(from, to) : to;
5608         if (newfd < 0) {
5609                 /* Happens when source fd is not open: try "echo >&99" */
5610                 ash_msg_and_raise_perror("%d", from);
5611         }
5612         return newfd;
5613 }
5614 static int
5615 dup_CLOEXEC(int fd, int avoid_fd)
5616 {
5617         int newfd;
5618  repeat:
5619         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5620         if (newfd >= 0) {
5621                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
5622                         close_on_exec_on(newfd);
5623         } else { /* newfd < 0 */
5624                 if (errno == EBUSY)
5625                         goto repeat;
5626                 if (errno == EINTR)
5627                         goto repeat;
5628         }
5629         return newfd;
5630 }
5631 static int
5632 xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5633 {
5634         int newfd;
5635  repeat:
5636         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5637         if (newfd < 0) {
5638                 if (errno == EBUSY)
5639                         goto repeat;
5640                 if (errno == EINTR)
5641                         goto repeat;
5642                 /* fd was not open? */
5643                 if (errno == EBADF)
5644                         return fd;
5645                 ash_msg_and_raise_perror("%d", newfd);
5646         }
5647         if (F_DUPFD_CLOEXEC == F_DUPFD)
5648                 close_on_exec_on(newfd);
5649         close(fd);
5650         return newfd;
5651 }
5652
5653 /* Struct def and variable are moved down to the first usage site */
5654 struct squirrel {
5655         int orig_fd;
5656         int moved_to;
5657 };
5658 struct redirtab {
5659         struct redirtab *next;
5660         int pair_count;
5661         struct squirrel two_fd[];
5662 };
5663 #define redirlist (G_var.redirlist)
5664
5665 static void
5666 add_squirrel_closed(struct redirtab *sq, int fd)
5667 {
5668         int i;
5669
5670         if (!sq)
5671                 return;
5672
5673         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5674                 /* If we collide with an already moved fd... */
5675                 if (fd == sq->two_fd[i].orig_fd) {
5676                         /* Examples:
5677                          * "echo 3>FILE 3>&- 3>FILE"
5678                          * "echo 3>&- 3>FILE"
5679                          * No need for last redirect to insert
5680                          * another "need to close 3" indicator.
5681                          */
5682                         TRACE(("redirect_fd %d: already moved or closed\n", fd));
5683                         return;
5684                 }
5685         }
5686         TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5687         sq->two_fd[i].orig_fd = fd;
5688         sq->two_fd[i].moved_to = CLOSED;
5689 }
5690
5691 static int
5692 save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5693 {
5694         int i, new_fd;
5695
5696         if (avoid_fd < 9) /* the important case here is that it can be -1 */
5697                 avoid_fd = 9;
5698
5699 #if JOBS
5700         if (fd == ttyfd) {
5701                 /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5702                 ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5703                 TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5704                 return 1; /* "we closed fd" */
5705         }
5706 #endif
5707         /* Are we called from redirect(0)? E.g. redirect
5708          * in a forked child. No need to save fds,
5709          * we aren't going to use them anymore, ok to trash.
5710          */
5711         if (!sq)
5712                 return 0;
5713
5714         /* If this one of script's fds? */
5715         if (fd != 0) {
5716                 struct parsefile *pf = g_parsefile;
5717                 while (pf) {
5718                         /* We skip fd == 0 case because of the following:
5719                          * $ ash  # running ash interactively
5720                          * $ . ./script.sh
5721                          * and in script.sh: "exec 9>&0".
5722                          * Even though top-level pf_fd _is_ 0,
5723                          * it's still ok to use it: "read" builtin uses it,
5724                          * why should we cripple "exec" builtin?
5725                          */
5726                         if (fd == pf->pf_fd) {
5727                                 pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5728                                 return 1; /* "we closed fd" */
5729                         }
5730                         pf = pf->prev;
5731                 }
5732         }
5733
5734         /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5735
5736         /* First: do we collide with some already moved fds? */
5737         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5738                 /* If we collide with an already moved fd... */
5739                 if (fd == sq->two_fd[i].moved_to) {
5740                         new_fd = dup_CLOEXEC(fd, avoid_fd);
5741                         sq->two_fd[i].moved_to = new_fd;
5742                         TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5743                         if (new_fd < 0) /* what? */
5744                                 xfunc_die();
5745                         return 0; /* "we did not close fd" */
5746                 }
5747                 if (fd == sq->two_fd[i].orig_fd) {
5748                         /* Example: echo Hello >/dev/null 1>&2 */
5749                         TRACE(("redirect_fd %d: already moved\n", fd));
5750                         return 0; /* "we did not close fd" */
5751                 }
5752         }
5753
5754         /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5755         new_fd = dup_CLOEXEC(fd, avoid_fd);
5756         TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5757         if (new_fd < 0) {
5758                 if (errno != EBADF)
5759                         xfunc_die();
5760                 /* new_fd = CLOSED; - already is -1 */
5761         }
5762         sq->two_fd[i].moved_to = new_fd;
5763         sq->two_fd[i].orig_fd = fd;
5764
5765         /* if we move stderr, let "set -x" code know */
5766         if (fd == preverrout_fd)
5767                 preverrout_fd = new_fd;
5768
5769         return 0; /* "we did not close fd" */
5770 }
5771
5772 static int
5773 internally_opened_fd(int fd, struct redirtab *sq)
5774 {
5775         int i;
5776 #if JOBS
5777         if (fd == ttyfd)
5778                 return 1;
5779 #endif
5780         /* If this one of script's fds? */
5781         if (fd != 0) {
5782                 struct parsefile *pf = g_parsefile;
5783                 while (pf) {
5784                         if (fd == pf->pf_fd)
5785                                 return 1;
5786                         pf = pf->prev;
5787                 }
5788         }
5789
5790         if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5791                 if (fd == sq->two_fd[i].moved_to)
5792                         return 1;
5793         }
5794         return 0;
5795 }
5796
5797 /*
5798  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5799  * old file descriptors are stashed away so that the redirection can be
5800  * undone by calling popredir.
5801  */
5802 /* flags passed to redirect */
5803 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5804 static void
5805 redirect(union node *redir, int flags)
5806 {
5807         struct redirtab *sv;
5808
5809         if (!redir)
5810                 return;
5811
5812         sv = NULL;
5813         INT_OFF;
5814         if (flags & REDIR_PUSH)
5815                 sv = redirlist;
5816         do {
5817                 int fd;
5818                 int newfd;
5819                 int close_fd;
5820                 int closed;
5821
5822                 fd = redir->nfile.fd;
5823                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5824                         //bb_error_msg("doing %d > %d", fd, newfd);
5825                         newfd = redir->ndup.dupfd;
5826                         close_fd = -1;
5827                 } else {
5828                         newfd = openredirect(redir); /* always >= 0 */
5829                         if (fd == newfd) {
5830                                 /* open() gave us precisely the fd we wanted.
5831                                  * This means that this fd was not busy
5832                                  * (not opened to anywhere).
5833                                  * Remember to close it on restore:
5834                                  */
5835                                 add_squirrel_closed(sv, fd);
5836                                 continue;
5837                         }
5838                         close_fd = newfd;
5839                 }
5840
5841                 if (fd == newfd)
5842                         continue;
5843
5844                 /* if "N>FILE": move newfd to fd */
5845                 /* if "N>&M": dup newfd to fd */
5846                 /* if "N>&-": close fd (newfd is -1) */
5847
5848  IF_BASH_REDIR_OUTPUT(redirect_more:)
5849
5850                 closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5851                 if (newfd == -1) {
5852                         /* "N>&-" means "close me" */
5853                         if (!closed) {
5854                                 /* ^^^ optimization: saving may already
5855                                  * have closed it. If not... */
5856                                 close(fd);
5857                         }
5858                 } else {
5859                         /* if newfd is a script fd or saved fd, simulate EBADF */
5860                         if (internally_opened_fd(newfd, sv)) {
5861                                 errno = EBADF;
5862                                 ash_msg_and_raise_perror("%d", newfd);
5863                         }
5864                         dup2_or_raise(newfd, fd);
5865                         if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5866                                 close(close_fd);
5867 #if BASH_REDIR_OUTPUT
5868                         if (redir->nfile.type == NTO2 && fd == 1) {
5869                                 /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5870                                 fd = 2;
5871                                 newfd = 1;
5872                                 close_fd = -1;
5873                                 goto redirect_more;
5874                         }
5875 #endif
5876                 }
5877         } while ((redir = redir->nfile.next) != NULL);
5878         INT_ON;
5879
5880 //dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5881 #define REDIR_SAVEFD2 0
5882         // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5883         // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5884         // not only for calls with flags containing REDIR_SAVEFD2.
5885         // We do this unconditionally (see save_fd_on_redirect()).
5886         //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5887         //      preverrout_fd = copied_fd2;
5888 }
5889
5890 static int
5891 redirectsafe(union node *redir, int flags)
5892 {
5893         int err;
5894         volatile int saveint;
5895         struct jmploc *volatile savehandler = exception_handler;
5896         struct jmploc jmploc;
5897
5898         SAVE_INT(saveint);
5899         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5900         err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5901         if (!err) {
5902                 exception_handler = &jmploc;
5903                 redirect(redir, flags);
5904         }
5905         exception_handler = savehandler;
5906         if (err && exception_type != EXERROR)
5907                 longjmp(exception_handler->loc, 1);
5908         RESTORE_INT(saveint);
5909         return err;
5910 }
5911
5912 static struct redirtab*
5913 pushredir(union node *redir)
5914 {
5915         struct redirtab *sv;
5916         int i;
5917
5918         if (!redir)
5919                 return redirlist;
5920
5921         i = 0;
5922         do {
5923                 i++;
5924 #if BASH_REDIR_OUTPUT
5925                 if (redir->nfile.type == NTO2)
5926                         i++;
5927 #endif
5928                 redir = redir->nfile.next;
5929         } while (redir);
5930
5931         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5932         sv->pair_count = i;
5933         while (--i >= 0)
5934                 sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5935         sv->next = redirlist;
5936         redirlist = sv;
5937         return sv->next;
5938 }
5939
5940 /*
5941  * Undo the effects of the last redirection.
5942  */
5943 static void
5944 popredir(int drop)
5945 {
5946         struct redirtab *rp;
5947         int i;
5948
5949         if (redirlist == NULL)
5950                 return;
5951         INT_OFF;
5952         rp = redirlist;
5953         for (i = 0; i < rp->pair_count; i++) {
5954                 int fd = rp->two_fd[i].orig_fd;
5955                 int copy = rp->two_fd[i].moved_to;
5956                 if (copy == CLOSED) {
5957                         if (!drop)
5958                                 close(fd);
5959                         continue;
5960                 }
5961                 if (copy != EMPTY) {
5962                         if (!drop) {
5963                                 /*close(fd);*/
5964                                 dup2_or_raise(copy, fd);
5965                         }
5966                         close(copy);
5967                 }
5968         }
5969         redirlist = rp->next;
5970         free(rp);
5971         INT_ON;
5972 }
5973
5974 static void
5975 unwindredir(struct redirtab *stop)
5976 {
5977         while (redirlist != stop)
5978                 popredir(/*drop:*/ 0);
5979 }
5980
5981
5982 /* ============ Routines to expand arguments to commands
5983  *
5984  * We have to deal with backquotes, shell variables, and file metacharacters.
5985  */
5986
5987 #if ENABLE_FEATURE_SH_MATH
5988 static arith_t
5989 ash_arith(const char *s)
5990 {
5991         arith_state_t math_state;
5992         arith_t result;
5993
5994         math_state.lookupvar = lookupvar;
5995         math_state.setvar    = setvar0;
5996         //math_state.endofname = endofname;
5997
5998         INT_OFF;
5999         result = arith(&math_state, s);
6000         if (math_state.errmsg)
6001                 ash_msg_and_raise_error(math_state.errmsg);
6002         INT_ON;
6003
6004         return result;
6005 }
6006 #endif
6007 #if BASH_SUBSTR
6008 # if ENABLE_FEATURE_SH_MATH
6009 static int substr_atoi(const char *s)
6010 {
6011         arith_t t = ash_arith(s);
6012         if (sizeof(t) > sizeof(int)) {
6013                 /* clamp very large or very large negative nums for ${v:N:M}:
6014                  * else "${v:0:0x100000001}" would work as "${v:0:1}"
6015                  */
6016                 if (t > INT_MAX)
6017                         t = INT_MAX;
6018                 if (t < INT_MIN)
6019                         t = INT_MIN;
6020         }
6021         return t;
6022 }
6023 # else
6024 #  define substr_atoi(s) number(s)
6025 # endif
6026 #endif
6027
6028 /*
6029  * expandarg flags
6030  */
6031 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
6032 #define EXP_TILDE       0x2     /* do normal tilde expansion */
6033 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
6034 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
6035 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
6036  * POSIX says for this case:
6037  *  Pathname expansion shall not be performed on the word by a
6038  *  non-interactive shell; an interactive shell may perform it, but shall
6039  *  do so only when the expansion would result in one word.
6040  * Currently, our code complies to the above rule by never globbing
6041  * redirection filenames.
6042  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
6043  * (this means that on a typical Linux distro, bash almost always
6044  * performs globbing, and thus diverges from what we do).
6045  */
6046 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
6047 #define EXP_VARTILDE2   0x20    /* expand tildes after colons only */
6048 #define EXP_WORD        0x40    /* expand word in parameter expansion */
6049 #define EXP_QUOTED      0x100   /* expand word in double quotes */
6050 /*
6051  * rmescape() flags
6052  */
6053 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
6054 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
6055 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
6056 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
6057
6058 /* Add CTLESC when necessary. */
6059 #define QUOTES_ESC     (EXP_FULL | EXP_CASE)
6060 /* Do not skip NUL characters. */
6061 #define QUOTES_KEEPNUL EXP_TILDE
6062
6063 /*
6064  * Structure specifying which parts of the string should be searched
6065  * for IFS characters.
6066  */
6067 struct ifsregion {
6068         struct ifsregion *next; /* next region in list */
6069         int begoff;             /* offset of start of region */
6070         int endoff;             /* offset of end of region */
6071         int nulonly;            /* search for nul bytes only */
6072 };
6073
6074 struct arglist {
6075         struct strlist *list;
6076         struct strlist **lastp;
6077 };
6078
6079 /* output of current string */
6080 static char *expdest;
6081 /* list of back quote expressions */
6082 static struct nodelist *argbackq;
6083 /* first struct in list of ifs regions */
6084 static struct ifsregion ifsfirst;
6085 /* last struct in list */
6086 static struct ifsregion *ifslastp;
6087 /* holds expanded arg list */
6088 static struct arglist exparg;
6089
6090 /*
6091  * Our own itoa().
6092  * cvtnum() is used even if math support is off (to prepare $? values and such).
6093  */
6094 static int
6095 cvtnum(arith_t num)
6096 {
6097         int len;
6098
6099         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
6100         len = sizeof(arith_t) * 3;
6101         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
6102         if (sizeof(arith_t) < 4) len += 2;
6103
6104         expdest = makestrspace(len, expdest);
6105         len = fmtstr(expdest, len, ARITH_FMT, num);
6106         STADJUST(len, expdest);
6107         return len;
6108 }
6109
6110 /*
6111  * Break the argument string into pieces based upon IFS and add the
6112  * strings to the argument list.  The regions of the string to be
6113  * searched for IFS characters have been stored by recordregion.
6114  */
6115 static void
6116 ifsbreakup(char *string, struct arglist *arglist)
6117 {
6118         struct ifsregion *ifsp;
6119         struct strlist *sp;
6120         char *start;
6121         char *p;
6122         char *q;
6123         const char *ifs, *realifs;
6124         int ifsspc;
6125         int nulonly;
6126
6127         start = string;
6128         if (ifslastp != NULL) {
6129                 ifsspc = 0;
6130                 nulonly = 0;
6131                 realifs = ifsset() ? ifsval() : defifs;
6132                 ifsp = &ifsfirst;
6133                 do {
6134                         int afternul;
6135
6136                         p = string + ifsp->begoff;
6137                         afternul = nulonly;
6138                         nulonly = ifsp->nulonly;
6139                         ifs = nulonly ? nullstr : realifs;
6140                         ifsspc = 0;
6141                         while (p < string + ifsp->endoff) {
6142                                 q = p;
6143                                 if ((unsigned char)*p == CTLESC)
6144                                         p++;
6145                                 if (!strchr(ifs, *p)) {
6146                                         p++;
6147                                         continue;
6148                                 }
6149                                 if (!(afternul || nulonly))
6150                                         ifsspc = (strchr(defifs, *p) != NULL);
6151                                 /* Ignore IFS whitespace at start */
6152                                 if (q == start && ifsspc) {
6153                                         p++;
6154                                         start = p;
6155                                         continue;
6156                                 }
6157                                 *q = '\0';
6158                                 sp = stzalloc(sizeof(*sp));
6159                                 sp->text = start;
6160                                 *arglist->lastp = sp;
6161                                 arglist->lastp = &sp->next;
6162                                 p++;
6163                                 if (!nulonly) {
6164                                         for (;;) {
6165                                                 if (p >= string + ifsp->endoff) {
6166                                                         break;
6167                                                 }
6168                                                 q = p;
6169                                                 if ((unsigned char)*p == CTLESC)
6170                                                         p++;
6171                                                 if (strchr(ifs, *p) == NULL) {
6172                                                         p = q;
6173                                                         break;
6174                                                 }
6175                                                 if (strchr(defifs, *p) == NULL) {
6176                                                         if (ifsspc) {
6177                                                                 p++;
6178                                                                 ifsspc = 0;
6179                                                         } else {
6180                                                                 p = q;
6181                                                                 break;
6182                                                         }
6183                                                 } else
6184                                                         p++;
6185                                         }
6186                                 }
6187                                 start = p;
6188                         } /* while */
6189                         ifsp = ifsp->next;
6190                 } while (ifsp != NULL);
6191                 if (nulonly)
6192                         goto add;
6193         }
6194
6195         if (!*start)
6196                 return;
6197
6198  add:
6199         sp = stzalloc(sizeof(*sp));
6200         sp->text = start;
6201         *arglist->lastp = sp;
6202         arglist->lastp = &sp->next;
6203 }
6204
6205 static void
6206 ifsfree(void)
6207 {
6208         struct ifsregion *p = ifsfirst.next;
6209
6210         if (!p)
6211                 goto out;
6212
6213         INT_OFF;
6214         do {
6215                 struct ifsregion *ifsp;
6216                 ifsp = p->next;
6217                 free(p);
6218                 p = ifsp;
6219         } while (p);
6220         ifsfirst.next = NULL;
6221         INT_ON;
6222  out:
6223         ifslastp = NULL;
6224 }
6225
6226 static size_t
6227 esclen(const char *start, const char *p)
6228 {
6229         size_t esc = 0;
6230
6231         while (p > start && (unsigned char)*--p == CTLESC) {
6232                 esc++;
6233         }
6234         return esc;
6235 }
6236
6237 /*
6238  * Remove any CTLESC characters from a string.
6239  */
6240 #if !BASH_PATTERN_SUBST
6241 #define rmescapes(str, flag, slash_position) \
6242         rmescapes(str, flag)
6243 #endif
6244 static char *
6245 rmescapes(char *str, int flag, int *slash_position)
6246 {
6247         static const char qchars[] ALIGN1 = {
6248                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
6249
6250         char *p, *q, *r;
6251         unsigned protect_against_glob;
6252         unsigned globbing;
6253
6254         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash_position));
6255         if (!p)
6256                 return str;
6257
6258         q = p;
6259         r = str;
6260         if (flag & RMESCAPE_ALLOC) {
6261                 size_t len = p - str;
6262                 size_t fulllen = len + strlen(p) + 1;
6263
6264                 if (flag & RMESCAPE_GROW) {
6265                         int strloc = str - (char *)stackblock();
6266                         r = makestrspace(fulllen, expdest);
6267                         /* p and str may be invalidated by makestrspace */
6268                         str = (char *)stackblock() + strloc;
6269                         p = str + len;
6270                 } else if (flag & RMESCAPE_HEAP) {
6271                         r = ckmalloc(fulllen);
6272                 } else {
6273                         r = stalloc(fulllen);
6274                 }
6275                 q = r;
6276                 if (len > 0) {
6277                         q = (char *)mempcpy(q, str, len);
6278                 }
6279         }
6280
6281         globbing = flag & RMESCAPE_GLOB;
6282         protect_against_glob = globbing;
6283         while (*p) {
6284                 if ((unsigned char)*p == CTLQUOTEMARK) {
6285 // Note: protect_against_glob only affect whether
6286 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6287                         p++;
6288                         protect_against_glob = globbing;
6289                         continue;
6290                 }
6291                 if (*p == '\\') {
6292                         /* naked back slash */
6293                         protect_against_glob = 0;
6294                         goto copy;
6295                 }
6296                 if ((unsigned char)*p == CTLESC) {
6297                         p++;
6298 #if DEBUG
6299                         if (*p == '\0')
6300                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6301 #endif
6302                         if (protect_against_glob) {
6303                                 /*
6304                                  * We used to trust glob() and fnmatch() to eat
6305                                  * superfluous escapes (\z where z has no
6306                                  * special meaning anyway). But this causes
6307                                  * bugs such as string of one greek letter rho
6308                                  * (unicode-encoded as two bytes "cf,81")
6309                                  * getting encoded as "cf,CTLESC,81"
6310                                  * and here, converted to "cf,\,81" -
6311                                  * which does not go well with some flavors
6312                                  * of fnmatch() in unicode locales
6313                                  * (for example, glibc <= 2.22).
6314                                  *
6315                                  * Lets add "\" only on the chars which need it.
6316                                  * Testcases for less obvious chars are shown.
6317                                  */
6318                                 if (*p == '*'
6319                                  || *p == '?'
6320                                  || *p == '['
6321                                  || *p == '\\' /* case '\' in \\    ) echo ok;; *) echo WRONG;; esac */
6322                                  || *p == ']'  /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6323                                  || *p == '-'  /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6324                                  || *p == '!'  /* case '!' in [\!]  ) echo ok;; *) echo WRONG;; esac */
6325                                 /* Some libc support [^negate], that's why "^" also needs love */
6326                                  || *p == '^'  /* case '^' in [\^]  ) echo ok;; *) echo WRONG;; esac */
6327                                 ) {
6328                                         *q++ = '\\';
6329                                 }
6330                         }
6331                 }
6332 #if BASH_PATTERN_SUBST
6333                 else if (slash_position && p == str + *slash_position) {
6334                         /* stop handling globbing */
6335                         globbing = 0;
6336                         *slash_position = q - r;
6337                         slash_position = NULL;
6338                 }
6339 #endif
6340                 protect_against_glob = globbing;
6341  copy:
6342                 *q++ = *p++;
6343         }
6344         *q = '\0';
6345         if (flag & RMESCAPE_GROW) {
6346                 expdest = r;
6347                 STADJUST(q - r + 1, expdest);
6348         }
6349         return r;
6350 }
6351 #define pmatch(a, b) !fnmatch((a), (b), 0)
6352
6353 /*
6354  * Prepare a pattern for a expmeta (internal glob(3)) call.
6355  *
6356  * Returns an stalloced string.
6357  */
6358 static char *
6359 preglob(const char *pattern, int flag)
6360 {
6361         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB, NULL);
6362 }
6363
6364 /*
6365  * Put a string on the stack.
6366  */
6367 static void
6368 memtodest(const char *p, size_t len, int syntax, int quotes)
6369 {
6370         char *q;
6371
6372         if (!len)
6373                 return;
6374
6375         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6376
6377         do {
6378                 unsigned char c = *p++;
6379                 if (c) {
6380                         if (quotes & QUOTES_ESC) {
6381                                 int n = SIT(c, syntax);
6382                                 if (n == CCTL
6383                                  || (syntax != BASESYNTAX && n == CBACK)
6384                                 ) {
6385                                         USTPUTC(CTLESC, q);
6386                                 }
6387                         }
6388                 } else if (!(quotes & QUOTES_KEEPNUL))
6389                         continue;
6390                 USTPUTC(c, q);
6391         } while (--len);
6392
6393         expdest = q;
6394 }
6395
6396 static size_t
6397 strtodest(const char *p, int syntax, int quotes)
6398 {
6399         size_t len = strlen(p);
6400         memtodest(p, len, syntax, quotes);
6401         return len;
6402 }
6403
6404 /*
6405  * Record the fact that we have to scan this region of the
6406  * string for IFS characters.
6407  */
6408 static void
6409 recordregion(int start, int end, int nulonly)
6410 {
6411         struct ifsregion *ifsp;
6412
6413         if (ifslastp == NULL) {
6414                 ifsp = &ifsfirst;
6415         } else {
6416                 INT_OFF;
6417                 ifsp = ckzalloc(sizeof(*ifsp));
6418                 /*ifsp->next = NULL; - ckzalloc did it */
6419                 ifslastp->next = ifsp;
6420                 INT_ON;
6421         }
6422         ifslastp = ifsp;
6423         ifslastp->begoff = start;
6424         ifslastp->endoff = end;
6425         ifslastp->nulonly = nulonly;
6426 }
6427
6428 static void
6429 removerecordregions(int endoff)
6430 {
6431         if (ifslastp == NULL)
6432                 return;
6433
6434         if (ifsfirst.endoff > endoff) {
6435                 while (ifsfirst.next) {
6436                         struct ifsregion *ifsp;
6437                         INT_OFF;
6438                         ifsp = ifsfirst.next->next;
6439                         free(ifsfirst.next);
6440                         ifsfirst.next = ifsp;
6441                         INT_ON;
6442                 }
6443                 if (ifsfirst.begoff > endoff) {
6444                         ifslastp = NULL;
6445                 } else {
6446                         ifslastp = &ifsfirst;
6447                         ifsfirst.endoff = endoff;
6448                 }
6449                 return;
6450         }
6451
6452         ifslastp = &ifsfirst;
6453         while (ifslastp->next && ifslastp->next->begoff < endoff)
6454                 ifslastp = ifslastp->next;
6455         while (ifslastp->next) {
6456                 struct ifsregion *ifsp;
6457                 INT_OFF;
6458                 ifsp = ifslastp->next->next;
6459                 free(ifslastp->next);
6460                 ifslastp->next = ifsp;
6461                 INT_ON;
6462         }
6463         if (ifslastp->endoff > endoff)
6464                 ifslastp->endoff = endoff;
6465 }
6466
6467 static char *
6468 exptilde(char *startp, char *p, int flags)
6469 {
6470         unsigned char c;
6471         char *name;
6472         struct passwd *pw;
6473         const char *home;
6474         int quotes = flags & QUOTES_ESC;
6475
6476         name = p + 1;
6477
6478         while ((c = *++p) != '\0') {
6479                 switch (c) {
6480                 case CTLESC:
6481                         return startp;
6482                 case CTLQUOTEMARK:
6483                         return startp;
6484                 case ':':
6485                         if (flags & EXP_VARTILDE)
6486                                 goto done;
6487                         break;
6488                 case '/':
6489                 case CTLENDVAR:
6490                         goto done;
6491                 }
6492         }
6493  done:
6494         *p = '\0';
6495         if (*name == '\0') {
6496                 home = lookupvar("HOME");
6497         } else {
6498                 pw = getpwnam(name);
6499                 if (pw == NULL)
6500                         goto lose;
6501                 home = pw->pw_dir;
6502         }
6503         if (!home)
6504                 goto lose;
6505         *p = c;
6506         strtodest(home, SQSYNTAX, quotes);
6507         return p;
6508  lose:
6509         *p = c;
6510         return startp;
6511 }
6512
6513 /*
6514  * Execute a command inside back quotes.  If it's a builtin command, we
6515  * want to save its output in a block obtained from malloc.  Otherwise
6516  * we fork off a subprocess and get the output of the command via a pipe.
6517  * Should be called with interrupts off.
6518  */
6519 struct backcmd {                /* result of evalbackcmd */
6520         int fd;                 /* file descriptor to read from */
6521         int nleft;              /* number of chars in buffer */
6522         char *buf;              /* buffer */
6523         struct job *jp;         /* job structure for command */
6524 };
6525
6526 /* These forward decls are needed to use "eval" code for backticks handling: */
6527 /* flags in argument to evaltree */
6528 #define EV_EXIT    01           /* exit after evaluating tree */
6529 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6530 static int evaltree(union node *, int);
6531
6532 /* An evaltree() which is known to never return.
6533  * Used to use an alias:
6534  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6535  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6536  */
6537 static ALWAYS_INLINE NORETURN void
6538 evaltreenr(union node *n, int flags)
6539 {
6540         evaltree(n, flags);
6541         bb_unreachable(abort());
6542         /* NOTREACHED */
6543 }
6544
6545 static void FAST_FUNC
6546 evalbackcmd(union node *n, struct backcmd *result)
6547 {
6548         int pip[2];
6549         struct job *jp;
6550
6551         result->fd = -1;
6552         result->buf = NULL;
6553         result->nleft = 0;
6554         result->jp = NULL;
6555         if (n == NULL) {
6556                 goto out;
6557         }
6558
6559         if (pipe(pip) < 0)
6560                 ash_msg_and_raise_perror("can't create pipe");
6561         jp = makejob(/*n,*/ 1);
6562         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6563                 /* child */
6564                 FORCE_INT_ON;
6565                 close(pip[0]);
6566                 if (pip[1] != 1) {
6567                         /*close(1);*/
6568                         dup2_or_raise(pip[1], 1);
6569                         close(pip[1]);
6570                 }
6571 /* TODO: eflag clearing makes the following not abort:
6572  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6573  * which is what bash does (unless it is in POSIX mode).
6574  * dash deleted "eflag = 0" line in the commit
6575  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6576  *  [EVAL] Don't clear eflag in evalbackcmd
6577  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6578  */
6579                 eflag = 0;
6580                 ifsfree();
6581                 evaltreenr(n, EV_EXIT);
6582                 /* NOTREACHED */
6583         }
6584         /* parent */
6585         close(pip[1]);
6586         result->fd = pip[0];
6587         result->jp = jp;
6588
6589  out:
6590         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6591                 result->fd, result->buf, result->nleft, result->jp));
6592 }
6593
6594 /*
6595  * Expand stuff in backwards quotes.
6596  */
6597 static void
6598 expbackq(union node *cmd, int flag)
6599 {
6600         struct backcmd in;
6601         int i;
6602         char buf[128];
6603         char *p;
6604         char *dest;
6605         int startloc;
6606         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6607         struct stackmark smark;
6608
6609         INT_OFF;
6610         startloc = expdest - (char *)stackblock();
6611         pushstackmark(&smark, startloc);
6612         evalbackcmd(cmd, &in);
6613         popstackmark(&smark);
6614
6615         p = in.buf;
6616         i = in.nleft;
6617         if (i == 0)
6618                 goto read;
6619         for (;;) {
6620                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6621  read:
6622                 if (in.fd < 0)
6623                         break;
6624                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6625                 TRACE(("expbackq: read returns %d\n", i));
6626                 if (i <= 0)
6627                         break;
6628                 p = buf;
6629         }
6630
6631         free(in.buf);
6632         if (in.fd >= 0) {
6633                 close(in.fd);
6634                 back_exitstatus = waitforjob(in.jp);
6635         }
6636         INT_ON;
6637
6638         /* Eat all trailing newlines */
6639         dest = expdest;
6640         for (; dest > ((char *)stackblock() + startloc) && dest[-1] == '\n';)
6641                 STUNPUTC(dest);
6642         expdest = dest;
6643
6644         if (!(flag & EXP_QUOTED))
6645                 recordregion(startloc, dest - (char *)stackblock(), 0);
6646         TRACE(("evalbackq: size:%d:'%.*s'\n",
6647                 (int)((dest - (char *)stackblock()) - startloc),
6648                 (int)((dest - (char *)stackblock()) - startloc),
6649                 stackblock() + startloc));
6650 }
6651
6652 #if ENABLE_FEATURE_SH_MATH
6653 /*
6654  * Expand arithmetic expression.  Backup to start of expression,
6655  * evaluate, place result in (backed up) result, adjust string position.
6656  */
6657 static void
6658 expari(int flag)
6659 {
6660         char *p, *start;
6661         int begoff;
6662         int len;
6663
6664         /* ifsfree(); */
6665
6666         /*
6667          * This routine is slightly over-complicated for
6668          * efficiency.  Next we scan backwards looking for the
6669          * start of arithmetic.
6670          */
6671         start = stackblock();
6672         p = expdest - 1;
6673         *p = '\0';
6674         p--;
6675         while (1) {
6676                 int esc;
6677
6678                 while ((unsigned char)*p != CTLARI) {
6679                         p--;
6680 #if DEBUG
6681                         if (p < start) {
6682                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6683                         }
6684 #endif
6685                 }
6686
6687                 esc = esclen(start, p);
6688                 if (!(esc % 2)) {
6689                         break;
6690                 }
6691
6692                 p -= esc + 1;
6693         }
6694
6695         begoff = p - start;
6696
6697         removerecordregions(begoff);
6698
6699         expdest = p;
6700
6701         if (flag & QUOTES_ESC)
6702                 rmescapes(p + 1, 0, NULL);
6703
6704         len = cvtnum(ash_arith(p + 1));
6705
6706         if (!(flag & EXP_QUOTED))
6707                 recordregion(begoff, begoff + len, 0);
6708 }
6709 #endif
6710
6711 /* argstr needs it */
6712 static char *evalvar(char *p, int flags);
6713
6714 /*
6715  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6716  * characters to allow for further processing.  Otherwise treat
6717  * $@ like $* since no splitting will be performed.
6718  */
6719 static void
6720 argstr(char *p, int flags)
6721 {
6722         static const char spclchars[] ALIGN1 = {
6723                 '=',
6724                 ':',
6725                 CTLQUOTEMARK,
6726                 CTLENDVAR,
6727                 CTLESC,
6728                 CTLVAR,
6729                 CTLBACKQ,
6730 #if ENABLE_FEATURE_SH_MATH
6731                 CTLENDARI,
6732 #endif
6733                 '\0'
6734         };
6735         const char *reject = spclchars;
6736         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6737         int inquotes;
6738         size_t length;
6739         int startloc;
6740
6741         if (!(flags & EXP_VARTILDE)) {
6742                 reject += 2;
6743         } else if (flags & EXP_VARTILDE2) {
6744                 reject++;
6745         }
6746         inquotes = 0;
6747         length = 0;
6748         if (flags & EXP_TILDE) {
6749                 char *q;
6750
6751                 flags &= ~EXP_TILDE;
6752  tilde:
6753                 q = p;
6754                 if (*q == '~')
6755                         p = exptilde(p, q, flags);
6756         }
6757  start:
6758         startloc = expdest - (char *)stackblock();
6759         for (;;) {
6760                 unsigned char c;
6761
6762                 length += strcspn(p + length, reject);
6763                 c = p[length];
6764                 if (c) {
6765                         if (!(c & 0x80)
6766                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6767                         ) {
6768                                 /* c == '=' || c == ':' || c == CTLENDARI */
6769                                 length++;
6770                         }
6771                 }
6772                 if (length > 0) {
6773                         int newloc;
6774                         expdest = stack_nputstr(p, length, expdest);
6775                         newloc = expdest - (char *)stackblock();
6776                         if (breakall && !inquotes && newloc > startloc) {
6777                                 recordregion(startloc, newloc, 0);
6778                         }
6779                         startloc = newloc;
6780                 }
6781                 p += length + 1;
6782                 length = 0;
6783
6784                 switch (c) {
6785                 case '\0':
6786                         goto breakloop;
6787                 case '=':
6788                         if (flags & EXP_VARTILDE2) {
6789                                 p--;
6790                                 continue;
6791                         }
6792                         flags |= EXP_VARTILDE2;
6793                         reject++;
6794                         /* fall through */
6795                 case ':':
6796                         /*
6797                          * sort of a hack - expand tildes in variable
6798                          * assignments (after the first '=' and after ':'s).
6799                          */
6800                         if (*--p == '~') {
6801                                 goto tilde;
6802                         }
6803                         continue;
6804                 }
6805
6806                 switch (c) {
6807                 case CTLENDVAR: /* ??? */
6808                         goto breakloop;
6809                 case CTLQUOTEMARK:
6810                         /* "$@" syntax adherence hack */
6811                         if (!inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6812                                 p = evalvar(p + 1, flags | EXP_QUOTED) + 1;
6813                                 goto start;
6814                         }
6815                         inquotes ^= EXP_QUOTED;
6816  addquote:
6817                         if (flags & QUOTES_ESC) {
6818                                 p--;
6819                                 length++;
6820                                 startloc++;
6821                         }
6822                         break;
6823                 case CTLESC:
6824                         startloc++;
6825                         length++;
6826                         goto addquote;
6827                 case CTLVAR:
6828                         TRACE(("argstr: evalvar('%s')\n", p));
6829                         p = evalvar(p, flags | inquotes);
6830                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6831                         goto start;
6832                 case CTLBACKQ:
6833                         expbackq(argbackq->n, flags | inquotes);
6834                         argbackq = argbackq->next;
6835                         goto start;
6836 #if ENABLE_FEATURE_SH_MATH
6837                 case CTLENDARI:
6838                         p--;
6839                         expari(flags | inquotes);
6840                         goto start;
6841 #endif
6842                 }
6843         }
6844  breakloop: ;
6845 }
6846
6847 static char *
6848 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6849                 char *pattern, int quotes, int zero)
6850 {
6851         char *loc, *loc2;
6852         char c;
6853
6854         loc = startp;
6855         loc2 = rmesc;
6856         do {
6857                 int match;
6858                 const char *s = loc2;
6859
6860                 c = *loc2;
6861                 if (zero) {
6862                         *loc2 = '\0';
6863                         s = rmesc;
6864                 }
6865                 match = pmatch(pattern, s);
6866
6867                 *loc2 = c;
6868                 if (match)
6869                         return loc;
6870                 if (quotes && (unsigned char)*loc == CTLESC)
6871                         loc++;
6872                 loc++;
6873                 loc2++;
6874         } while (c);
6875         return NULL;
6876 }
6877
6878 static char *
6879 scanright(char *startp, char *rmesc, char *rmescend,
6880                 char *pattern, int quotes, int match_at_start)
6881 {
6882 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6883         int try2optimize = match_at_start;
6884 #endif
6885         int esc = 0;
6886         char *loc;
6887         char *loc2;
6888
6889         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6890          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6891          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6892          * Logic:
6893          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6894          * and on each iteration they go back two/one char until they reach the beginning.
6895          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6896          */
6897         /* TODO: document in what other circumstances we are called. */
6898
6899         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6900                 int match;
6901                 char c = *loc2;
6902                 const char *s = loc2;
6903                 if (match_at_start) {
6904                         *loc2 = '\0';
6905                         s = rmesc;
6906                 }
6907                 match = pmatch(pattern, s);
6908                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6909                 *loc2 = c;
6910                 if (match)
6911                         return loc;
6912 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6913                 if (try2optimize) {
6914                         /* Maybe we can optimize this:
6915                          * if pattern ends with unescaped *, we can avoid checking
6916                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6917                          * it won't match truncated "raw_value_of_" strings too.
6918                          */
6919                         unsigned plen = strlen(pattern);
6920                         /* Does it end with "*"? */
6921                         if (plen != 0 && pattern[--plen] == '*') {
6922                                 /* "xxxx*" is not escaped */
6923                                 /* "xxx\*" is escaped */
6924                                 /* "xx\\*" is not escaped */
6925                                 /* "x\\\*" is escaped */
6926                                 int slashes = 0;
6927                                 while (plen != 0 && pattern[--plen] == '\\')
6928                                         slashes++;
6929                                 if (!(slashes & 1))
6930                                         break; /* ends with unescaped "*" */
6931                         }
6932                         try2optimize = 0;
6933                 }
6934 #endif
6935                 loc--;
6936                 if (quotes) {
6937                         if (--esc < 0) {
6938                                 esc = esclen(startp, loc);
6939                         }
6940                         if (esc % 2) {
6941                                 esc--;
6942                                 loc--;
6943                         }
6944                 }
6945         }
6946         return NULL;
6947 }
6948
6949 static void varunset(const char *, const char *, const char *, int) NORETURN;
6950 static void
6951 varunset(const char *end, const char *var, const char *umsg, int varflags)
6952 {
6953         const char *msg;
6954         const char *tail;
6955
6956         tail = nullstr;
6957         msg = "parameter not set";
6958         if (umsg) {
6959                 if ((unsigned char)*end == CTLENDVAR) {
6960                         if (varflags & VSNUL)
6961                                 tail = " or null";
6962                 } else {
6963                         msg = umsg;
6964                 }
6965         }
6966         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6967 }
6968
6969 static const char *
6970 subevalvar(char *p, char *varname, int strloc, int subtype,
6971                 int startloc, int varflags, int flag)
6972 {
6973         struct nodelist *saveargbackq = argbackq;
6974         int quotes = flag & QUOTES_ESC;
6975         char *startp;
6976         char *loc;
6977         char *rmesc, *rmescend;
6978         char *str;
6979         int amount, resetloc;
6980         int argstr_flags;
6981         IF_BASH_PATTERN_SUBST(int workloc;)
6982         IF_BASH_PATTERN_SUBST(int slash_pos;)
6983         IF_BASH_PATTERN_SUBST(char *repl;)
6984         int zero;
6985         char *(*scan)(char*, char*, char*, char*, int, int);
6986
6987         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6988         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6989
6990 #if BASH_PATTERN_SUBST
6991         /* For "${v/pattern/repl}", we must find the delimiter _before_
6992          * argstr() call expands possible variable references in pattern:
6993          * think about "v=a; a=a/; echo ${v/$a/r}" case.
6994          */
6995         repl = NULL;
6996         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6997                 /* Find '/' and replace with NUL */
6998                 repl = p;
6999                 /* The pattern can't be empty.
7000                  * IOW: if the first char after "${v//" is a slash,
7001                  * it does not terminate the pattern - it's the first char of the pattern:
7002                  *  v=/dev/ram; echo ${v////-}  prints -dev-ram (pattern is "/")
7003                  *  v=/dev/ram; echo ${v///r/-} prints /dev-am  (pattern is "/r")
7004                  */
7005                 if (*repl == '/')
7006                         repl++;
7007                 for (;;) {
7008                         if (*repl == '\0') {
7009                                 repl = NULL;
7010                                 break;
7011                         }
7012                         if (*repl == '/') {
7013                                 *repl = '\0';
7014                                 break;
7015                         }
7016                         /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */
7017                         if ((unsigned char)*repl == CTLESC && repl[1])
7018                                 repl++;
7019                         repl++;
7020                 }
7021         }
7022 #endif
7023         argstr_flags = EXP_TILDE;
7024         if (subtype != VSASSIGN
7025          && subtype != VSQUESTION
7026 #if BASH_SUBSTR
7027          && subtype != VSSUBSTR
7028 #endif
7029         ) {
7030                 /* EXP_CASE keeps CTLESC's */
7031                 argstr_flags = EXP_TILDE | EXP_CASE;
7032         }
7033         argstr(p, argstr_flags);
7034         //bb_error_msg("str0:'%s'", (char *)stackblock() + strloc);
7035 #if BASH_PATTERN_SUBST
7036         slash_pos = -1;
7037         if (repl) {
7038                 slash_pos = expdest - ((char *)stackblock() + strloc);
7039                 STPUTC('/', expdest);
7040                 //bb_error_msg("repl+1:'%s'", repl + 1);
7041                 argstr(repl + 1, EXP_TILDE); /* EXP_TILDE: echo "${v/x/~}" expands ~ ! */
7042                 *repl = '/';
7043         }
7044 #endif
7045         STPUTC('\0', expdest);
7046         argbackq = saveargbackq;
7047         startp = (char *)stackblock() + startloc;
7048         //bb_error_msg("str1:'%s'", (char *)stackblock() + strloc);
7049
7050         switch (subtype) {
7051         case VSASSIGN:
7052                 setvar0(varname, startp);
7053                 amount = startp - expdest;
7054                 STADJUST(amount, expdest);
7055                 return startp;
7056
7057         case VSQUESTION:
7058                 varunset(p, varname, startp, varflags);
7059                 /* NOTREACHED */
7060
7061 #if BASH_SUBSTR
7062         case VSSUBSTR: {
7063                 int pos, len, orig_len;
7064                 char *colon;
7065
7066                 loc = str = stackblock() + strloc;
7067
7068                 /* Read POS in ${var:POS:LEN} */
7069                 colon = strchr(loc, ':');
7070                 if (colon) *colon = '\0';
7071                 pos = substr_atoi(loc);
7072                 if (colon) *colon = ':';
7073
7074                 /* Read LEN in ${var:POS:LEN} */
7075                 len = str - startp - 1;
7076                 /* *loc != '\0', guaranteed by parser */
7077                 if (quotes) {
7078                         char *ptr;
7079                         /* Adjust the length by the number of escapes */
7080                         for (ptr = startp; ptr < (str - 1); ptr++) {
7081                                 if ((unsigned char)*ptr == CTLESC) {
7082                                         len--;
7083                                         ptr++;
7084                                 }
7085                         }
7086                 }
7087                 orig_len = len;
7088                 if (*loc++ == ':') {
7089                         /* ${var::LEN} */
7090                         len = substr_atoi(loc);
7091                 } else {
7092                         /* Skip POS in ${var:POS:LEN} */
7093                         len = orig_len;
7094                         while (*loc && *loc != ':')
7095                                 loc++;
7096                         if (*loc++ == ':')
7097                                 len = substr_atoi(loc);
7098                 }
7099                 if (pos < 0) {
7100                         /* ${VAR:$((-n)):l} starts n chars from the end */
7101                         pos = orig_len + pos;
7102                 }
7103                 if ((unsigned)pos >= orig_len) {
7104                         /* apart from obvious ${VAR:999999:l},
7105                          * covers ${VAR:$((-9999999)):l} - result is ""
7106                          * (bash compat)
7107                          */
7108                         pos = 0;
7109                         len = 0;
7110                 }
7111                 if (len < 0) {
7112                         /* ${VAR:N:-M} sets LEN to strlen()-M */
7113                         len = (orig_len - pos) + len;
7114                 }
7115                 if ((unsigned)len > (orig_len - pos))
7116                         len = orig_len - pos;
7117
7118                 for (str = startp; pos; str++, pos--) {
7119                         if (quotes && (unsigned char)*str == CTLESC)
7120                                 str++;
7121                 }
7122                 for (loc = startp; len; len--) {
7123                         if (quotes && (unsigned char)*str == CTLESC)
7124                                 *loc++ = *str++;
7125                         *loc++ = *str++;
7126                 }
7127                 *loc = '\0';
7128                 amount = loc - expdest;
7129                 STADJUST(amount, expdest);
7130                 return loc;
7131         }
7132 #endif /* BASH_SUBSTR */
7133         }
7134
7135         resetloc = expdest - (char *)stackblock();
7136
7137 #if BASH_PATTERN_SUBST
7138         repl = NULL;
7139
7140         /* We'll comeback here if we grow the stack while handling
7141          * a VSREPLACE or VSREPLACEALL, since our pointers into the
7142          * stack will need rebasing, and we'll need to remove our work
7143          * areas each time
7144          */
7145  restart:
7146 #endif
7147
7148         amount = expdest - ((char *)stackblock() + resetloc);
7149         STADJUST(-amount, expdest);
7150         startp = (char *)stackblock() + startloc;
7151
7152         rmesc = startp;
7153         rmescend = (char *)stackblock() + strloc;
7154         //bb_error_msg("str7:'%s'", rmescend);
7155         if (quotes) {
7156 //TODO: how to handle slash_pos here if string changes (shortens?)
7157                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW, NULL);
7158                 if (rmesc != startp) {
7159                         rmescend = expdest;
7160                         startp = (char *)stackblock() + startloc;
7161                 }
7162         }
7163         rmescend--;
7164         str = (char *)stackblock() + strloc;
7165         /*
7166          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
7167          * The result is a_\_z_c (not a\_\_z_c)!
7168          *
7169          * The search pattern and replace string treat backslashes differently!
7170          * "&slash_pos" causes rmescapes() to work differently on the pattern
7171          * and string.  It's only used on the first call.
7172          */
7173         //bb_error_msg("str8:'%s' slash_pos:%d", str, slash_pos);
7174         rmescapes(str, RMESCAPE_GLOB,
7175                 repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos)
7176         );
7177
7178 #if BASH_PATTERN_SUBST
7179         workloc = expdest - (char *)stackblock();
7180         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
7181                 int len;
7182                 char *idx, *end;
7183
7184                 if (!repl) {
7185                         //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos);
7186                         repl = nullstr;
7187                         if (slash_pos >= 0) {
7188                                 repl = str + slash_pos;
7189                                 *repl++ = '\0';
7190                         }
7191                 }
7192                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
7193
7194                 /* If there's no pattern to match, return the expansion unmolested */
7195                 if (str[0] == '\0')
7196                         return NULL;
7197
7198                 len = 0;
7199                 idx = startp;
7200                 end = str - 1;
7201                 while (idx < end) {
7202  try_to_match:
7203                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
7204                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
7205                         if (!loc) {
7206                                 /* No match, advance */
7207                                 char *restart_detect = stackblock();
7208  skip_matching:
7209                                 STPUTC(*idx, expdest);
7210                                 if (quotes && (unsigned char)*idx == CTLESC) {
7211                                         idx++;
7212                                         len++;
7213                                         STPUTC(*idx, expdest);
7214                                 }
7215                                 if (stackblock() != restart_detect)
7216                                         goto restart;
7217                                 idx++;
7218                                 len++;
7219                                 rmesc++;
7220                                 /* continue; - prone to quadratic behavior, smarter code: */
7221                                 if (idx >= end)
7222                                         break;
7223                                 if (str[0] == '*') {
7224                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
7225                                          * it would never match "ong_string" etc, no point in trying.
7226                                          */
7227                                         goto skip_matching;
7228                                 }
7229                                 goto try_to_match;
7230                         }
7231
7232                         if (subtype == VSREPLACEALL) {
7233                                 while (idx < loc) {
7234                                         if (quotes && (unsigned char)*idx == CTLESC)
7235                                                 idx++;
7236                                         idx++;
7237                                         rmesc++;
7238                                 }
7239                         } else {
7240                                 idx = loc;
7241                         }
7242
7243                         //bb_error_msg("repl:'%s'", repl);
7244                         for (loc = (char*)repl; *loc; loc++) {
7245                                 char *restart_detect = stackblock();
7246                                 if (quotes && *loc == '\\') {
7247                                         STPUTC(CTLESC, expdest);
7248                                         len++;
7249                                 }
7250                                 STPUTC(*loc, expdest);
7251                                 if (stackblock() != restart_detect)
7252                                         goto restart;
7253                                 len++;
7254                         }
7255
7256                         if (subtype == VSREPLACE) {
7257                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
7258                                 while (*idx) {
7259                                         char *restart_detect = stackblock();
7260                                         STPUTC(*idx, expdest);
7261                                         if (stackblock() != restart_detect)
7262                                                 goto restart;
7263                                         len++;
7264                                         idx++;
7265                                 }
7266                                 break;
7267                         }
7268                 }
7269
7270                 /* We've put the replaced text into a buffer at workloc, now
7271                  * move it to the right place and adjust the stack.
7272                  */
7273                 STPUTC('\0', expdest);
7274                 startp = (char *)stackblock() + startloc;
7275                 memmove(startp, (char *)stackblock() + workloc, len + 1);
7276                 //bb_error_msg("startp:'%s'", startp);
7277                 amount = expdest - (startp + len);
7278                 STADJUST(-amount, expdest);
7279                 return startp;
7280         }
7281 #endif /* BASH_PATTERN_SUBST */
7282
7283         subtype -= VSTRIMRIGHT;
7284 #if DEBUG
7285         if (subtype < 0 || subtype > 7)
7286                 abort();
7287 #endif
7288         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
7289         zero = subtype >> 1;
7290         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
7291         scan = (subtype & 1) ^ zero ? scanleft : scanright;
7292
7293         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
7294         if (loc) {
7295                 if (zero) {
7296                         memmove(startp, loc, str - loc);
7297                         loc = startp + (str - loc) - 1;
7298                 }
7299                 *loc = '\0';
7300                 amount = loc - expdest;
7301                 STADJUST(amount, expdest);
7302         }
7303         return loc;
7304 }
7305
7306 /*
7307  * Add the value of a specialized variable to the stack string.
7308  * name parameter (examples):
7309  * ash -c 'echo $1'      name:'1='
7310  * ash -c 'echo $qwe'    name:'qwe='
7311  * ash -c 'echo $$'      name:'$='
7312  * ash -c 'echo ${$}'    name:'$='
7313  * ash -c 'echo ${$##q}' name:'$=q'
7314  * ash -c 'echo ${#$}'   name:'$='
7315  * note: examples with bad shell syntax:
7316  * ash -c 'echo ${#$1}'  name:'$=1'
7317  * ash -c 'echo ${#1#}'  name:'1=#'
7318  */
7319 static NOINLINE ssize_t
7320 varvalue(char *name, int varflags, int flags, int quoted)
7321 {
7322         const char *p;
7323         int num;
7324         int i;
7325         ssize_t len = 0;
7326         int sep;
7327         int subtype = varflags & VSTYPE;
7328         int discard = subtype == VSPLUS || subtype == VSLENGTH;
7329         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
7330         int syntax;
7331
7332         sep = (flags & EXP_FULL) << CHAR_BIT;
7333         syntax = quoted ? DQSYNTAX : BASESYNTAX;
7334
7335         switch (*name) {
7336         case '$':
7337                 num = rootpid;
7338                 goto numvar;
7339         case '?':
7340                 num = exitstatus;
7341                 goto numvar;
7342         case '#':
7343                 num = shellparam.nparam;
7344                 goto numvar;
7345         case '!':
7346                 num = backgndpid;
7347                 if (num == 0)
7348                         return -1;
7349  numvar:
7350                 len = cvtnum(num);
7351                 goto check_1char_name;
7352         case '-':
7353                 expdest = makestrspace(NOPTS, expdest);
7354                 for (i = NOPTS - 1; i >= 0; i--) {
7355                         if (optlist[i] && optletters(i)) {
7356                                 USTPUTC(optletters(i), expdest);
7357                                 len++;
7358                         }
7359                 }
7360  check_1char_name:
7361 #if 0
7362                 /* handles cases similar to ${#$1} */
7363                 if (name[2] != '\0')
7364                         raise_error_syntax("bad substitution");
7365 #endif
7366                 break;
7367         case '@':
7368                 if (quoted && sep)
7369                         goto param;
7370                 /* fall through */
7371         case '*': {
7372                 char **ap;
7373                 char sepc;
7374                 char c;
7375
7376                 /* We will set c to 0 or ~0 depending on whether
7377                  * we're doing field splitting.  We won't do field
7378                  * splitting if either we're quoted or sep is zero.
7379                  *
7380                  * Instead of testing (quoted || !sep) the following
7381                  * trick optimises away any branches by using the
7382                  * fact that EXP_QUOTED (which is the only bit that
7383                  * can be set in quoted) is the same as EXP_FULL <<
7384                  * CHAR_BIT (which is the only bit that can be set
7385                  * in sep).
7386                  */
7387 #if EXP_QUOTED >> CHAR_BIT != EXP_FULL
7388 #error The following two lines expect EXP_QUOTED == EXP_FULL << CHAR_BIT
7389 #endif
7390                 c = !((quoted | ~sep) & EXP_QUOTED) - 1;
7391                 sep &= ~quoted;
7392                 sep |= ifsset() ? (unsigned char)(c & ifsval()[0]) : ' ';
7393  param:
7394                 sepc = sep;
7395                 ap = shellparam.p;
7396                 if (!ap)
7397                         return -1;
7398                 while ((p = *ap++) != NULL) {
7399                         len += strtodest(p, syntax, quotes);
7400
7401                         if (*ap && sep) {
7402                                 len++;
7403                                 memtodest(&sepc, 1, syntax, quotes);
7404                         }
7405                 }
7406                 break;
7407         } /* case '*' */
7408         case '0':
7409         case '1':
7410         case '2':
7411         case '3':
7412         case '4':
7413         case '5':
7414         case '6':
7415         case '7':
7416         case '8':
7417         case '9':
7418                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7419                 if (num < 0 || num > shellparam.nparam)
7420                         return -1;
7421                 p = num ? shellparam.p[num - 1] : arg0;
7422                 goto value;
7423         default:
7424                 /* NB: name has form "VAR=..." */
7425                 p = lookupvar(name);
7426  value:
7427                 if (!p)
7428                         return -1;
7429
7430                 len = strtodest(p, syntax, quotes);
7431 #if ENABLE_UNICODE_SUPPORT
7432                 if (subtype == VSLENGTH && len > 0) {
7433                         reinit_unicode_for_ash();
7434                         if (unicode_status == UNICODE_ON) {
7435                                 STADJUST(-len, expdest);
7436                                 discard = 0;
7437                                 len = unicode_strlen(p);
7438                         }
7439                 }
7440 #endif
7441                 break;
7442         }
7443
7444         if (discard)
7445                 STADJUST(-len, expdest);
7446         return len;
7447 }
7448
7449 /*
7450  * Expand a variable, and return a pointer to the next character in the
7451  * input string.
7452  */
7453 static char *
7454 evalvar(char *p, int flag)
7455 {
7456         char varflags;
7457         char subtype;
7458         int quoted;
7459         char *var;
7460         int patloc;
7461         int startloc;
7462         ssize_t varlen;
7463
7464         varflags = (unsigned char) *p++;
7465         subtype = varflags & VSTYPE;
7466
7467         if (!subtype)
7468                 raise_error_syntax("bad substitution");
7469
7470         quoted = flag & EXP_QUOTED;
7471         var = p;
7472         startloc = expdest - (char *)stackblock();
7473         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7474
7475  again:
7476         varlen = varvalue(var, varflags, flag, quoted);
7477         if (varflags & VSNUL)
7478                 varlen--;
7479
7480         if (subtype == VSPLUS) {
7481                 varlen = -1 - varlen;
7482                 goto vsplus;
7483         }
7484
7485         if (subtype == VSMINUS) {
7486  vsplus:
7487                 if (varlen < 0) {
7488                         argstr(
7489                                 p,
7490                                 flag | EXP_TILDE | EXP_WORD
7491                         );
7492                         goto end;
7493                 }
7494                 goto record;
7495         }
7496
7497         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7498                 if (varlen >= 0)
7499                         goto record;
7500
7501                 subevalvar(p, var, 0, subtype, startloc, varflags,
7502                            flag & ~QUOTES_ESC);
7503                 varflags &= ~VSNUL;
7504                 /*
7505                  * Remove any recorded regions beyond
7506                  * start of variable
7507                  */
7508                 removerecordregions(startloc);
7509                 goto again;
7510         }
7511
7512         if (varlen < 0 && uflag)
7513                 varunset(p, var, 0, 0);
7514
7515         if (subtype == VSLENGTH) {
7516                 cvtnum(varlen > 0 ? varlen : 0);
7517                 goto record;
7518         }
7519
7520         if (subtype == VSNORMAL) {
7521  record:
7522                 if (quoted) {
7523                         quoted = *var == '@' && shellparam.nparam;
7524                         if (!quoted)
7525                                 goto end;
7526                 }
7527                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7528                 goto end;
7529         }
7530
7531 #if DEBUG
7532         switch (subtype) {
7533         case VSTRIMLEFT:
7534         case VSTRIMLEFTMAX:
7535         case VSTRIMRIGHT:
7536         case VSTRIMRIGHTMAX:
7537 #if BASH_SUBSTR
7538         case VSSUBSTR:
7539 #endif
7540 #if BASH_PATTERN_SUBST
7541         case VSREPLACE:
7542         case VSREPLACEALL:
7543 #endif
7544                 break;
7545         default:
7546                 abort();
7547         }
7548 #endif
7549
7550         if (varlen >= 0) {
7551                 /*
7552                  * Terminate the string and start recording the pattern
7553                  * right after it
7554                  */
7555                 STPUTC('\0', expdest);
7556                 patloc = expdest - (char *)stackblock();
7557                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7558                                 startloc, varflags, flag)) {
7559                         int amount = expdest - (
7560                                 (char *)stackblock() + patloc - 1
7561                         );
7562                         STADJUST(-amount, expdest);
7563                 }
7564                 /* Remove any recorded regions beyond start of variable */
7565                 removerecordregions(startloc);
7566                 goto record;
7567         }
7568
7569         varlen = 0;
7570
7571  end:
7572         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7573                 int nesting = 1;
7574                 for (;;) {
7575                         unsigned char c = *p++;
7576                         if (c == CTLESC)
7577                                 p++;
7578                         else if (c == CTLBACKQ) {
7579                                 if (varlen >= 0)
7580                                         argbackq = argbackq->next;
7581                         } else if (c == CTLVAR) {
7582                                 if ((*p++ & VSTYPE) != VSNORMAL)
7583                                         nesting++;
7584                         } else if (c == CTLENDVAR) {
7585                                 if (--nesting == 0)
7586                                         break;
7587                         }
7588                 }
7589         }
7590         return p;
7591 }
7592
7593 /*
7594  * Add a file name to the list.
7595  */
7596 static void
7597 addfname(const char *name)
7598 {
7599         struct strlist *sp;
7600
7601         sp = stzalloc(sizeof(*sp));
7602         sp->text = sstrdup(name);
7603         *exparg.lastp = sp;
7604         exparg.lastp = &sp->next;
7605 }
7606
7607 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7608 static int
7609 hasmeta(const char *p)
7610 {
7611         static const char chars[] ALIGN1 = {
7612                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7613         };
7614
7615         for (;;) {
7616                 p = strpbrk(p, chars);
7617                 if (!p)
7618                         break;
7619                 switch ((unsigned char)*p) {
7620                 case CTLQUOTEMARK:
7621                         for (;;) {
7622                                 p++;
7623                                 if ((unsigned char)*p == CTLQUOTEMARK)
7624                                         break;
7625                                 if ((unsigned char)*p == CTLESC)
7626                                         p++;
7627                                 if (*p == '\0') /* huh? */
7628                                         return 0;
7629                         }
7630                         break;
7631                 case '\\':
7632                 case CTLESC:
7633                         p++;
7634                         if (*p == '\0')
7635                                 return 0;
7636                         break;
7637                 case '[':
7638                         if (!strchr(p + 1, ']')) {
7639                                 /* It's not a properly closed [] pattern,
7640                                  * but other metas may follow. Continue checking.
7641                                  * my[file* _is_ globbed by bash
7642                                  * and matches filenames like "my[file1".
7643                                  */
7644                                 break;
7645                         }
7646                         /* fallthrough */
7647                 default:
7648                 /* case '*': */
7649                 /* case '?': */
7650                         return 1;
7651                 }
7652                 p++;
7653         }
7654
7655         return 0;
7656 }
7657
7658 /* If we want to use glob() from libc... */
7659 #if !ENABLE_ASH_INTERNAL_GLOB
7660
7661 /* Add the result of glob() to the list */
7662 static void
7663 addglob(const glob_t *pglob)
7664 {
7665         char **p = pglob->gl_pathv;
7666
7667         do {
7668                 addfname(*p);
7669         } while (*++p);
7670 }
7671 static void
7672 expandmeta(struct strlist *str /*, int flag*/)
7673 {
7674         /* TODO - EXP_REDIR */
7675
7676         while (str) {
7677                 char *p;
7678                 glob_t pglob;
7679                 int i;
7680
7681                 if (fflag)
7682                         goto nometa;
7683
7684                 if (!hasmeta(str->text))
7685                         goto nometa;
7686
7687                 INT_OFF;
7688                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7689 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7690 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7691 //
7692 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7693 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7694 // Which means you need to unescape the string, right? Not so fast:
7695 // if there _is_ a file named "file\?" (with backslash), it is returned
7696 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7697 // You DON'T KNOW by looking at the result whether you need to unescape it.
7698 //
7699 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7700 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7701 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7702 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7703 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7704 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7705                 i = glob(p, 0, NULL, &pglob);
7706                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7707                 if (p != str->text)
7708                         free(p);
7709                 switch (i) {
7710                 case 0:
7711 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7712                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7713                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7714                                 goto nometa2;
7715 #endif
7716                         addglob(&pglob);
7717                         globfree(&pglob);
7718                         INT_ON;
7719                         break;
7720                 case GLOB_NOMATCH:
7721  //nometa2:
7722                         globfree(&pglob);
7723                         INT_ON;
7724  nometa:
7725                         *exparg.lastp = str;
7726                         rmescapes(str->text, 0, NULL);
7727                         exparg.lastp = &str->next;
7728                         break;
7729                 default:        /* GLOB_NOSPACE */
7730                         globfree(&pglob);
7731                         INT_ON;
7732                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7733                 }
7734                 str = str->next;
7735         }
7736 }
7737
7738 #else
7739 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7740
7741 /*
7742  * Do metacharacter (i.e. *, ?, [...]) expansion.
7743  */
7744 typedef struct exp_t {
7745         char *dir;
7746         unsigned dir_max;
7747 } exp_t;
7748 static void
7749 expmeta(exp_t *exp, char *name, unsigned name_len, unsigned expdir_len)
7750 {
7751 #define expdir exp->dir
7752 #define expdir_max exp->dir_max
7753         char *enddir = expdir + expdir_len;
7754         char *p;
7755         const char *cp;
7756         char *start;
7757         char *endname;
7758         int metaflag;
7759         struct stat statb;
7760         DIR *dirp;
7761         struct dirent *dp;
7762         int atend;
7763         int matchdot;
7764         int esc;
7765
7766         metaflag = 0;
7767         start = name;
7768         for (p = name; esc = 0, *p; p += esc + 1) {
7769                 if (*p == '*' || *p == '?')
7770                         metaflag = 1;
7771                 else if (*p == '[') {
7772                         char *q = p + 1;
7773                         if (*q == '!')
7774                                 q++;
7775                         for (;;) {
7776                                 if (*q == '\\')
7777                                         q++;
7778                                 if (*q == '/' || *q == '\0')
7779                                         break;
7780                                 if (*++q == ']') {
7781                                         metaflag = 1;
7782                                         break;
7783                                 }
7784                         }
7785                 } else {
7786                         if (*p == '\\' && p[1])
7787                                 esc++;
7788                         if (p[esc] == '/') {
7789                                 if (metaflag)
7790                                         break;
7791                                 start = p + esc + 1;
7792                         }
7793                 }
7794         }
7795         if (metaflag == 0) {    /* we've reached the end of the file name */
7796                 if (!expdir_len)
7797                         return;
7798                 p = name;
7799                 do {
7800                         if (*p == '\\' && p[1])
7801                                 p++;
7802                         *enddir++ = *p;
7803                 } while (*p++);
7804                 if (lstat(expdir, &statb) == 0)
7805                         addfname(expdir);
7806                 return;
7807         }
7808         endname = p;
7809         if (name < start) {
7810                 p = name;
7811                 do {
7812                         if (*p == '\\' && p[1])
7813                                 p++;
7814                         *enddir++ = *p++;
7815                 } while (p < start);
7816         }
7817         *enddir = '\0';
7818         cp = expdir;
7819         expdir_len = enddir - cp;
7820         if (!expdir_len)
7821                 cp = ".";
7822         dirp = opendir(cp);
7823         if (dirp == NULL)
7824                 return;
7825         if (*endname == 0) {
7826                 atend = 1;
7827         } else {
7828                 atend = 0;
7829                 *endname = '\0';
7830                 endname += esc + 1;
7831         }
7832         name_len -= endname - name;
7833         matchdot = 0;
7834         p = start;
7835         if (*p == '\\')
7836                 p++;
7837         if (*p == '.')
7838                 matchdot++;
7839         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7840                 if (dp->d_name[0] == '.' && !matchdot)
7841                         continue;
7842                 if (pmatch(start, dp->d_name)) {
7843                         if (atend) {
7844                                 strcpy(enddir, dp->d_name);
7845                                 addfname(expdir);
7846                         } else {
7847                                 unsigned offset;
7848                                 unsigned len;
7849
7850                                 p = stpcpy(enddir, dp->d_name);
7851                                 *p = '/';
7852
7853                                 offset = p - expdir + 1;
7854                                 len = offset + name_len + NAME_MAX;
7855                                 if (len > expdir_max) {
7856                                         len += PATH_MAX;
7857                                         expdir = ckrealloc(expdir, len);
7858                                         expdir_max = len;
7859                                 }
7860
7861                                 expmeta(exp, endname, name_len, offset);
7862                                 enddir = expdir + expdir_len;
7863                         }
7864                 }
7865         }
7866         closedir(dirp);
7867         if (!atend)
7868                 endname[-esc - 1] = esc ? '\\' : '/';
7869 #undef expdir
7870 #undef expdir_max
7871 }
7872
7873 static struct strlist *
7874 msort(struct strlist *list, int len)
7875 {
7876         struct strlist *p, *q = NULL;
7877         struct strlist **lpp;
7878         int half;
7879         int n;
7880
7881         if (len <= 1)
7882                 return list;
7883         half = len >> 1;
7884         p = list;
7885         for (n = half; --n >= 0;) {
7886                 q = p;
7887                 p = p->next;
7888         }
7889         q->next = NULL;                 /* terminate first half of list */
7890         q = msort(list, half);          /* sort first half of list */
7891         p = msort(p, len - half);               /* sort second half */
7892         lpp = &list;
7893         for (;;) {
7894 #if ENABLE_LOCALE_SUPPORT
7895                 if (strcoll(p->text, q->text) < 0)
7896 #else
7897                 if (strcmp(p->text, q->text) < 0)
7898 #endif
7899                                                 {
7900                         *lpp = p;
7901                         lpp = &p->next;
7902                         p = *lpp;
7903                         if (p == NULL) {
7904                                 *lpp = q;
7905                                 break;
7906                         }
7907                 } else {
7908                         *lpp = q;
7909                         lpp = &q->next;
7910                         q = *lpp;
7911                         if (q == NULL) {
7912                                 *lpp = p;
7913                                 break;
7914                         }
7915                 }
7916         }
7917         return list;
7918 }
7919
7920 /*
7921  * Sort the results of file name expansion.  It calculates the number of
7922  * strings to sort and then calls msort (short for merge sort) to do the
7923  * work.
7924  */
7925 static struct strlist *
7926 expsort(struct strlist *str)
7927 {
7928         int len;
7929         struct strlist *sp;
7930
7931         len = 0;
7932         for (sp = str; sp; sp = sp->next)
7933                 len++;
7934         return msort(str, len);
7935 }
7936
7937 static void
7938 expandmeta(struct strlist *str /*, int flag*/)
7939 {
7940         /* TODO - EXP_REDIR */
7941
7942         while (str) {
7943                 exp_t exp;
7944                 struct strlist **savelastp;
7945                 struct strlist *sp;
7946                 char *p;
7947                 unsigned len;
7948
7949                 if (fflag)
7950                         goto nometa;
7951                 if (!hasmeta(str->text))
7952                         goto nometa;
7953                 savelastp = exparg.lastp;
7954
7955                 INT_OFF;
7956                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7957                 len = strlen(p);
7958                 exp.dir_max = len + PATH_MAX;
7959                 exp.dir = ckmalloc(exp.dir_max);
7960
7961                 expmeta(&exp, p, len, 0);
7962                 free(exp.dir);
7963                 if (p != str->text)
7964                         free(p);
7965                 INT_ON;
7966                 if (exparg.lastp == savelastp) {
7967                         /*
7968                          * no matches
7969                          */
7970  nometa:
7971                         *exparg.lastp = str;
7972                         rmescapes(str->text, 0, NULL);
7973                         exparg.lastp = &str->next;
7974                 } else {
7975                         *exparg.lastp = NULL;
7976                         *savelastp = sp = expsort(*savelastp);
7977                         while (sp->next != NULL)
7978                                 sp = sp->next;
7979                         exparg.lastp = &sp->next;
7980                 }
7981                 str = str->next;
7982         }
7983 }
7984 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7985
7986 /*
7987  * Perform variable substitution and command substitution on an argument,
7988  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7989  * perform splitting and file name expansion.  When arglist is NULL, perform
7990  * here document expansion.
7991  */
7992 static void
7993 expandarg(union node *arg, struct arglist *arglist, int flag)
7994 {
7995         struct strlist *sp;
7996         char *p;
7997
7998         argbackq = arg->narg.backquote;
7999         STARTSTACKSTR(expdest);
8000         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
8001         argstr(arg->narg.text, flag);
8002         p = _STPUTC('\0', expdest);
8003         expdest = p - 1;
8004         if (arglist == NULL) {
8005                 /* here document expanded */
8006                 goto out;
8007         }
8008         p = grabstackstr(p);
8009         TRACE(("expandarg: p:'%s'\n", p));
8010         exparg.lastp = &exparg.list;
8011         /*
8012          * TODO - EXP_REDIR
8013          */
8014         if (flag & EXP_FULL) {
8015                 ifsbreakup(p, &exparg);
8016                 *exparg.lastp = NULL;
8017                 exparg.lastp = &exparg.list;
8018                 expandmeta(exparg.list /*, flag*/);
8019         } else {
8020                 sp = stzalloc(sizeof(*sp));
8021                 sp->text = p;
8022                 *exparg.lastp = sp;
8023                 exparg.lastp = &sp->next;
8024         }
8025         *exparg.lastp = NULL;
8026         if (exparg.list) {
8027                 *arglist->lastp = exparg.list;
8028                 arglist->lastp = exparg.lastp;
8029         }
8030
8031  out:
8032         ifsfree();
8033 }
8034
8035 /*
8036  * Expand shell variables and backquotes inside a here document.
8037  */
8038 static void
8039 expandhere(union node *arg, int fd)
8040 {
8041         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
8042         full_write(fd, stackblock(), expdest - (char *)stackblock());
8043 }
8044
8045 /*
8046  * Returns true if the pattern matches the string.
8047  */
8048 static int
8049 patmatch(char *pattern, const char *string)
8050 {
8051         char *p = preglob(pattern, 0);
8052         int r = pmatch(p, string);
8053         //bb_error_msg("!fnmatch(pattern:'%s',str:'%s',0):%d", p, string, r);
8054         return r;
8055 }
8056
8057 /*
8058  * See if a pattern matches in a case statement.
8059  */
8060 static int
8061 casematch(union node *pattern, char *val)
8062 {
8063         struct stackmark smark;
8064         int result;
8065
8066         setstackmark(&smark);
8067         argbackq = pattern->narg.backquote;
8068         STARTSTACKSTR(expdest);
8069         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
8070         STACKSTRNUL(expdest);
8071         ifsfree();
8072         result = patmatch(stackblock(), val);
8073         popstackmark(&smark);
8074         return result;
8075 }
8076
8077
8078 /* ============ find_command */
8079
8080 struct builtincmd {
8081         const char *name;
8082         int (*builtin)(int, char **) FAST_FUNC;
8083         /* unsigned flags; */
8084 };
8085 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
8086 /* "regular" builtins always take precedence over commands,
8087  * regardless of PATH=....%builtin... position */
8088 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
8089 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
8090
8091 struct cmdentry {
8092         smallint cmdtype;       /* CMDxxx */
8093         union param {
8094                 int index;
8095                 /* index >= 0 for commands without path (slashes) */
8096                 /* (TODO: what exactly does the value mean? PATH position?) */
8097                 /* index == -1 for commands with slashes */
8098                 /* index == (-2 - applet_no) for NOFORK applets */
8099                 const struct builtincmd *cmd;
8100                 struct funcnode *func;
8101         } u;
8102 };
8103 /* values of cmdtype */
8104 #define CMDUNKNOWN      -1      /* no entry in table for command */
8105 #define CMDNORMAL       0       /* command is an executable program */
8106 #define CMDFUNCTION     1       /* command is a shell function */
8107 #define CMDBUILTIN      2       /* command is a shell builtin */
8108
8109 /* action to find_command() */
8110 #define DO_ERR          0x01    /* prints errors */
8111 #define DO_ABS          0x02    /* checks absolute paths */
8112 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
8113 #define DO_ALTPATH      0x08    /* using alternate path */
8114 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
8115
8116 static void find_command(char *, struct cmdentry *, int, const char *);
8117
8118
8119 /* ============ Hashing commands */
8120
8121 /*
8122  * When commands are first encountered, they are entered in a hash table.
8123  * This ensures that a full path search will not have to be done for them
8124  * on each invocation.
8125  *
8126  * We should investigate converting to a linear search, even though that
8127  * would make the command name "hash" a misnomer.
8128  */
8129
8130 struct tblentry {
8131         struct tblentry *next;  /* next entry in hash chain */
8132         union param param;      /* definition of builtin function */
8133         smallint cmdtype;       /* CMDxxx */
8134         char rehash;            /* if set, cd done since entry created */
8135         char cmdname[1];        /* name of command */
8136 };
8137
8138 static struct tblentry **cmdtable;
8139 #define INIT_G_cmdtable() do { \
8140         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
8141 } while (0)
8142
8143 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
8144
8145
8146 static void
8147 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
8148 {
8149 #if ENABLE_FEATURE_SH_STANDALONE
8150         if (applet_no >= 0) {
8151                 if (APPLET_IS_NOEXEC(applet_no)) {
8152                         clearenv();
8153                         while (*envp)
8154                                 putenv(*envp++);
8155                         popredir(/*drop:*/ 1);
8156                         run_noexec_applet_and_exit(applet_no, cmd, argv);
8157                 }
8158                 /* re-exec ourselves with the new arguments */
8159                 execve(bb_busybox_exec_path, argv, envp);
8160                 /* If they called chroot or otherwise made the binary no longer
8161                  * executable, fall through */
8162         }
8163 #endif
8164
8165  repeat:
8166 #ifdef SYSV
8167         do {
8168                 execve(cmd, argv, envp);
8169         } while (errno == EINTR);
8170 #else
8171         execve(cmd, argv, envp);
8172 #endif
8173
8174         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
8175                 /* Run "cmd" as a shell script:
8176                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
8177                  * "If the execve() function fails with ENOEXEC, the shell
8178                  * shall execute a command equivalent to having a shell invoked
8179                  * with the command name as its first operand,
8180                  * with any remaining arguments passed to the new shell"
8181                  *
8182                  * That is, do not use $SHELL, user's shell, or /bin/sh;
8183                  * just call ourselves.
8184                  *
8185                  * Note that bash reads ~80 chars of the file, and if it sees
8186                  * a zero byte before it sees newline, it doesn't try to
8187                  * interpret it, but fails with "cannot execute binary file"
8188                  * message and exit code 126. For one, this prevents attempts
8189                  * to interpret foreign ELF binaries as shell scripts.
8190                  */
8191                 argv[0] = (char*) cmd;
8192                 cmd = bb_busybox_exec_path;
8193                 /* NB: this is only possible because all callers of shellexec()
8194                  * ensure that the argv[-1] slot exists!
8195                  */
8196                 argv--;
8197                 argv[0] = (char*) "ash";
8198                 goto repeat;
8199         }
8200 }
8201
8202 /*
8203  * Exec a program.  Never returns.  If you change this routine, you may
8204  * have to change the find_command routine as well.
8205  * argv[-1] must exist and be writable! See tryexec() for why.
8206  */
8207 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
8208 static void shellexec(char *prog, char **argv, const char *path, int idx)
8209 {
8210         char *cmdname;
8211         int e;
8212         char **envp;
8213         int exerrno;
8214         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
8215
8216         envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
8217         if (strchr(prog, '/') != NULL
8218 #if ENABLE_FEATURE_SH_STANDALONE
8219          || (applet_no = find_applet_by_name(prog)) >= 0
8220 #endif
8221         ) {
8222                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
8223                 if (applet_no >= 0) {
8224                         /* We tried execing ourself, but it didn't work.
8225                          * Maybe /proc/self/exe doesn't exist?
8226                          * Try $PATH search.
8227                          */
8228                         goto try_PATH;
8229                 }
8230                 e = errno;
8231         } else {
8232  try_PATH:
8233                 e = ENOENT;
8234                 while (padvance(&path, argv[0]) >= 0) {
8235                         cmdname = stackblock();
8236                         if (--idx < 0 && pathopt == NULL) {
8237                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
8238                                 if (errno != ENOENT && errno != ENOTDIR)
8239                                         e = errno;
8240                         }
8241                 }
8242         }
8243
8244         /* Map to POSIX errors */
8245         switch (e) {
8246         default:
8247                 exerrno = 126;
8248                 break;
8249         case ELOOP:
8250         case ENAMETOOLONG:
8251         case ENOENT:
8252         case ENOTDIR:
8253                 exerrno = 127;
8254                 break;
8255         }
8256         exitstatus = exerrno;
8257         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
8258                 prog, e, suppress_int));
8259         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
8260         /* NOTREACHED */
8261 }
8262
8263 static void
8264 printentry(struct tblentry *cmdp)
8265 {
8266         int idx;
8267         const char *path;
8268         char *name;
8269
8270         idx = cmdp->param.index;
8271         path = pathval();
8272         do {
8273                 padvance(&path, cmdp->cmdname);
8274         } while (--idx >= 0);
8275         name = stackblock();
8276         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
8277 }
8278
8279 /*
8280  * Clear out command entries.
8281  */
8282 static void
8283 clearcmdentry(void)
8284 {
8285         struct tblentry **tblp;
8286         struct tblentry **pp;
8287         struct tblentry *cmdp;
8288
8289         INT_OFF;
8290         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
8291                 pp = tblp;
8292                 while ((cmdp = *pp) != NULL) {
8293                         if (cmdp->cmdtype == CMDNORMAL
8294                          || (cmdp->cmdtype == CMDBUILTIN
8295                             && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8296                             && builtinloc > 0
8297                             )
8298                         ) {
8299                                 *pp = cmdp->next;
8300                                 free(cmdp);
8301                         } else {
8302                                 pp = &cmdp->next;
8303                         }
8304                 }
8305         }
8306         INT_ON;
8307 }
8308
8309 /*
8310  * Locate a command in the command hash table.  If "add" is nonzero,
8311  * add the command to the table if it is not already present.  The
8312  * variable "lastcmdentry" is set to point to the address of the link
8313  * pointing to the entry, so that delete_cmd_entry can delete the
8314  * entry.
8315  *
8316  * Interrupts must be off if called with add != 0.
8317  */
8318 static struct tblentry **lastcmdentry;
8319
8320 static struct tblentry *
8321 cmdlookup(const char *name, int add)
8322 {
8323         unsigned int hashval;
8324         const char *p;
8325         struct tblentry *cmdp;
8326         struct tblentry **pp;
8327
8328         p = name;
8329         hashval = (unsigned char)*p << 4;
8330         while (*p)
8331                 hashval += (unsigned char)*p++;
8332         hashval &= 0x7FFF;
8333         pp = &cmdtable[hashval % CMDTABLESIZE];
8334         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8335                 if (strcmp(cmdp->cmdname, name) == 0)
8336                         break;
8337                 pp = &cmdp->next;
8338         }
8339         if (add && cmdp == NULL) {
8340                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
8341                                 + strlen(name)
8342                                 /* + 1 - already done because
8343                                  * tblentry::cmdname is char[1] */);
8344                 /*cmdp->next = NULL; - ckzalloc did it */
8345                 cmdp->cmdtype = CMDUNKNOWN;
8346                 strcpy(cmdp->cmdname, name);
8347         }
8348         lastcmdentry = pp;
8349         return cmdp;
8350 }
8351
8352 /*
8353  * Delete the command entry returned on the last lookup.
8354  */
8355 static void
8356 delete_cmd_entry(void)
8357 {
8358         struct tblentry *cmdp;
8359
8360         INT_OFF;
8361         cmdp = *lastcmdentry;
8362         *lastcmdentry = cmdp->next;
8363         if (cmdp->cmdtype == CMDFUNCTION)
8364                 freefunc(cmdp->param.func);
8365         free(cmdp);
8366         INT_ON;
8367 }
8368
8369 /*
8370  * Add a new command entry, replacing any existing command entry for
8371  * the same name - except special builtins.
8372  */
8373 static void
8374 addcmdentry(char *name, struct cmdentry *entry)
8375 {
8376         struct tblentry *cmdp;
8377
8378         cmdp = cmdlookup(name, 1);
8379         if (cmdp->cmdtype == CMDFUNCTION) {
8380                 freefunc(cmdp->param.func);
8381         }
8382         cmdp->cmdtype = entry->cmdtype;
8383         cmdp->param = entry->u;
8384         cmdp->rehash = 0;
8385 }
8386
8387 static int FAST_FUNC
8388 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8389 {
8390         struct tblentry **pp;
8391         struct tblentry *cmdp;
8392         int c;
8393         struct cmdentry entry;
8394         char *name;
8395
8396         if (nextopt("r") != '\0') {
8397                 clearcmdentry();
8398                 return 0;
8399         }
8400
8401         if (*argptr == NULL) {
8402                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8403                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8404                                 if (cmdp->cmdtype == CMDNORMAL)
8405                                         printentry(cmdp);
8406                         }
8407                 }
8408                 return 0;
8409         }
8410
8411         c = 0;
8412         while ((name = *argptr) != NULL) {
8413                 cmdp = cmdlookup(name, 0);
8414                 if (cmdp != NULL
8415                  && (cmdp->cmdtype == CMDNORMAL
8416                     || (cmdp->cmdtype == CMDBUILTIN
8417                         && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8418                         && builtinloc > 0
8419                         )
8420                     )
8421                 ) {
8422                         delete_cmd_entry();
8423                 }
8424                 find_command(name, &entry, DO_ERR, pathval());
8425                 if (entry.cmdtype == CMDUNKNOWN)
8426                         c = 1;
8427                 argptr++;
8428         }
8429         return c;
8430 }
8431
8432 /*
8433  * Called when a cd is done.  Marks all commands so the next time they
8434  * are executed they will be rehashed.
8435  */
8436 static void
8437 hashcd(void)
8438 {
8439         struct tblentry **pp;
8440         struct tblentry *cmdp;
8441
8442         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8443                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8444                         if (cmdp->cmdtype == CMDNORMAL
8445                          || (cmdp->cmdtype == CMDBUILTIN
8446                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8447                              && builtinloc > 0)
8448                         ) {
8449                                 cmdp->rehash = 1;
8450                         }
8451                 }
8452         }
8453 }
8454
8455 /*
8456  * Fix command hash table when PATH changed.
8457  * Called before PATH is changed.  The argument is the new value of PATH;
8458  * pathval() still returns the old value at this point.
8459  * Called with interrupts off.
8460  */
8461 static void FAST_FUNC
8462 changepath(const char *newval)
8463 {
8464         const char *new;
8465         int idx;
8466         int bltin;
8467
8468         new = newval;
8469         idx = 0;
8470         bltin = -1;
8471         for (;;) {
8472                 if (*new == '%' && prefix(new + 1, "builtin")) {
8473                         bltin = idx;
8474                         break;
8475                 }
8476                 new = strchr(new, ':');
8477                 if (!new)
8478                         break;
8479                 idx++;
8480                 new++;
8481         }
8482         builtinloc = bltin;
8483         clearcmdentry();
8484 }
8485 enum {
8486         TEOF,
8487         TNL,
8488         TREDIR,
8489         TWORD,
8490         TSEMI,
8491         TBACKGND,
8492         TAND,
8493         TOR,
8494         TPIPE,
8495         TLP,
8496         TRP,
8497         TENDCASE,
8498         TENDBQUOTE,
8499         TNOT,
8500         TCASE,
8501         TDO,
8502         TDONE,
8503         TELIF,
8504         TELSE,
8505         TESAC,
8506         TFI,
8507         TFOR,
8508 #if BASH_FUNCTION
8509         TFUNCTION,
8510 #endif
8511         TIF,
8512         TIN,
8513         TTHEN,
8514         TUNTIL,
8515         TWHILE,
8516         TBEGIN,
8517         TEND
8518 };
8519 typedef smallint token_id_t;
8520
8521 /* Nth bit indicates if token marks the end of a list */
8522 enum {
8523         tokendlist = 0
8524         /*  0 */ | (1u << TEOF)
8525         /*  1 */ | (0u << TNL)
8526         /*  2 */ | (0u << TREDIR)
8527         /*  3 */ | (0u << TWORD)
8528         /*  4 */ | (0u << TSEMI)
8529         /*  5 */ | (0u << TBACKGND)
8530         /*  6 */ | (0u << TAND)
8531         /*  7 */ | (0u << TOR)
8532         /*  8 */ | (0u << TPIPE)
8533         /*  9 */ | (0u << TLP)
8534         /* 10 */ | (1u << TRP)
8535         /* 11 */ | (1u << TENDCASE)
8536         /* 12 */ | (1u << TENDBQUOTE)
8537         /* 13 */ | (0u << TNOT)
8538         /* 14 */ | (0u << TCASE)
8539         /* 15 */ | (1u << TDO)
8540         /* 16 */ | (1u << TDONE)
8541         /* 17 */ | (1u << TELIF)
8542         /* 18 */ | (1u << TELSE)
8543         /* 19 */ | (1u << TESAC)
8544         /* 20 */ | (1u << TFI)
8545         /* 21 */ | (0u << TFOR)
8546 #if BASH_FUNCTION
8547         /* 22 */ | (0u << TFUNCTION)
8548 #endif
8549         /* 23 */ | (0u << TIF)
8550         /* 24 */ | (0u << TIN)
8551         /* 25 */ | (1u << TTHEN)
8552         /* 26 */ | (0u << TUNTIL)
8553         /* 27 */ | (0u << TWHILE)
8554         /* 28 */ | (0u << TBEGIN)
8555         /* 29 */ | (1u << TEND)
8556         , /* thus far 29 bits used */
8557 };
8558
8559 static const char *const tokname_array[] = {
8560         "end of file",
8561         "newline",
8562         "redirection",
8563         "word",
8564         ";",
8565         "&",
8566         "&&",
8567         "||",
8568         "|",
8569         "(",
8570         ")",
8571         ";;",
8572         "`",
8573 #define KWDOFFSET 13
8574         /* the following are keywords */
8575         "!",
8576         "case",
8577         "do",
8578         "done",
8579         "elif",
8580         "else",
8581         "esac",
8582         "fi",
8583         "for",
8584 #if BASH_FUNCTION
8585         "function",
8586 #endif
8587         "if",
8588         "in",
8589         "then",
8590         "until",
8591         "while",
8592         "{",
8593         "}",
8594 };
8595
8596 /* Wrapper around strcmp for qsort/bsearch/... */
8597 static int
8598 pstrcmp(const void *a, const void *b)
8599 {
8600         return strcmp((char*)a, *(char**)b);
8601 }
8602
8603 static const char *const *
8604 findkwd(const char *s)
8605 {
8606         return bsearch(s, tokname_array + KWDOFFSET,
8607                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8608                         sizeof(tokname_array[0]), pstrcmp);
8609 }
8610
8611 /*
8612  * Locate and print what a word is...
8613  */
8614 static int
8615 describe_command(char *command, const char *path, int describe_command_verbose)
8616 {
8617         struct cmdentry entry;
8618 #if ENABLE_ASH_ALIAS
8619         const struct alias *ap;
8620 #endif
8621
8622         path = path ? path : pathval();
8623
8624         if (describe_command_verbose) {
8625                 out1str(command);
8626         }
8627
8628         /* First look at the keywords */
8629         if (findkwd(command)) {
8630                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8631                 goto out;
8632         }
8633
8634 #if ENABLE_ASH_ALIAS
8635         /* Then look at the aliases */
8636         ap = lookupalias(command, 0);
8637         if (ap != NULL) {
8638                 if (!describe_command_verbose) {
8639                         out1str("alias ");
8640                         printalias(ap);
8641                         return 0;
8642                 }
8643                 out1fmt(" is an alias for %s", ap->val);
8644                 goto out;
8645         }
8646 #endif
8647         /* Brute force */
8648         find_command(command, &entry, DO_ABS, path);
8649
8650         switch (entry.cmdtype) {
8651         case CMDNORMAL: {
8652                 int j = entry.u.index;
8653                 char *p;
8654                 if (j < 0) {
8655                         p = command;
8656                 } else {
8657                         do {
8658                                 padvance(&path, command);
8659                         } while (--j >= 0);
8660                         p = stackblock();
8661                 }
8662                 if (describe_command_verbose) {
8663                         out1fmt(" is %s", p);
8664                 } else {
8665                         out1str(p);
8666                 }
8667                 break;
8668         }
8669
8670         case CMDFUNCTION:
8671                 if (describe_command_verbose) {
8672                         /*out1str(" is a shell function");*/
8673                         out1str(" is a function"); /* bash says this */
8674                 } else {
8675                         out1str(command);
8676                 }
8677                 break;
8678
8679         case CMDBUILTIN:
8680                 if (describe_command_verbose) {
8681                         out1fmt(" is a %sshell builtin",
8682                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8683                                         "special " : nullstr
8684                         );
8685                 } else {
8686                         out1str(command);
8687                 }
8688                 break;
8689
8690         default:
8691                 if (describe_command_verbose) {
8692                         out1str(": not found\n");
8693                 }
8694                 return 127;
8695         }
8696  out:
8697         out1str("\n");
8698         return 0;
8699 }
8700
8701 static int FAST_FUNC
8702 typecmd(int argc UNUSED_PARAM, char **argv)
8703 {
8704         int i = 1;
8705         int err = 0;
8706         int verbose = 1;
8707
8708         /* type -p ... ? (we don't bother checking for 'p') */
8709         if (argv[1] && argv[1][0] == '-') {
8710                 i++;
8711                 verbose = 0;
8712         }
8713         while (argv[i]) {
8714                 err |= describe_command(argv[i++], NULL, verbose);
8715         }
8716         return err;
8717 }
8718
8719 #if ENABLE_ASH_CMDCMD
8720 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8721 static char **
8722 parse_command_args(char **argv, const char **path)
8723 {
8724         char *cp, c;
8725
8726         for (;;) {
8727                 cp = *++argv;
8728                 if (!cp)
8729                         return NULL;
8730                 if (*cp++ != '-')
8731                         break;
8732                 c = *cp++;
8733                 if (!c)
8734                         break;
8735                 if (c == '-' && !*cp) {
8736                         if (!*++argv)
8737                                 return NULL;
8738                         break;
8739                 }
8740                 do {
8741                         switch (c) {
8742                         case 'p':
8743                                 *path = bb_default_path;
8744                                 break;
8745                         default:
8746                                 /* run 'typecmd' for other options */
8747                                 return NULL;
8748                         }
8749                         c = *cp++;
8750                 } while (c);
8751         }
8752         return argv;
8753 }
8754
8755 static int FAST_FUNC
8756 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8757 {
8758         char *cmd;
8759         int c;
8760         enum {
8761                 VERIFY_BRIEF = 1,
8762                 VERIFY_VERBOSE = 2,
8763         } verify = 0;
8764         const char *path = NULL;
8765
8766         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8767          * never reaches this function.
8768          */
8769
8770         while ((c = nextopt("pvV")) != '\0')
8771                 if (c == 'V')
8772                         verify |= VERIFY_VERBOSE;
8773                 else if (c == 'v')
8774                         /*verify |= VERIFY_BRIEF*/;
8775 #if DEBUG
8776                 else if (c != 'p')
8777                         abort();
8778 #endif
8779                 else
8780                         path = bb_default_path;
8781
8782         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8783         cmd = *argptr;
8784         if (/*verify && */ cmd)
8785                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8786
8787         return 0;
8788 }
8789 #endif
8790
8791
8792 /*static int funcblocksize;     // size of structures in function */
8793 /*static int funcstringsize;    // size of strings in node */
8794 static void *funcblock;         /* block to allocate function from */
8795 static char *funcstring_end;    /* end of block to allocate strings from */
8796
8797 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8798         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8799         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8800         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8801         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8802         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8803         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8804         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8805         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8806         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8807         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8808         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8809         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8810         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8811         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8812         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8813         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8814         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8815 #if BASH_REDIR_OUTPUT
8816         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8817 #endif
8818         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8819         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8820         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8821         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8822         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8823         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8824         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8825         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8826         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8827 };
8828
8829 static int calcsize(int funcblocksize, union node *n);
8830
8831 static int
8832 sizenodelist(int funcblocksize, struct nodelist *lp)
8833 {
8834         while (lp) {
8835                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8836                 funcblocksize = calcsize(funcblocksize, lp->n);
8837                 lp = lp->next;
8838         }
8839         return funcblocksize;
8840 }
8841
8842 static int
8843 calcsize(int funcblocksize, union node *n)
8844 {
8845         if (n == NULL)
8846                 return funcblocksize;
8847         funcblocksize += nodesize[n->type];
8848         switch (n->type) {
8849         case NCMD:
8850                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8851                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8852                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8853                 break;
8854         case NPIPE:
8855                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8856                 break;
8857         case NREDIR:
8858         case NBACKGND:
8859         case NSUBSHELL:
8860                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8861                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8862                 break;
8863         case NAND:
8864         case NOR:
8865         case NSEMI:
8866         case NWHILE:
8867         case NUNTIL:
8868                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8869                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8870                 break;
8871         case NIF:
8872                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8873                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8874                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8875                 break;
8876         case NFOR:
8877                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8878                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8879                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8880                 break;
8881         case NCASE:
8882                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8883                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8884                 break;
8885         case NCLIST:
8886                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8887                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8888                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8889                 break;
8890         case NDEFUN:
8891                 funcblocksize = calcsize(funcblocksize, n->ndefun.body);
8892                 funcblocksize += SHELL_ALIGN(strlen(n->ndefun.text) + 1);
8893                 break;
8894         case NARG:
8895                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8896                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8897                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8898                 break;
8899         case NTO:
8900 #if BASH_REDIR_OUTPUT
8901         case NTO2:
8902 #endif
8903         case NCLOBBER:
8904         case NFROM:
8905         case NFROMTO:
8906         case NAPPEND:
8907                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8908                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8909                 break;
8910         case NTOFD:
8911         case NFROMFD:
8912                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8913                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8914         break;
8915         case NHERE:
8916         case NXHERE:
8917                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8918                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8919                 break;
8920         case NNOT:
8921                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8922                 break;
8923         };
8924         return funcblocksize;
8925 }
8926
8927 static char *
8928 nodeckstrdup(char *s)
8929 {
8930         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8931         return strcpy(funcstring_end, s);
8932 }
8933
8934 static union node *copynode(union node *);
8935
8936 static struct nodelist *
8937 copynodelist(struct nodelist *lp)
8938 {
8939         struct nodelist *start;
8940         struct nodelist **lpp;
8941
8942         lpp = &start;
8943         while (lp) {
8944                 *lpp = funcblock;
8945                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8946                 (*lpp)->n = copynode(lp->n);
8947                 lp = lp->next;
8948                 lpp = &(*lpp)->next;
8949         }
8950         *lpp = NULL;
8951         return start;
8952 }
8953
8954 static union node *
8955 copynode(union node *n)
8956 {
8957         union node *new;
8958
8959         if (n == NULL)
8960                 return NULL;
8961         new = funcblock;
8962         funcblock = (char *) funcblock + nodesize[n->type];
8963
8964         switch (n->type) {
8965         case NCMD:
8966                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8967                 new->ncmd.args = copynode(n->ncmd.args);
8968                 new->ncmd.assign = copynode(n->ncmd.assign);
8969                 new->ncmd.linno = n->ncmd.linno;
8970                 break;
8971         case NPIPE:
8972                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8973                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8974                 break;
8975         case NREDIR:
8976         case NBACKGND:
8977         case NSUBSHELL:
8978                 new->nredir.redirect = copynode(n->nredir.redirect);
8979                 new->nredir.n = copynode(n->nredir.n);
8980                 new->nredir.linno = n->nredir.linno;
8981                 break;
8982         case NAND:
8983         case NOR:
8984         case NSEMI:
8985         case NWHILE:
8986         case NUNTIL:
8987                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8988                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8989                 break;
8990         case NIF:
8991                 new->nif.elsepart = copynode(n->nif.elsepart);
8992                 new->nif.ifpart = copynode(n->nif.ifpart);
8993                 new->nif.test = copynode(n->nif.test);
8994                 break;
8995         case NFOR:
8996                 new->nfor.var = nodeckstrdup(n->nfor.var);
8997                 new->nfor.body = copynode(n->nfor.body);
8998                 new->nfor.args = copynode(n->nfor.args);
8999                 new->nfor.linno = n->nfor.linno;
9000                 break;
9001         case NCASE:
9002                 new->ncase.cases = copynode(n->ncase.cases);
9003                 new->ncase.expr = copynode(n->ncase.expr);
9004                 new->ncase.linno = n->ncase.linno;
9005                 break;
9006         case NCLIST:
9007                 new->nclist.body = copynode(n->nclist.body);
9008                 new->nclist.pattern = copynode(n->nclist.pattern);
9009                 new->nclist.next = copynode(n->nclist.next);
9010                 break;
9011         case NDEFUN:
9012                 new->ndefun.body = copynode(n->ndefun.body);
9013                 new->ndefun.text = nodeckstrdup(n->ndefun.text);
9014                 new->ndefun.linno = n->ndefun.linno;
9015                 break;
9016         case NARG:
9017                 new->narg.backquote = copynodelist(n->narg.backquote);
9018                 new->narg.text = nodeckstrdup(n->narg.text);
9019                 new->narg.next = copynode(n->narg.next);
9020                 break;
9021         case NTO:
9022 #if BASH_REDIR_OUTPUT
9023         case NTO2:
9024 #endif
9025         case NCLOBBER:
9026         case NFROM:
9027         case NFROMTO:
9028         case NAPPEND:
9029                 new->nfile.fname = copynode(n->nfile.fname);
9030                 new->nfile.fd = n->nfile.fd;
9031                 new->nfile.next = copynode(n->nfile.next);
9032                 break;
9033         case NTOFD:
9034         case NFROMFD:
9035                 new->ndup.vname = copynode(n->ndup.vname);
9036                 new->ndup.dupfd = n->ndup.dupfd;
9037                 new->ndup.fd = n->ndup.fd;
9038                 new->ndup.next = copynode(n->ndup.next);
9039                 break;
9040         case NHERE:
9041         case NXHERE:
9042                 new->nhere.doc = copynode(n->nhere.doc);
9043                 new->nhere.fd = n->nhere.fd;
9044                 new->nhere.next = copynode(n->nhere.next);
9045                 break;
9046         case NNOT:
9047                 new->nnot.com = copynode(n->nnot.com);
9048                 break;
9049         };
9050         new->type = n->type;
9051         return new;
9052 }
9053
9054 /*
9055  * Make a copy of a parse tree.
9056  */
9057 static struct funcnode *
9058 copyfunc(union node *n)
9059 {
9060         struct funcnode *f;
9061         size_t blocksize;
9062
9063         /*funcstringsize = 0;*/
9064         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
9065         f = ckzalloc(blocksize /* + funcstringsize */);
9066         funcblock = (char *) f + offsetof(struct funcnode, n);
9067         funcstring_end = (char *) f + blocksize;
9068         copynode(n);
9069         /* f->count = 0; - ckzalloc did it */
9070         return f;
9071 }
9072
9073 /*
9074  * Define a shell function.
9075  */
9076 static void
9077 defun(union node *func)
9078 {
9079         struct cmdentry entry;
9080
9081         INT_OFF;
9082         entry.cmdtype = CMDFUNCTION;
9083         entry.u.func = copyfunc(func);
9084         addcmdentry(func->ndefun.text, &entry);
9085         INT_ON;
9086 }
9087
9088 /* Reasons for skipping commands (see comment on breakcmd routine) */
9089 #define SKIPBREAK      (1 << 0)
9090 #define SKIPCONT       (1 << 1)
9091 #define SKIPFUNC       (1 << 2)
9092 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
9093 static int skipcount;           /* number of levels to skip */
9094 static int loopnest;            /* current loop nesting level */
9095 static int funcline;            /* starting line number of current function, or 0 if not in a function */
9096
9097 /* Forward decl way out to parsing code - dotrap needs it */
9098 static int evalstring(char *s, int flags);
9099
9100 /* Called to execute a trap.
9101  * Single callsite - at the end of evaltree().
9102  * If we return non-zero, evaltree raises EXEXIT exception.
9103  *
9104  * Perhaps we should avoid entering new trap handlers
9105  * while we are executing a trap handler. [is it a TODO?]
9106  */
9107 static void
9108 dotrap(void)
9109 {
9110         uint8_t *g;
9111         int sig;
9112         int status, last_status;
9113
9114         if (!pending_sig)
9115                 return;
9116
9117         status = savestatus;
9118         last_status = status;
9119         if (status < 0) {
9120                 status = exitstatus;
9121                 savestatus = status;
9122         }
9123         pending_sig = 0;
9124         barrier();
9125
9126         TRACE(("dotrap entered\n"));
9127         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
9128                 char *p;
9129
9130                 if (!*g)
9131                         continue;
9132
9133                 if (evalskip) {
9134                         pending_sig = sig;
9135                         break;
9136                 }
9137
9138                 p = trap[sig];
9139                 /* non-trapped SIGINT is handled separately by raise_interrupt,
9140                  * don't upset it by resetting gotsig[SIGINT-1] */
9141                 if (sig == SIGINT && !p)
9142                         continue;
9143
9144                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
9145                 *g = 0;
9146                 if (!p)
9147                         continue;
9148                 evalstring(p, 0);
9149                 exitstatus = status;
9150         }
9151
9152         savestatus = last_status;
9153         TRACE(("dotrap returns\n"));
9154 }
9155
9156 /* forward declarations - evaluation is fairly recursive business... */
9157 static int evalloop(union node *, int);
9158 static int evalfor(union node *, int);
9159 static int evalcase(union node *, int);
9160 static int evalsubshell(union node *, int);
9161 static void expredir(union node *);
9162 static int evalpipe(union node *, int);
9163 static int evalcommand(union node *, int);
9164 static int evalbltin(const struct builtincmd *, int, char **, int);
9165 static void prehash(union node *);
9166
9167 /*
9168  * Evaluate a parse tree.  The value is left in the global variable
9169  * exitstatus.
9170  */
9171 static int
9172 evaltree(union node *n, int flags)
9173 {
9174         int checkexit = 0;
9175         int (*evalfn)(union node *, int);
9176         struct stackmark smark;
9177         int status = 0;
9178
9179         setstackmark(&smark);
9180
9181         if (n == NULL) {
9182                 TRACE(("evaltree(NULL) called\n"));
9183                 goto out;
9184         }
9185         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
9186
9187         dotrap();
9188
9189         switch (n->type) {
9190         default:
9191 #if DEBUG
9192                 out1fmt("Node type = %d\n", n->type);
9193                 fflush_all();
9194                 break;
9195 #endif
9196         case NNOT:
9197                 status = !evaltree(n->nnot.com, EV_TESTED);
9198                 goto setstatus;
9199         case NREDIR:
9200                 errlinno = lineno = n->nredir.linno;
9201                 if (funcline)
9202                         lineno -= funcline - 1;
9203                 expredir(n->nredir.redirect);
9204                 pushredir(n->nredir.redirect);
9205                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
9206                 if (!status) {
9207                         status = evaltree(n->nredir.n, flags & EV_TESTED);
9208                 }
9209                 if (n->nredir.redirect)
9210                         popredir(/*drop:*/ 0);
9211                 goto setstatus;
9212         case NCMD:
9213                 evalfn = evalcommand;
9214  checkexit:
9215                 if (eflag && !(flags & EV_TESTED))
9216                         checkexit = ~0;
9217                 goto calleval;
9218         case NFOR:
9219                 evalfn = evalfor;
9220                 goto calleval;
9221         case NWHILE:
9222         case NUNTIL:
9223                 evalfn = evalloop;
9224                 goto calleval;
9225         case NSUBSHELL:
9226         case NBACKGND:
9227                 evalfn = evalsubshell;
9228                 goto checkexit;
9229         case NPIPE:
9230                 evalfn = evalpipe;
9231                 goto checkexit;
9232         case NCASE:
9233                 evalfn = evalcase;
9234                 goto calleval;
9235         case NAND:
9236         case NOR:
9237         case NSEMI: {
9238
9239 #if NAND + 1 != NOR
9240 #error NAND + 1 != NOR
9241 #endif
9242 #if NOR + 1 != NSEMI
9243 #error NOR + 1 != NSEMI
9244 #endif
9245                 unsigned is_or = n->type - NAND;
9246                 status = evaltree(
9247                         n->nbinary.ch1,
9248                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
9249                 );
9250                 if ((!status) == is_or || evalskip)
9251                         break;
9252                 n = n->nbinary.ch2;
9253  evaln:
9254                 evalfn = evaltree;
9255  calleval:
9256                 status = evalfn(n, flags);
9257                 goto setstatus;
9258         }
9259         case NIF:
9260                 status = evaltree(n->nif.test, EV_TESTED);
9261                 if (evalskip)
9262                         break;
9263                 if (!status) {
9264                         n = n->nif.ifpart;
9265                         goto evaln;
9266                 }
9267                 if (n->nif.elsepart) {
9268                         n = n->nif.elsepart;
9269                         goto evaln;
9270                 }
9271                 status = 0;
9272                 goto setstatus;
9273         case NDEFUN:
9274                 defun(n);
9275                 /* Not necessary. To test it:
9276                  * "false; f() { qwerty; }; echo $?" should print 0.
9277                  */
9278                 /* status = 0; */
9279  setstatus:
9280                 exitstatus = status;
9281                 break;
9282         }
9283  out:
9284         /* Order of checks below is important:
9285          * signal handlers trigger before exit caused by "set -e".
9286          */
9287         dotrap();
9288
9289         if (checkexit & status)
9290                 raise_exception(EXEXIT);
9291         if (flags & EV_EXIT)
9292                 raise_exception(EXEXIT);
9293
9294         popstackmark(&smark);
9295         TRACE(("leaving evaltree (no interrupts)\n"));
9296         return exitstatus;
9297 }
9298
9299 static int
9300 skiploop(void)
9301 {
9302         int skip = evalskip;
9303
9304         switch (skip) {
9305         case 0:
9306                 break;
9307         case SKIPBREAK:
9308         case SKIPCONT:
9309                 if (--skipcount <= 0) {
9310                         evalskip = 0;
9311                         break;
9312                 }
9313                 skip = SKIPBREAK;
9314                 break;
9315         }
9316         return skip;
9317 }
9318
9319 static int
9320 evalloop(union node *n, int flags)
9321 {
9322         int skip;
9323         int status;
9324
9325         loopnest++;
9326         status = 0;
9327         flags &= EV_TESTED;
9328         do {
9329                 int i;
9330
9331                 i = evaltree(n->nbinary.ch1, EV_TESTED);
9332                 skip = skiploop();
9333                 if (skip == SKIPFUNC)
9334                         status = i;
9335                 if (skip)
9336                         continue;
9337                 if (n->type != NWHILE)
9338                         i = !i;
9339                 if (i != 0)
9340                         break;
9341                 status = evaltree(n->nbinary.ch2, flags);
9342                 skip = skiploop();
9343         } while (!(skip & ~SKIPCONT));
9344         loopnest--;
9345
9346         return status;
9347 }
9348
9349 static int
9350 evalfor(union node *n, int flags)
9351 {
9352         struct arglist arglist;
9353         union node *argp;
9354         struct strlist *sp;
9355         int status = 0;
9356
9357         errlinno = lineno = n->ncase.linno;
9358         if (funcline)
9359                 lineno -= funcline - 1;
9360
9361         arglist.list = NULL;
9362         arglist.lastp = &arglist.list;
9363         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
9364                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9365         }
9366         *arglist.lastp = NULL;
9367
9368         loopnest++;
9369         flags &= EV_TESTED;
9370         for (sp = arglist.list; sp; sp = sp->next) {
9371                 setvar0(n->nfor.var, sp->text);
9372                 status = evaltree(n->nfor.body, flags);
9373                 if (skiploop() & ~SKIPCONT)
9374                         break;
9375         }
9376         loopnest--;
9377
9378         return status;
9379 }
9380
9381 static int
9382 evalcase(union node *n, int flags)
9383 {
9384         union node *cp;
9385         union node *patp;
9386         struct arglist arglist;
9387         int status = 0;
9388
9389         errlinno = lineno = n->ncase.linno;
9390         if (funcline)
9391                 lineno -= funcline - 1;
9392
9393         arglist.list = NULL;
9394         arglist.lastp = &arglist.list;
9395         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9396         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9397                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9398                         if (casematch(patp, arglist.list->text)) {
9399                                 /* Ensure body is non-empty as otherwise
9400                                  * EV_EXIT may prevent us from setting the
9401                                  * exit status.
9402                                  */
9403                                 if (evalskip == 0 && cp->nclist.body) {
9404                                         status = evaltree(cp->nclist.body, flags);
9405                                 }
9406                                 goto out;
9407                         }
9408                 }
9409         }
9410  out:
9411         return status;
9412 }
9413
9414 /*
9415  * Kick off a subshell to evaluate a tree.
9416  */
9417 static int
9418 evalsubshell(union node *n, int flags)
9419 {
9420         struct job *jp;
9421         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9422         int status;
9423
9424         errlinno = lineno = n->nredir.linno;
9425         if (funcline)
9426                 lineno -= funcline - 1;
9427
9428         expredir(n->nredir.redirect);
9429         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9430                 goto nofork;
9431         INT_OFF;
9432         if (backgnd == FORK_FG)
9433                 get_tty_state();
9434         jp = makejob(/*n,*/ 1);
9435         if (forkshell(jp, n, backgnd) == 0) {
9436                 /* child */
9437                 INT_ON;
9438                 flags |= EV_EXIT;
9439                 if (backgnd)
9440                         flags &= ~EV_TESTED;
9441  nofork:
9442                 redirect(n->nredir.redirect, 0);
9443                 evaltreenr(n->nredir.n, flags);
9444                 /* never returns */
9445         }
9446         /* parent */
9447         status = 0;
9448         if (backgnd == FORK_FG)
9449                 status = waitforjob(jp);
9450         INT_ON;
9451         return status;
9452 }
9453
9454 /*
9455  * Compute the names of the files in a redirection list.
9456  */
9457 static void fixredir(union node *, const char *, int);
9458 static void
9459 expredir(union node *n)
9460 {
9461         union node *redir;
9462
9463         for (redir = n; redir; redir = redir->nfile.next) {
9464                 struct arglist fn;
9465
9466                 fn.list = NULL;
9467                 fn.lastp = &fn.list;
9468                 switch (redir->type) {
9469                 case NFROMTO:
9470                 case NFROM:
9471                 case NTO:
9472 #if BASH_REDIR_OUTPUT
9473                 case NTO2:
9474 #endif
9475                 case NCLOBBER:
9476                 case NAPPEND:
9477                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9478                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9479 #if BASH_REDIR_OUTPUT
9480  store_expfname:
9481 #endif
9482 #if 0
9483 // By the design of stack allocator, the loop of this kind:
9484 //      while true; do while true; do break; done </dev/null; done
9485 // will look like a memory leak: ash plans to free expfname's
9486 // of "/dev/null" as soon as it finishes running the loop
9487 // (in this case, never).
9488 // This "fix" is wrong:
9489                         if (redir->nfile.expfname)
9490                                 stunalloc(redir->nfile.expfname);
9491 // It results in corrupted state of stacked allocations.
9492 #endif
9493                         redir->nfile.expfname = fn.list->text;
9494                         break;
9495                 case NFROMFD:
9496                 case NTOFD: /* >& */
9497                         if (redir->ndup.vname) {
9498                                 expandarg(redir->ndup.vname, &fn, EXP_TILDE | EXP_REDIR);
9499                                 if (fn.list == NULL)
9500                                         ash_msg_and_raise_error("redir error");
9501 #if BASH_REDIR_OUTPUT
9502                                 if (!isdigit_str9(fn.list->text)) {
9503                                         /* >&file, not >&fd */
9504                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9505                                                 ash_msg_and_raise_error("redir error");
9506                                         redir->type = NTO2;
9507                                         goto store_expfname;
9508                                 }
9509 #endif
9510                                 fixredir(redir, fn.list->text, 1);
9511                         }
9512                         break;
9513                 }
9514         }
9515 }
9516
9517 /*
9518  * Evaluate a pipeline.  All the processes in the pipeline are children
9519  * of the process creating the pipeline.  (This differs from some versions
9520  * of the shell, which make the last process in a pipeline the parent
9521  * of all the rest.)
9522  */
9523 static int
9524 evalpipe(union node *n, int flags)
9525 {
9526         struct job *jp;
9527         struct nodelist *lp;
9528         int pipelen;
9529         int prevfd;
9530         int pip[2];
9531         int status = 0;
9532
9533         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9534         pipelen = 0;
9535         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9536                 pipelen++;
9537         flags |= EV_EXIT;
9538         INT_OFF;
9539         if (n->npipe.pipe_backgnd == 0)
9540                 get_tty_state();
9541         jp = makejob(/*n,*/ pipelen);
9542         prevfd = -1;
9543         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9544                 prehash(lp->n);
9545                 pip[1] = -1;
9546                 if (lp->next) {
9547                         if (pipe(pip) < 0) {
9548                                 close(prevfd);
9549                                 ash_msg_and_raise_perror("can't create pipe");
9550                         }
9551                 }
9552                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9553                         /* child */
9554                         INT_ON;
9555                         if (pip[1] >= 0) {
9556                                 close(pip[0]);
9557                         }
9558                         if (prevfd > 0) {
9559                                 dup2(prevfd, 0);
9560                                 close(prevfd);
9561                         }
9562                         if (pip[1] > 1) {
9563                                 dup2(pip[1], 1);
9564                                 close(pip[1]);
9565                         }
9566                         evaltreenr(lp->n, flags);
9567                         /* never returns */
9568                 }
9569                 /* parent */
9570                 if (prevfd >= 0)
9571                         close(prevfd);
9572                 prevfd = pip[0];
9573                 /* Don't want to trigger debugging */
9574                 if (pip[1] != -1)
9575                         close(pip[1]);
9576         }
9577         if (n->npipe.pipe_backgnd == 0) {
9578                 status = waitforjob(jp);
9579                 TRACE(("evalpipe:  job done exit status %d\n", status));
9580         }
9581         INT_ON;
9582
9583         return status;
9584 }
9585
9586 /* setinteractive needs this forward reference */
9587 #if EDITING_HAS_get_exe_name
9588 static const char *get_builtin_name(int i) FAST_FUNC;
9589 #endif
9590
9591 /*
9592  * Controls whether the shell is interactive or not.
9593  */
9594 static void
9595 setinteractive(int on)
9596 {
9597         static smallint is_interactive;
9598
9599         if (++on == is_interactive)
9600                 return;
9601         is_interactive = on;
9602         setsignal(SIGINT);
9603         setsignal(SIGQUIT);
9604         setsignal(SIGTERM);
9605         if (is_interactive > 1) {
9606 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9607                 /* Looks like they want an interactive shell */
9608                 static smallint did_banner;
9609
9610                 if (!did_banner) {
9611                         /* note: ash and hush share this string */
9612                         out1fmt("\n\n%s %s\n"
9613                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9614                                 "\n",
9615                                 bb_banner,
9616                                 "built-in shell (ash)"
9617                         );
9618                         did_banner = 1;
9619                 }
9620 #endif
9621 #if ENABLE_FEATURE_EDITING
9622                 if (!line_input_state) {
9623                         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
9624 # if EDITING_HAS_get_exe_name
9625                         line_input_state->get_exe_name = get_builtin_name;
9626 # endif
9627                 }
9628 #endif
9629         }
9630 }
9631
9632 static void
9633 optschanged(void)
9634 {
9635 #if DEBUG
9636         opentrace();
9637 #endif
9638         setinteractive(iflag);
9639         setjobctl(mflag);
9640 #if ENABLE_FEATURE_EDITING_VI
9641         if (line_input_state) {
9642                 if (viflag)
9643                         line_input_state->flags |= VI_MODE;
9644                 else
9645                         line_input_state->flags &= ~VI_MODE;
9646         }
9647 #else
9648         viflag = 0; /* forcibly keep the option off */
9649 #endif
9650 }
9651
9652 struct localvar_list {
9653         struct localvar_list *next;
9654         struct localvar *lv;
9655 };
9656
9657 static struct localvar_list *localvar_stack;
9658
9659 /*
9660  * Called after a function returns.
9661  * Interrupts must be off.
9662  */
9663 static void
9664 poplocalvars(int keep)
9665 {
9666         struct localvar_list *ll;
9667         struct localvar *lvp, *next;
9668         struct var *vp;
9669
9670         INT_OFF;
9671         ll = localvar_stack;
9672         localvar_stack = ll->next;
9673
9674         next = ll->lv;
9675         free(ll);
9676
9677         while ((lvp = next) != NULL) {
9678                 next = lvp->next;
9679                 vp = lvp->vp;
9680                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9681                 if (keep) {
9682                         int bits = VSTRFIXED;
9683
9684                         if (lvp->flags != VUNSET) {
9685                                 if (vp->var_text == lvp->text)
9686                                         bits |= VTEXTFIXED;
9687                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9688                                         free((char*)lvp->text);
9689                         }
9690
9691                         vp->flags &= ~bits;
9692                         vp->flags |= (lvp->flags & bits);
9693
9694                         if ((vp->flags &
9695                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9696                                 unsetvar(vp->var_text);
9697                 } else if (vp == NULL) {        /* $- saved */
9698                         memcpy(optlist, lvp->text, sizeof(optlist));
9699                         free((char*)lvp->text);
9700                         optschanged();
9701                 } else if (lvp->flags == VUNSET) {
9702                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9703                         unsetvar(vp->var_text);
9704                 } else {
9705                         if (vp->var_func)
9706                                 vp->var_func(var_end(lvp->text));
9707                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9708                                 free((char*)vp->var_text);
9709                         vp->flags = lvp->flags;
9710                         vp->var_text = lvp->text;
9711                 }
9712                 free(lvp);
9713         }
9714         INT_ON;
9715 }
9716
9717 /*
9718  * Create a new localvar environment.
9719  */
9720 static struct localvar_list *
9721 pushlocalvars(void)
9722 {
9723         struct localvar_list *ll;
9724
9725         INT_OFF;
9726         ll = ckzalloc(sizeof(*ll));
9727         /*ll->lv = NULL; - zalloc did it */
9728         ll->next = localvar_stack;
9729         localvar_stack = ll;
9730         INT_ON;
9731
9732         return ll->next;
9733 }
9734
9735 static void
9736 unwindlocalvars(struct localvar_list *stop)
9737 {
9738         while (localvar_stack != stop)
9739                 poplocalvars(0);
9740 }
9741
9742 static int
9743 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9744 {
9745         volatile struct shparam saveparam;
9746         struct jmploc *volatile savehandler;
9747         struct jmploc jmploc;
9748         int e;
9749         int savefuncline;
9750
9751         saveparam = shellparam;
9752         savefuncline = funcline;
9753         savehandler = exception_handler;
9754         e = setjmp(jmploc.loc);
9755         if (e) {
9756                 goto funcdone;
9757         }
9758         INT_OFF;
9759         exception_handler = &jmploc;
9760         shellparam.malloced = 0;
9761         func->count++;
9762         funcline = func->n.ndefun.linno;
9763         INT_ON;
9764         shellparam.nparam = argc - 1;
9765         shellparam.p = argv + 1;
9766 #if ENABLE_ASH_GETOPTS
9767         shellparam.optind = 1;
9768         shellparam.optoff = -1;
9769 #endif
9770         evaltree(func->n.ndefun.body, flags & EV_TESTED);
9771  funcdone:
9772         INT_OFF;
9773         funcline = savefuncline;
9774         freefunc(func);
9775         freeparam(&shellparam);
9776         shellparam = saveparam;
9777         exception_handler = savehandler;
9778         INT_ON;
9779         evalskip &= ~SKIPFUNC;
9780         return e;
9781 }
9782
9783 /*
9784  * Make a variable a local variable.  When a variable is made local, it's
9785  * value and flags are saved in a localvar structure.  The saved values
9786  * will be restored when the shell function returns.  We handle the name
9787  * "-" as a special case: it makes changes to "set +-options" local
9788  * (options will be restored on return from the function).
9789  */
9790 static void
9791 mklocal(char *name)
9792 {
9793         struct localvar *lvp;
9794         struct var **vpp;
9795         struct var *vp;
9796         char *eq = strchr(name, '=');
9797
9798         INT_OFF;
9799         /* Cater for duplicate "local". Examples:
9800          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9801          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9802          */
9803         lvp = localvar_stack->lv;
9804         while (lvp) {
9805                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9806                         if (eq)
9807                                 setvareq(name, 0);
9808                         /* else:
9809                          * it's a duplicate "local VAR" declaration, do nothing
9810                          */
9811                         goto ret;
9812                 }
9813                 lvp = lvp->next;
9814         }
9815
9816         lvp = ckzalloc(sizeof(*lvp));
9817         if (LONE_DASH(name)) {
9818                 char *p;
9819                 p = ckmalloc(sizeof(optlist));
9820                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9821                 vp = NULL;
9822         } else {
9823                 vpp = hashvar(name);
9824                 vp = *findvar(vpp, name);
9825                 if (vp == NULL) {
9826                         /* variable did not exist yet */
9827                         if (eq)
9828                                 vp = setvareq(name, VSTRFIXED);
9829                         else
9830                                 vp = setvar(name, NULL, VSTRFIXED);
9831                         lvp->flags = VUNSET;
9832                 } else {
9833                         lvp->text = vp->var_text;
9834                         lvp->flags = vp->flags;
9835                         /* make sure neither "struct var" nor string gets freed
9836                          * during (un)setting:
9837                          */
9838                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9839                         if (eq)
9840                                 setvareq(name, 0);
9841                         else
9842                                 /* "local VAR" unsets VAR: */
9843                                 setvar0(name, NULL);
9844                 }
9845         }
9846         lvp->vp = vp;
9847         lvp->next = localvar_stack->lv;
9848         localvar_stack->lv = lvp;
9849  ret:
9850         INT_ON;
9851 }
9852
9853 /*
9854  * The "local" command.
9855  */
9856 static int FAST_FUNC
9857 localcmd(int argc UNUSED_PARAM, char **argv)
9858 {
9859         char *name;
9860
9861         if (!localvar_stack)
9862                 ash_msg_and_raise_error("not in a function");
9863
9864         argv = argptr;
9865         while ((name = *argv++) != NULL) {
9866                 mklocal(name);
9867         }
9868         return 0;
9869 }
9870
9871 static int FAST_FUNC
9872 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9873 {
9874         return 1;
9875 }
9876
9877 static int FAST_FUNC
9878 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9879 {
9880         return 0;
9881 }
9882
9883 static int FAST_FUNC
9884 execcmd(int argc UNUSED_PARAM, char **argv)
9885 {
9886         optionarg = NULL;
9887         while (nextopt("a:") != '\0')
9888                 /* nextopt() sets optionarg to "-a ARGV0" */;
9889
9890         argv = argptr;
9891         if (argv[0]) {
9892                 char *prog;
9893
9894                 iflag = 0;              /* exit on error */
9895                 mflag = 0;
9896                 optschanged();
9897                 /* We should set up signals for "exec CMD"
9898                  * the same way as for "CMD" without "exec".
9899                  * But optschanged->setinteractive->setsignal
9900                  * still thought we are a root shell. Therefore, for example,
9901                  * SIGQUIT is still set to IGN. Fix it:
9902                  */
9903                 shlvl++;
9904                 setsignal(SIGQUIT);
9905                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9906                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9907                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9908
9909                 prog = argv[0];
9910                 if (optionarg)
9911                         argv[0] = optionarg;
9912                 shellexec(prog, argv, pathval(), 0);
9913                 /* NOTREACHED */
9914         }
9915         return 0;
9916 }
9917
9918 /*
9919  * The return command.
9920  */
9921 static int FAST_FUNC
9922 returncmd(int argc UNUSED_PARAM, char **argv)
9923 {
9924         /*
9925          * If called outside a function, do what ksh does;
9926          * skip the rest of the file.
9927          */
9928         evalskip = SKIPFUNC;
9929         return argv[1] ? number(argv[1]) : exitstatus;
9930 }
9931
9932 /* Forward declarations for builtintab[] */
9933 static int breakcmd(int, char **) FAST_FUNC;
9934 static int dotcmd(int, char **) FAST_FUNC;
9935 static int evalcmd(int, char **, int) FAST_FUNC;
9936 static int exitcmd(int, char **) FAST_FUNC;
9937 static int exportcmd(int, char **) FAST_FUNC;
9938 #if ENABLE_ASH_GETOPTS
9939 static int getoptscmd(int, char **) FAST_FUNC;
9940 #endif
9941 #if ENABLE_ASH_HELP
9942 static int helpcmd(int, char **) FAST_FUNC;
9943 #endif
9944 #if MAX_HISTORY
9945 static int historycmd(int, char **) FAST_FUNC;
9946 #endif
9947 #if ENABLE_FEATURE_SH_MATH
9948 static int letcmd(int, char **) FAST_FUNC;
9949 #endif
9950 static int readcmd(int, char **) FAST_FUNC;
9951 static int setcmd(int, char **) FAST_FUNC;
9952 static int shiftcmd(int, char **) FAST_FUNC;
9953 static int timescmd(int, char **) FAST_FUNC;
9954 static int trapcmd(int, char **) FAST_FUNC;
9955 static int umaskcmd(int, char **) FAST_FUNC;
9956 static int unsetcmd(int, char **) FAST_FUNC;
9957 static int ulimitcmd(int, char **) FAST_FUNC;
9958
9959 #define BUILTIN_NOSPEC          "0"
9960 #define BUILTIN_SPECIAL         "1"
9961 #define BUILTIN_REGULAR         "2"
9962 #define BUILTIN_SPEC_REG        "3"
9963 #define BUILTIN_ASSIGN          "4"
9964 #define BUILTIN_SPEC_ASSG       "5"
9965 #define BUILTIN_REG_ASSG        "6"
9966 #define BUILTIN_SPEC_REG_ASSG   "7"
9967
9968 /* Stubs for calling non-FAST_FUNC's */
9969 #if ENABLE_ASH_ECHO
9970 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9971 #endif
9972 #if ENABLE_ASH_PRINTF
9973 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9974 #endif
9975 #if ENABLE_ASH_TEST || BASH_TEST2
9976 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9977 #endif
9978
9979 /* Keep these in proper order since it is searched via bsearch() */
9980 static const struct builtincmd builtintab[] = {
9981         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9982         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9983 #if ENABLE_ASH_TEST
9984         { BUILTIN_REGULAR       "["       , testcmd    },
9985 #endif
9986 #if BASH_TEST2
9987         { BUILTIN_REGULAR       "[["      , testcmd    },
9988 #endif
9989 #if ENABLE_ASH_ALIAS
9990         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9991 #endif
9992 #if JOBS
9993         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9994 #endif
9995         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9996         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9997         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9998 #if ENABLE_ASH_CMDCMD
9999         { BUILTIN_REGULAR       "command" , commandcmd },
10000 #endif
10001         { BUILTIN_SPEC_REG      "continue", breakcmd   },
10002 #if ENABLE_ASH_ECHO
10003         { BUILTIN_REGULAR       "echo"    , echocmd    },
10004 #endif
10005         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
10006         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
10007         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
10008         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
10009         { BUILTIN_REGULAR       "false"   , falsecmd   },
10010 #if JOBS
10011         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
10012 #endif
10013 #if ENABLE_ASH_GETOPTS
10014         { BUILTIN_REGULAR       "getopts" , getoptscmd },
10015 #endif
10016         { BUILTIN_REGULAR       "hash"    , hashcmd    },
10017 #if ENABLE_ASH_HELP
10018         { BUILTIN_NOSPEC        "help"    , helpcmd    },
10019 #endif
10020 #if MAX_HISTORY
10021         { BUILTIN_NOSPEC        "history" , historycmd },
10022 #endif
10023 #if JOBS
10024         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
10025         { BUILTIN_REGULAR       "kill"    , killcmd    },
10026 #endif
10027 #if ENABLE_FEATURE_SH_MATH
10028         { BUILTIN_NOSPEC        "let"     , letcmd     },
10029 #endif
10030         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
10031 #if ENABLE_ASH_PRINTF
10032         { BUILTIN_REGULAR       "printf"  , printfcmd  },
10033 #endif
10034         { BUILTIN_REGULAR       "pwd"     , pwdcmd     },
10035         { BUILTIN_REGULAR       "read"    , readcmd    },
10036         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
10037         { BUILTIN_SPEC_REG      "return"  , returncmd  },
10038         { BUILTIN_SPEC_REG      "set"     , setcmd     },
10039         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
10040 #if BASH_SOURCE
10041         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
10042 #endif
10043 #if ENABLE_ASH_TEST
10044         { BUILTIN_REGULAR       "test"    , testcmd    },
10045 #endif
10046         { BUILTIN_SPEC_REG      "times"   , timescmd   },
10047         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
10048         { BUILTIN_REGULAR       "true"    , truecmd    },
10049         { BUILTIN_REGULAR       "type"    , typecmd    },
10050         { BUILTIN_REGULAR       "ulimit"  , ulimitcmd  },
10051         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
10052 #if ENABLE_ASH_ALIAS
10053         { BUILTIN_REGULAR       "unalias" , unaliascmd },
10054 #endif
10055         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
10056         { BUILTIN_REGULAR       "wait"    , waitcmd    },
10057 };
10058
10059 /* Should match the above table! */
10060 #define COMMANDCMD (builtintab + \
10061         /* . : */       2 + \
10062         /* [ */         1 * ENABLE_ASH_TEST + \
10063         /* [[ */        1 * BASH_TEST2 + \
10064         /* alias */     1 * ENABLE_ASH_ALIAS + \
10065         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
10066         /* break cd cddir  */   3)
10067 #define EVALCMD (COMMANDCMD + \
10068         /* command */   1 * ENABLE_ASH_CMDCMD + \
10069         /* continue */  1 + \
10070         /* echo */      1 * ENABLE_ASH_ECHO + \
10071         0)
10072 #define EXECCMD (EVALCMD + \
10073         /* eval */      1)
10074
10075 /*
10076  * Search the table of builtin commands.
10077  */
10078 static int
10079 pstrcmp1(const void *a, const void *b)
10080 {
10081         return strcmp((char*)a, *(char**)b + 1);
10082 }
10083 static struct builtincmd *
10084 find_builtin(const char *name)
10085 {
10086         struct builtincmd *bp;
10087
10088         bp = bsearch(
10089                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
10090                 pstrcmp1
10091         );
10092         return bp;
10093 }
10094
10095 #if EDITING_HAS_get_exe_name
10096 static const char * FAST_FUNC
10097 get_builtin_name(int i)
10098 {
10099         return /*i >= 0 &&*/ i < ARRAY_SIZE(builtintab) ? builtintab[i].name + 1 : NULL;
10100 }
10101 #endif
10102
10103 /*
10104  * Execute a simple command.
10105  */
10106 static void unwindfiles(struct parsefile *stop);
10107 static int
10108 isassignment(const char *p)
10109 {
10110         const char *q = endofname(p);
10111         if (p == q)
10112                 return 0;
10113         return *q == '=';
10114 }
10115 static int FAST_FUNC
10116 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10117 {
10118         /* Preserve exitstatus of a previous possible redirection
10119          * as POSIX mandates */
10120         return back_exitstatus;
10121 }
10122 static int
10123 evalcommand(union node *cmd, int flags)
10124 {
10125         static const struct builtincmd null_bltin = {
10126                 "\0\0", bltincmd /* why three NULs? */
10127         };
10128         struct localvar_list *localvar_stop;
10129         struct parsefile *file_stop;
10130         struct redirtab *redir_stop;
10131         union node *argp;
10132         struct arglist arglist;
10133         struct arglist varlist;
10134         char **argv;
10135         int argc;
10136         const struct strlist *sp;
10137         struct cmdentry cmdentry;
10138         struct job *jp;
10139         char *lastarg;
10140         const char *path;
10141         int spclbltin;
10142         int status;
10143         char **nargv;
10144         smallint cmd_is_exec;
10145
10146         errlinno = lineno = cmd->ncmd.linno;
10147         if (funcline)
10148                 lineno -= funcline - 1;
10149
10150         /* First expand the arguments. */
10151         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
10152         localvar_stop = pushlocalvars();
10153         file_stop = g_parsefile;
10154         back_exitstatus = 0;
10155
10156         cmdentry.cmdtype = CMDBUILTIN;
10157         cmdentry.u.cmd = &null_bltin;
10158         varlist.lastp = &varlist.list;
10159         *varlist.lastp = NULL;
10160         arglist.lastp = &arglist.list;
10161         *arglist.lastp = NULL;
10162
10163         argc = 0;
10164         if (cmd->ncmd.args) {
10165                 struct builtincmd *bcmd;
10166                 smallint pseudovarflag;
10167
10168                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
10169                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
10170
10171                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
10172                         struct strlist **spp;
10173
10174                         spp = arglist.lastp;
10175                         if (pseudovarflag && isassignment(argp->narg.text))
10176                                 expandarg(argp, &arglist, EXP_VARTILDE);
10177                         else
10178                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
10179
10180                         for (sp = *spp; sp; sp = sp->next)
10181                                 argc++;
10182                 }
10183         }
10184
10185         /* Reserve one extra spot at the front for shellexec. */
10186         nargv = stalloc(sizeof(char *) * (argc + 2));
10187         argv = ++nargv;
10188         for (sp = arglist.list; sp; sp = sp->next) {
10189                 TRACE(("evalcommand arg: %s\n", sp->text));
10190                 *nargv++ = sp->text;
10191         }
10192         *nargv = NULL;
10193
10194         lastarg = NULL;
10195         if (iflag && funcline == 0 && argc > 0)
10196                 lastarg = nargv[-1];
10197
10198         expredir(cmd->ncmd.redirect);
10199         redir_stop = pushredir(cmd->ncmd.redirect);
10200         preverrout_fd = 2;
10201         if (BASH_XTRACEFD && xflag) {
10202                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
10203                  * we do not emulate this. We only use its value.
10204                  */
10205                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
10206                 if (xtracefd && is_number(xtracefd))
10207                         preverrout_fd = atoi(xtracefd);
10208
10209         }
10210         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
10211
10212         path = vpath.var_text;
10213         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
10214                 struct strlist **spp;
10215                 char *p;
10216
10217                 spp = varlist.lastp;
10218                 expandarg(argp, &varlist, EXP_VARTILDE);
10219
10220                 mklocal((*spp)->text);
10221
10222                 /*
10223                  * Modify the command lookup path, if a PATH= assignment
10224                  * is present
10225                  */
10226                 p = (*spp)->text;
10227                 if (varcmp(p, path) == 0)
10228                         path = p;
10229         }
10230
10231         /* Print the command if xflag is set. */
10232         if (xflag) {
10233                 const char *pfx = "";
10234
10235                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
10236
10237                 sp = varlist.list;
10238                 while (sp) {
10239                         char *varval = sp->text;
10240                         char *eq = strchrnul(varval, '=');
10241                         if (*eq)
10242                                 eq++;
10243                         fdprintf(preverrout_fd, "%s%.*s%s",
10244                                 pfx,
10245                                 (int)(eq - varval), varval,
10246                                 maybe_single_quote(eq)
10247                         );
10248                         sp = sp->next;
10249                         pfx = " ";
10250                 }
10251
10252                 sp = arglist.list;
10253                 while (sp) {
10254                         fdprintf(preverrout_fd, "%s%s",
10255                                 pfx,
10256                                 /* always quote if matches reserved word: */
10257                                 findkwd(sp->text)
10258                                 ? single_quote(sp->text)
10259                                 : maybe_single_quote(sp->text)
10260                         );
10261                         sp = sp->next;
10262                         pfx = " ";
10263                 }
10264                 safe_write(preverrout_fd, "\n", 1);
10265         }
10266
10267         cmd_is_exec = 0;
10268         spclbltin = -1;
10269
10270         /* Now locate the command. */
10271         if (argc) {
10272                 int cmd_flag = DO_ERR;
10273 #if ENABLE_ASH_CMDCMD
10274                 const char *oldpath = path + 5;
10275 #endif
10276                 path += 5;
10277                 for (;;) {
10278                         find_command(argv[0], &cmdentry, cmd_flag, path);
10279                         if (cmdentry.cmdtype == CMDUNKNOWN) {
10280                                 flush_stdout_stderr();
10281                                 status = 127;
10282                                 goto bail;
10283                         }
10284
10285                         /* implement bltin and command here */
10286                         if (cmdentry.cmdtype != CMDBUILTIN)
10287                                 break;
10288                         if (spclbltin < 0)
10289                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
10290                         if (cmdentry.u.cmd == EXECCMD)
10291                                 cmd_is_exec = 1;
10292 #if ENABLE_ASH_CMDCMD
10293                         if (cmdentry.u.cmd == COMMANDCMD) {
10294                                 path = oldpath;
10295                                 nargv = parse_command_args(argv, &path);
10296                                 if (!nargv)
10297                                         break;
10298                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
10299                                  * nargv => "PROG". path is updated if -p.
10300                                  */
10301                                 argc -= nargv - argv;
10302                                 argv = nargv;
10303                                 cmd_flag |= DO_NOFUNC;
10304                         } else
10305 #endif
10306                                 break;
10307                 }
10308         }
10309
10310         if (status) {
10311  bail:
10312                 exitstatus = status;
10313
10314                 /* We have a redirection error. */
10315                 if (spclbltin > 0)
10316                         raise_exception(EXERROR);
10317
10318                 goto out;
10319         }
10320
10321         jp = NULL;
10322
10323         /* Execute the command. */
10324         switch (cmdentry.cmdtype) {
10325         default: {
10326
10327 #if ENABLE_FEATURE_SH_STANDALONE \
10328  && ENABLE_FEATURE_SH_NOFORK \
10329  && NUM_APPLETS > 1
10330 /* (1) BUG: if variables are set, we need to fork, or save/restore them
10331  *     around run_nofork_applet() call.
10332  * (2) Should this check also be done in forkshell()?
10333  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
10334  */
10335                 /* find_command() encodes applet_no as (-2 - applet_no) */
10336                 int applet_no = (- cmdentry.u.index - 2);
10337                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
10338                         char **sv_environ;
10339
10340                         INT_OFF;
10341                         sv_environ = environ;
10342                         environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
10343                         /*
10344                          * Run <applet>_main().
10345                          * Signals (^C) can't interrupt here.
10346                          * Otherwise we can mangle stdio or malloc internal state.
10347                          * This makes applets which can run for a long time
10348                          * and/or wait for user input ineligible for NOFORK:
10349                          * for example, "yes" or "rm" (rm -i waits for input).
10350                          */
10351                         status = run_nofork_applet(applet_no, argv);
10352                         environ = sv_environ;
10353                         /*
10354                          * Try enabling NOFORK for "yes" applet.
10355                          * ^C _will_ stop it (write returns EINTR),
10356                          * but this causes stdout FILE to be stuck
10357                          * and needing clearerr(). What if other applets
10358                          * also can get EINTRs? Do we need to switch
10359                          * our signals to SA_RESTART?
10360                          */
10361                         /*clearerr(stdout);*/
10362                         INT_ON;
10363                         break;
10364                 }
10365 #endif
10366                 /* Can we avoid forking? For example, very last command
10367                  * in a script or a subshell does not need forking,
10368                  * we can just exec it.
10369                  */
10370                 if (!(flags & EV_EXIT) || may_have_traps) {
10371                         /* No, forking off a child is necessary */
10372                         INT_OFF;
10373                         get_tty_state();
10374                         jp = makejob(/*cmd,*/ 1);
10375                         if (forkshell(jp, cmd, FORK_FG) != 0) {
10376                                 /* parent */
10377                                 TRACE(("forked child exited with %d\n", status));
10378                                 break;
10379                         }
10380                         /* child */
10381                         FORCE_INT_ON;
10382                         /* fall through to exec'ing external program */
10383                 }
10384                 listsetvar(varlist.list, VEXPORT|VSTACK);
10385                 shellexec(argv[0], argv, path, cmdentry.u.index);
10386                 /* NOTREACHED */
10387         } /* default */
10388         case CMDBUILTIN:
10389                 if (spclbltin > 0 || argc == 0) {
10390                         poplocalvars(1);
10391                         if (cmd_is_exec && argc > 1)
10392                                 listsetvar(varlist.list, VEXPORT);
10393                 }
10394                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)
10395                  && !(exception_type == EXERROR && spclbltin <= 0)
10396                 ) {
10397  raise:
10398                         longjmp(exception_handler->loc, 1);
10399                 }
10400                 break;
10401
10402         case CMDFUNCTION:
10403                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10404                         goto raise;
10405                 break;
10406         } /* switch */
10407
10408         status = waitforjob(jp);
10409         FORCE_INT_ON;
10410
10411  out:
10412         if (cmd->ncmd.redirect)
10413                 popredir(/*drop:*/ cmd_is_exec);
10414         unwindredir(redir_stop);
10415         unwindfiles(file_stop);
10416         unwindlocalvars(localvar_stop);
10417         if (lastarg) {
10418                 /* dsl: I think this is intended to be used to support
10419                  * '_' in 'vi' command mode during line editing...
10420                  * However I implemented that within libedit itself.
10421                  */
10422                 setvar0("_", lastarg);
10423         }
10424
10425         return status;
10426 }
10427
10428 static int
10429 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10430 {
10431         char *volatile savecmdname;
10432         struct jmploc *volatile savehandler;
10433         struct jmploc jmploc;
10434         int status;
10435         int i;
10436
10437         savecmdname = commandname;
10438         savehandler = exception_handler;
10439         i = setjmp(jmploc.loc);
10440         if (i)
10441                 goto cmddone;
10442         exception_handler = &jmploc;
10443         commandname = argv[0];
10444         argptr = argv + 1;
10445         optptr = NULL;                  /* initialize nextopt */
10446         if (cmd == EVALCMD)
10447                 status = evalcmd(argc, argv, flags);
10448         else
10449                 status = (*cmd->builtin)(argc, argv);
10450         flush_stdout_stderr();
10451         status |= ferror(stdout);
10452         exitstatus = status;
10453  cmddone:
10454         clearerr(stdout);
10455         commandname = savecmdname;
10456         exception_handler = savehandler;
10457
10458         return i;
10459 }
10460
10461 static int
10462 goodname(const char *p)
10463 {
10464         return endofname(p)[0] == '\0';
10465 }
10466
10467
10468 /*
10469  * Search for a command.  This is called before we fork so that the
10470  * location of the command will be available in the parent as well as
10471  * the child.  The check for "goodname" is an overly conservative
10472  * check that the name will not be subject to expansion.
10473  */
10474 static void
10475 prehash(union node *n)
10476 {
10477         struct cmdentry entry;
10478
10479         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10480                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10481 }
10482
10483
10484 /* ============ Builtin commands
10485  *
10486  * Builtin commands whose functions are closely tied to evaluation
10487  * are implemented here.
10488  */
10489
10490 /*
10491  * Handle break and continue commands.  Break, continue, and return are
10492  * all handled by setting the evalskip flag.  The evaluation routines
10493  * above all check this flag, and if it is set they start skipping
10494  * commands rather than executing them.  The variable skipcount is
10495  * the number of loops to break/continue, or the number of function
10496  * levels to return.  (The latter is always 1.)  It should probably
10497  * be an error to break out of more loops than exist, but it isn't
10498  * in the standard shell so we don't make it one here.
10499  */
10500 static int FAST_FUNC
10501 breakcmd(int argc UNUSED_PARAM, char **argv)
10502 {
10503         int n = argv[1] ? number(argv[1]) : 1;
10504
10505         if (n <= 0)
10506                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10507         if (n > loopnest)
10508                 n = loopnest;
10509         if (n > 0) {
10510                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10511                 skipcount = n;
10512         }
10513         return 0;
10514 }
10515
10516
10517 /*
10518  * This implements the input routines used by the parser.
10519  */
10520
10521 enum {
10522         INPUT_PUSH_FILE = 1,
10523         INPUT_NOFILE_OK = 2,
10524 };
10525
10526 static smallint checkkwd;
10527 /* values of checkkwd variable */
10528 #define CHKALIAS        0x1
10529 #define CHKKWD          0x2
10530 #define CHKNL           0x4
10531 #define CHKEOFMARK      0x8
10532
10533 /*
10534  * Push a string back onto the input at this current parsefile level.
10535  * We handle aliases this way.
10536  */
10537 #if !ENABLE_ASH_ALIAS
10538 #define pushstring(s, ap) pushstring(s)
10539 #endif
10540 static void
10541 pushstring(char *s, struct alias *ap)
10542 {
10543         struct strpush *sp;
10544         int len;
10545
10546         len = strlen(s);
10547         INT_OFF;
10548         if (g_parsefile->strpush) {
10549                 sp = ckzalloc(sizeof(*sp));
10550                 sp->prev = g_parsefile->strpush;
10551         } else {
10552                 sp = &(g_parsefile->basestrpush);
10553         }
10554         g_parsefile->strpush = sp;
10555         sp->prev_string = g_parsefile->next_to_pgetc;
10556         sp->prev_left_in_line = g_parsefile->left_in_line;
10557         sp->unget = g_parsefile->unget;
10558         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10559 #if ENABLE_ASH_ALIAS
10560         sp->ap = ap;
10561         if (ap) {
10562                 ap->flag |= ALIASINUSE;
10563                 sp->string = s;
10564         }
10565 #endif
10566         g_parsefile->next_to_pgetc = s;
10567         g_parsefile->left_in_line = len;
10568         g_parsefile->unget = 0;
10569         INT_ON;
10570 }
10571
10572 static void
10573 popstring(void)
10574 {
10575         struct strpush *sp = g_parsefile->strpush;
10576
10577         INT_OFF;
10578 #if ENABLE_ASH_ALIAS
10579         if (sp->ap) {
10580                 if (g_parsefile->next_to_pgetc[-1] == ' '
10581                  || g_parsefile->next_to_pgetc[-1] == '\t'
10582                 ) {
10583                         checkkwd |= CHKALIAS;
10584                 }
10585                 if (sp->string != sp->ap->val) {
10586                         free(sp->string);
10587                 }
10588                 sp->ap->flag &= ~ALIASINUSE;
10589                 if (sp->ap->flag & ALIASDEAD) {
10590                         unalias(sp->ap->name);
10591                 }
10592         }
10593 #endif
10594         g_parsefile->next_to_pgetc = sp->prev_string;
10595         g_parsefile->left_in_line = sp->prev_left_in_line;
10596         g_parsefile->unget = sp->unget;
10597         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10598         g_parsefile->strpush = sp->prev;
10599         if (sp != &(g_parsefile->basestrpush))
10600                 free(sp);
10601         INT_ON;
10602 }
10603
10604 static int
10605 preadfd(void)
10606 {
10607         int nr;
10608         char *buf = g_parsefile->buf;
10609
10610         g_parsefile->next_to_pgetc = buf;
10611 #if ENABLE_FEATURE_EDITING
10612  retry:
10613         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10614                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10615         else {
10616 # if ENABLE_ASH_IDLE_TIMEOUT
10617                 int timeout = -1;
10618                 const char *tmout_var = lookupvar("TMOUT");
10619                 if (tmout_var) {
10620                         timeout = atoi(tmout_var) * 1000;
10621                         if (timeout <= 0)
10622                                 timeout = -1;
10623                 }
10624                 line_input_state->timeout = timeout;
10625 # endif
10626 # if ENABLE_FEATURE_TAB_COMPLETION
10627                 line_input_state->path_lookup = pathval();
10628 # endif
10629                 reinit_unicode_for_ash();
10630                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10631                 if (nr == 0) {
10632                         /* ^C pressed, "convert" to SIGINT */
10633                         write(STDOUT_FILENO, "^C", 2);
10634                         if (trap[SIGINT]) {
10635                                 buf[0] = '\n';
10636                                 buf[1] = '\0';
10637                                 raise(SIGINT);
10638                                 return 1;
10639                         }
10640                         exitstatus = 128 + SIGINT;
10641                         bb_putchar('\n');
10642                         goto retry;
10643                 }
10644                 if (nr < 0) {
10645                         if (errno == 0) {
10646                                 /* Ctrl+D pressed */
10647                                 nr = 0;
10648                         }
10649 # if ENABLE_ASH_IDLE_TIMEOUT
10650                         else if (errno == EAGAIN && timeout > 0) {
10651                                 puts("\007timed out waiting for input: auto-logout");
10652                                 exitshell();
10653                         }
10654 # endif
10655                 }
10656         }
10657 #else
10658         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10659 #endif
10660
10661 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10662         if (nr < 0) {
10663                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10664                         int flags = fcntl(0, F_GETFL);
10665                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10666                                 flags &= ~O_NONBLOCK;
10667                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10668                                         out2str("sh: turning off NDELAY mode\n");
10669                                         goto retry;
10670                                 }
10671                         }
10672                 }
10673         }
10674 #endif
10675         return nr;
10676 }
10677
10678 /*
10679  * Refill the input buffer and return the next input character:
10680  *
10681  * 1) If a string was pushed back on the input, pop it;
10682  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10683  *    or we are reading from a string so we can't refill the buffer,
10684  *    return EOF.
10685  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10686  * 4) Process input up to the next newline, deleting nul characters.
10687  */
10688 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10689 #define pgetc_debug(...) ((void)0)
10690 static int pgetc(void);
10691 static int
10692 preadbuffer(void)
10693 {
10694         char *q;
10695         int more;
10696
10697         if (g_parsefile->strpush) {
10698 #if ENABLE_ASH_ALIAS
10699                 if (g_parsefile->left_in_line == -1
10700                  && g_parsefile->strpush->ap
10701                  && g_parsefile->next_to_pgetc[-1] != ' '
10702                  && g_parsefile->next_to_pgetc[-1] != '\t'
10703                 ) {
10704                         pgetc_debug("preadbuffer PEOA");
10705                         return PEOA;
10706                 }
10707 #endif
10708                 popstring();
10709                 return pgetc();
10710         }
10711         /* on both branches above g_parsefile->left_in_line < 0.
10712          * "pgetc" needs refilling.
10713          */
10714
10715         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10716          * pungetc() may increment it a few times.
10717          * Assuming it won't increment it to less than -90.
10718          */
10719         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10720                 pgetc_debug("preadbuffer PEOF1");
10721                 /* even in failure keep left_in_line and next_to_pgetc
10722                  * in lock step, for correct multi-layer pungetc.
10723                  * left_in_line was decremented before preadbuffer(),
10724                  * must inc next_to_pgetc: */
10725                 g_parsefile->next_to_pgetc++;
10726                 return PEOF;
10727         }
10728
10729         more = g_parsefile->left_in_buffer;
10730         if (more <= 0) {
10731                 flush_stdout_stderr();
10732  again:
10733                 more = preadfd();
10734                 if (more <= 0) {
10735                         /* don't try reading again */
10736                         g_parsefile->left_in_line = -99;
10737                         pgetc_debug("preadbuffer PEOF2");
10738                         g_parsefile->next_to_pgetc++;
10739                         return PEOF;
10740                 }
10741         }
10742
10743         /* Find out where's the end of line.
10744          * Set g_parsefile->left_in_line
10745          * and g_parsefile->left_in_buffer acordingly.
10746          * NUL chars are deleted.
10747          */
10748         q = g_parsefile->next_to_pgetc;
10749         for (;;) {
10750                 char c;
10751
10752                 more--;
10753
10754                 c = *q;
10755                 if (c == '\0') {
10756                         memmove(q, q + 1, more);
10757                 } else {
10758                         q++;
10759                         if (c == '\n') {
10760                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10761                                 break;
10762                         }
10763                 }
10764
10765                 if (more <= 0) {
10766                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10767                         if (g_parsefile->left_in_line < 0)
10768                                 goto again;
10769                         break;
10770                 }
10771         }
10772         g_parsefile->left_in_buffer = more;
10773
10774         if (vflag) {
10775                 char save = *q;
10776                 *q = '\0';
10777                 out2str(g_parsefile->next_to_pgetc);
10778                 *q = save;
10779         }
10780
10781         pgetc_debug("preadbuffer at %d:%p'%s'",
10782                         g_parsefile->left_in_line,
10783                         g_parsefile->next_to_pgetc,
10784                         g_parsefile->next_to_pgetc);
10785         return (unsigned char)*g_parsefile->next_to_pgetc++;
10786 }
10787
10788 static void
10789 nlprompt(void)
10790 {
10791         g_parsefile->linno++;
10792         setprompt_if(doprompt, 2);
10793 }
10794 static void
10795 nlnoprompt(void)
10796 {
10797         g_parsefile->linno++;
10798         needprompt = doprompt;
10799 }
10800
10801 static int
10802 pgetc(void)
10803 {
10804         int c;
10805
10806         pgetc_debug("pgetc at %d:%p'%s'",
10807                         g_parsefile->left_in_line,
10808                         g_parsefile->next_to_pgetc,
10809                         g_parsefile->next_to_pgetc);
10810         if (g_parsefile->unget)
10811                 return g_parsefile->lastc[--g_parsefile->unget];
10812
10813         if (--g_parsefile->left_in_line >= 0)
10814                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10815         else
10816                 c = preadbuffer();
10817
10818         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10819         g_parsefile->lastc[0] = c;
10820
10821         return c;
10822 }
10823
10824 #if ENABLE_ASH_ALIAS
10825 static int
10826 pgetc_without_PEOA(void)
10827 {
10828         int c;
10829         do {
10830                 pgetc_debug("pgetc at %d:%p'%s'",
10831                                 g_parsefile->left_in_line,
10832                                 g_parsefile->next_to_pgetc,
10833                                 g_parsefile->next_to_pgetc);
10834                 c = pgetc();
10835         } while (c == PEOA);
10836         return c;
10837 }
10838 #else
10839 # define pgetc_without_PEOA() pgetc()
10840 #endif
10841
10842 /*
10843  * Undo a call to pgetc.  Only two characters may be pushed back.
10844  * PEOF may be pushed back.
10845  */
10846 static void
10847 pungetc(void)
10848 {
10849         g_parsefile->unget++;
10850 }
10851
10852 /* This one eats backslash+newline */
10853 static int
10854 pgetc_eatbnl(void)
10855 {
10856         int c;
10857
10858         while ((c = pgetc()) == '\\') {
10859                 if (pgetc() != '\n') {
10860                         pungetc();
10861                         break;
10862                 }
10863
10864                 nlprompt();
10865         }
10866
10867         return c;
10868 }
10869
10870 struct synstack {
10871         smalluint syntax;
10872         uint8_t innerdq   :1;
10873         uint8_t varpushed :1;
10874         uint8_t dblquote  :1;
10875         int varnest;            /* levels of variables expansion */
10876         int dqvarnest;          /* levels of variables expansion within double quotes */
10877         int parenlevel;         /* levels of parens in arithmetic */
10878         struct synstack *prev;
10879         struct synstack *next;
10880 };
10881
10882 static int
10883 pgetc_top(struct synstack *stack)
10884 {
10885         return stack->syntax == SQSYNTAX ? pgetc() : pgetc_eatbnl();
10886 }
10887
10888 static void
10889 synstack_push(struct synstack **stack, struct synstack *next, int syntax)
10890 {
10891         memset(next, 0, sizeof(*next));
10892         next->syntax = syntax;
10893         next->next = *stack;
10894         (*stack)->prev = next;
10895         *stack = next;
10896 }
10897
10898 static ALWAYS_INLINE void
10899 synstack_pop(struct synstack **stack)
10900 {
10901         *stack = (*stack)->next;
10902 }
10903
10904 /*
10905  * To handle the "." command, a stack of input files is used.  Pushfile
10906  * adds a new entry to the stack and popfile restores the previous level.
10907  */
10908 static void
10909 pushfile(void)
10910 {
10911         struct parsefile *pf;
10912
10913         pf = ckzalloc(sizeof(*pf));
10914         pf->prev = g_parsefile;
10915         pf->pf_fd = -1;
10916         /*pf->strpush = NULL; - ckzalloc did it */
10917         /*pf->basestrpush.prev = NULL;*/
10918         /*pf->unget = 0;*/
10919         g_parsefile = pf;
10920 }
10921
10922 static void
10923 popfile(void)
10924 {
10925         struct parsefile *pf = g_parsefile;
10926
10927         if (pf == &basepf)
10928                 return;
10929
10930         INT_OFF;
10931         if (pf->pf_fd >= 0)
10932                 close(pf->pf_fd);
10933         free(pf->buf);
10934         while (pf->strpush)
10935                 popstring();
10936         g_parsefile = pf->prev;
10937         free(pf);
10938         INT_ON;
10939 }
10940
10941 static void
10942 unwindfiles(struct parsefile *stop)
10943 {
10944         while (g_parsefile != stop)
10945                 popfile();
10946 }
10947
10948 /*
10949  * Return to top level.
10950  */
10951 static void
10952 popallfiles(void)
10953 {
10954         unwindfiles(&basepf);
10955 }
10956
10957 /*
10958  * Close the file(s) that the shell is reading commands from.  Called
10959  * after a fork is done.
10960  */
10961 static void
10962 closescript(void)
10963 {
10964         popallfiles();
10965         if (g_parsefile->pf_fd > 0) {
10966                 close(g_parsefile->pf_fd);
10967                 g_parsefile->pf_fd = 0;
10968         }
10969 }
10970
10971 /*
10972  * Like setinputfile, but takes an open file descriptor.  Call this with
10973  * interrupts off.
10974  */
10975 static void
10976 setinputfd(int fd, int push)
10977 {
10978         if (push) {
10979                 pushfile();
10980                 g_parsefile->buf = NULL;
10981         }
10982         g_parsefile->pf_fd = fd;
10983         if (g_parsefile->buf == NULL)
10984                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10985         g_parsefile->left_in_buffer = 0;
10986         g_parsefile->left_in_line = 0;
10987         g_parsefile->linno = 1;
10988 }
10989
10990 /*
10991  * Set the input to take input from a file.  If push is set, push the
10992  * old input onto the stack first.
10993  */
10994 static int
10995 setinputfile(const char *fname, int flags)
10996 {
10997         int fd;
10998
10999         INT_OFF;
11000         fd = open(fname, O_RDONLY | O_CLOEXEC);
11001         if (fd < 0) {
11002                 if (flags & INPUT_NOFILE_OK)
11003                         goto out;
11004                 exitstatus = 127;
11005                 ash_msg_and_raise_perror("can't open '%s'", fname);
11006         }
11007         if (fd < 10)
11008                 fd = savefd(fd);
11009         else if (O_CLOEXEC == 0) /* old libc */
11010                 close_on_exec_on(fd);
11011
11012         setinputfd(fd, flags & INPUT_PUSH_FILE);
11013  out:
11014         INT_ON;
11015         return fd;
11016 }
11017
11018 /*
11019  * Like setinputfile, but takes input from a string.
11020  */
11021 static void
11022 setinputstring(char *string)
11023 {
11024         INT_OFF;
11025         pushfile();
11026         g_parsefile->next_to_pgetc = string;
11027         g_parsefile->left_in_line = strlen(string);
11028         g_parsefile->buf = NULL;
11029         g_parsefile->linno = 1;
11030         INT_ON;
11031 }
11032
11033
11034 /*
11035  * Routines to check for mail.
11036  */
11037
11038 #if ENABLE_ASH_MAIL
11039
11040 /* Hash of mtimes of mailboxes */
11041 static unsigned mailtime_hash;
11042 /* Set if MAIL or MAILPATH is changed. */
11043 static smallint mail_var_path_changed;
11044
11045 /*
11046  * Print appropriate message(s) if mail has arrived.
11047  * If mail_var_path_changed is set,
11048  * then the value of MAIL has mail_var_path_changed,
11049  * so we just update the values.
11050  */
11051 static void
11052 chkmail(void)
11053 {
11054         const char *mpath;
11055         char *p;
11056         char *q;
11057         unsigned new_hash;
11058         struct stackmark smark;
11059         struct stat statb;
11060
11061         setstackmark(&smark);
11062         mpath = mpathset() ? mpathval() : mailval();
11063         new_hash = 0;
11064         for (;;) {
11065                 int len;
11066
11067                 len = padvance_magic(&mpath, nullstr, 2);
11068                 if (!len)
11069                         break;
11070                 p = stackblock();
11071                         break;
11072                 if (*p == '\0')
11073                         continue;
11074                 for (q = p; *q; q++)
11075                         continue;
11076 #if DEBUG
11077                 if (q[-1] != '/')
11078                         abort();
11079 #endif
11080                 q[-1] = '\0';                   /* delete trailing '/' */
11081                 if (stat(p, &statb) < 0) {
11082                         continue;
11083                 }
11084                 /* Very simplistic "hash": just a sum of all mtimes */
11085                 new_hash += (unsigned)statb.st_mtime;
11086         }
11087         if (!mail_var_path_changed && mailtime_hash != new_hash) {
11088                 if (mailtime_hash != 0)
11089                         out2str("you have mail\n");
11090                 mailtime_hash = new_hash;
11091         }
11092         mail_var_path_changed = 0;
11093         popstackmark(&smark);
11094 }
11095
11096 static void FAST_FUNC
11097 changemail(const char *val UNUSED_PARAM)
11098 {
11099         mail_var_path_changed = 1;
11100 }
11101
11102 #endif /* ASH_MAIL */
11103
11104
11105 /* ============ ??? */
11106
11107 /*
11108  * Set the shell parameters.
11109  */
11110 static void
11111 setparam(char **argv)
11112 {
11113         char **newparam;
11114         char **ap;
11115         int nparam;
11116
11117         for (nparam = 0; argv[nparam]; nparam++)
11118                 continue;
11119         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
11120         while (*argv) {
11121                 *ap++ = ckstrdup(*argv++);
11122         }
11123         *ap = NULL;
11124         freeparam(&shellparam);
11125         shellparam.malloced = 1;
11126         shellparam.nparam = nparam;
11127         shellparam.p = newparam;
11128 #if ENABLE_ASH_GETOPTS
11129         shellparam.optind = 1;
11130         shellparam.optoff = -1;
11131 #endif
11132 }
11133
11134 /*
11135  * Process shell options.  The global variable argptr contains a pointer
11136  * to the argument list; we advance it past the options.
11137  *
11138  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
11139  * For a non-interactive shell, an error condition encountered
11140  * by a special built-in ... shall cause the shell to write a diagnostic message
11141  * to standard error and exit as shown in the following table:
11142  * Error                                           Special Built-In
11143  * ...
11144  * Utility syntax error (option or operand error)  Shall exit
11145  * ...
11146  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
11147  * we see that bash does not do that (set "finishes" with error code 1 instead,
11148  * and shell continues), and people rely on this behavior!
11149  * Testcase:
11150  * set -o barfoo 2>/dev/null
11151  * echo $?
11152  *
11153  * Oh well. Let's mimic that.
11154  */
11155 static int
11156 plus_minus_o(char *name, int val)
11157 {
11158         int i;
11159
11160         if (name) {
11161                 for (i = 0; i < NOPTS; i++) {
11162                         if (strcmp(name, optnames(i)) == 0) {
11163                                 optlist[i] = val;
11164                                 return 0;
11165                         }
11166                 }
11167                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
11168                 return 1;
11169         }
11170         for (i = 0; i < NOPTS; i++) {
11171                 if (optnames(i)[0] == '\0')
11172                         continue;
11173                 if (val) {
11174                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
11175                 } else {
11176                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
11177                 }
11178         }
11179         return 0;
11180 }
11181 static void
11182 setoption(int flag, int val)
11183 {
11184         int i;
11185
11186         for (i = 0; i < NOPTS; i++) {
11187                 if (optletters(i) == flag && optnames(i)[0] != '\0') {
11188                         optlist[i] = val;
11189                         return;
11190                 }
11191         }
11192         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
11193         /* NOTREACHED */
11194 }
11195 /* If login_sh is not NULL, we are called to parse command line opts,
11196  * not "set -opts"
11197  */
11198 static int
11199 options(int *login_sh)
11200 {
11201         char *p;
11202         int val;
11203         int c;
11204
11205         if (login_sh)
11206                 minusc = NULL;
11207         while ((p = *argptr) != NULL) {
11208                 c = *p++;
11209                 if (c != '-' && c != '+')
11210                         break;
11211                 argptr++;
11212                 val = 0; /* val = 0 if c == '+' */
11213                 if (c == '-') {
11214                         val = 1;
11215                         if (p[0] == '\0' || LONE_DASH(p)) {
11216                                 if (!login_sh) {
11217                                         /* "-" means turn off -x and -v */
11218                                         if (p[0] == '\0')
11219                                                 xflag = vflag = 0;
11220                                         /* "--" means reset params */
11221                                         else if (*argptr == NULL)
11222                                                 setparam(argptr);
11223                                 }
11224                                 break;    /* "-" or "--" terminates options */
11225                         }
11226                 }
11227                 /* first char was + or - */
11228                 while ((c = *p++) != '\0') {
11229                         if (login_sh) {
11230                                 /* bash 3.2 indeed handles -c CMD and +c CMD the same */
11231                                 if (c == 'c') {
11232                                         minusc = p; /* command is after shell args */
11233                                         cflag = 1;
11234                                         continue;
11235                                 }
11236                                 if (c == 's') { /* -s, +s */
11237                                         sflag = 1;
11238                                         continue;
11239                                 }
11240                                 if (c == 'i') { /* -i, +i */
11241                                         iflag = 1;
11242                                         continue;
11243                                 }
11244                                 if (c == 'l') {
11245                                         *login_sh = 1; /* -l or +l == --login */
11246                                         continue;
11247                                 }
11248                                 /* bash does not accept +-login, we also won't */
11249                                 if (val && (c == '-')) { /* long options */
11250                                         if (strcmp(p, "login") == 0) {
11251                                                 *login_sh = 1;
11252                                         }
11253                                         break;
11254                                 }
11255                         }
11256                         if (c == 'o') {
11257                                 if (plus_minus_o(*argptr, val)) {
11258                                         /* it already printed err message */
11259                                         return 1; /* error */
11260                                 }
11261                                 if (*argptr)
11262                                         argptr++;
11263                         } else {
11264                                 setoption(c, val);
11265                         }
11266                 }
11267         }
11268         return 0;
11269 }
11270
11271 /*
11272  * The shift builtin command.
11273  */
11274 static int FAST_FUNC
11275 shiftcmd(int argc UNUSED_PARAM, char **argv)
11276 {
11277         int n;
11278         char **ap1, **ap2;
11279
11280         n = 1;
11281         if (argv[1])
11282                 n = number(argv[1]);
11283         if (n > shellparam.nparam)
11284                 return 1;
11285         INT_OFF;
11286         shellparam.nparam -= n;
11287         for (ap1 = shellparam.p; --n >= 0; ap1++) {
11288                 if (shellparam.malloced)
11289                         free(*ap1);
11290         }
11291         ap2 = shellparam.p;
11292         while ((*ap2++ = *ap1++) != NULL)
11293                 continue;
11294 #if ENABLE_ASH_GETOPTS
11295         shellparam.optind = 1;
11296         shellparam.optoff = -1;
11297 #endif
11298         INT_ON;
11299         return 0;
11300 }
11301
11302 /*
11303  * POSIX requires that 'set' (but not export or readonly) output the
11304  * variables in lexicographic order - by the locale's collating order (sigh).
11305  * Maybe we could keep them in an ordered balanced binary tree
11306  * instead of hashed lists.
11307  * For now just roll 'em through qsort for printing...
11308  */
11309 static int
11310 showvars(const char *sep_prefix, int on, int off)
11311 {
11312         const char *sep;
11313         char **ep, **epend;
11314
11315         ep = listvars(on, off, /*strlist:*/ NULL, &epend);
11316         qsort(ep, epend - ep, sizeof(char *), vpcmp);
11317
11318         sep = *sep_prefix ? " " : sep_prefix;
11319
11320         for (; ep < epend; ep++) {
11321                 const char *p;
11322                 const char *q;
11323
11324                 p = endofname(*ep);
11325 /* Used to have simple "p = strchrnul(*ep, '=')" here instead, but this
11326  * makes "export -p" to have output not suitable for "eval":
11327  * import os
11328  * os.environ["test-test"]="test"
11329  * if os.fork() == 0:
11330  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
11331  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])
11332  */
11333                 q = nullstr;
11334                 if (*p == '=')
11335                         q = single_quote(++p);
11336                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
11337         }
11338         return 0;
11339 }
11340
11341 /*
11342  * The set command builtin.
11343  */
11344 static int FAST_FUNC
11345 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11346 {
11347         int retval;
11348
11349         if (!argv[1])
11350                 return showvars(nullstr, 0, VUNSET);
11351
11352         INT_OFF;
11353         retval = options(/*login_sh:*/ NULL);
11354         if (retval == 0) { /* if no parse error... */
11355                 optschanged();
11356                 if (*argptr != NULL) {
11357                         setparam(argptr);
11358                 }
11359         }
11360         INT_ON;
11361         return retval;
11362 }
11363
11364 #if ENABLE_ASH_RANDOM_SUPPORT
11365 static void FAST_FUNC
11366 change_random(const char *value)
11367 {
11368         uint32_t t;
11369
11370         if (value == NULL) {
11371                 /* "get", generate */
11372                 t = next_random(&random_gen);
11373                 /* set without recursion */
11374                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
11375                 vrandom.flags &= ~VNOFUNC;
11376         } else {
11377                 /* set/reset */
11378                 t = strtoul(value, NULL, 10);
11379                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
11380         }
11381 }
11382 #endif
11383
11384 #if BASH_EPOCH_VARS
11385 static void FAST_FUNC
11386 change_epoch(struct var *vepoch, const char *fmt)
11387 {
11388         struct timeval tv;
11389         char buffer[sizeof("%lu.nnnnnn") + sizeof(long)*3];
11390
11391         gettimeofday(&tv, NULL);
11392         sprintf(buffer, fmt, (unsigned long)tv.tv_sec, (unsigned)tv.tv_usec);
11393         setvar(vepoch->var_text, buffer, VNOFUNC);
11394         vepoch->flags &= ~VNOFUNC;
11395 }
11396
11397 static void FAST_FUNC
11398 change_seconds(const char *value UNUSED_PARAM)
11399 {
11400         change_epoch(&vepochs, "%lu");
11401 }
11402
11403 static void FAST_FUNC
11404 change_realtime(const char *value UNUSED_PARAM)
11405 {
11406         change_epoch(&vepochr, "%lu.%06u");
11407 }
11408 #endif
11409
11410 #if ENABLE_ASH_GETOPTS
11411 static int
11412 getopts(char *optstr, char *optvar, char **optfirst)
11413 {
11414         char *p, *q;
11415         char c = '?';
11416         int done = 0;
11417         char sbuf[2];
11418         char **optnext;
11419         int ind = shellparam.optind;
11420         int off = shellparam.optoff;
11421
11422         sbuf[1] = '\0';
11423
11424         shellparam.optind = -1;
11425         optnext = optfirst + ind - 1;
11426
11427         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
11428                 p = NULL;
11429         else
11430                 p = optnext[-1] + off;
11431         if (p == NULL || *p == '\0') {
11432                 /* Current word is done, advance */
11433                 p = *optnext;
11434                 if (p == NULL || *p != '-' || *++p == '\0') {
11435  atend:
11436                         unsetvar("OPTARG");
11437                         p = NULL;
11438                         done = 1;
11439                         goto out;
11440                 }
11441                 optnext++;
11442                 if (LONE_DASH(p))        /* check for "--" */
11443                         goto atend;
11444         }
11445
11446         c = *p++;
11447         for (q = optstr; *q != c;) {
11448                 if (*q == '\0') {
11449                         /* OPTERR is a bashism */
11450                         const char *cp = lookupvar("OPTERR");
11451                         if ((cp && LONE_CHAR(cp, '0'))
11452                          || (optstr[0] == ':')
11453                         ) {
11454                                 sbuf[0] = c;
11455                                 /*sbuf[1] = '\0'; - already is */
11456                                 setvar0("OPTARG", sbuf);
11457                         } else {
11458                                 fprintf(stderr, "Illegal option -%c\n", c);
11459                                 unsetvar("OPTARG");
11460                         }
11461                         c = '?';
11462                         goto out;
11463                 }
11464                 if (*++q == ':')
11465                         q++;
11466         }
11467
11468         if (*++q == ':') {
11469                 if (*p == '\0' && (p = *optnext) == NULL) {
11470                         /* OPTERR is a bashism */
11471                         const char *cp = lookupvar("OPTERR");
11472                         if ((cp && LONE_CHAR(cp, '0'))
11473                          || (optstr[0] == ':')
11474                         ) {
11475                                 sbuf[0] = c;
11476                                 /*sbuf[1] = '\0'; - already is */
11477                                 setvar0("OPTARG", sbuf);
11478                                 c = ':';
11479                         } else {
11480                                 fprintf(stderr, "No arg for -%c option\n", c);
11481                                 unsetvar("OPTARG");
11482                                 c = '?';
11483                         }
11484                         goto out;
11485                 }
11486
11487                 if (p == *optnext)
11488                         optnext++;
11489                 setvar0("OPTARG", p);
11490                 p = NULL;
11491         } else
11492                 setvar0("OPTARG", nullstr);
11493  out:
11494         ind = optnext - optfirst + 1;
11495         setvar("OPTIND", itoa(ind), VNOFUNC);
11496         sbuf[0] = c;
11497         /*sbuf[1] = '\0'; - already is */
11498         setvar0(optvar, sbuf);
11499
11500         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11501         shellparam.optind = ind;
11502
11503         return done;
11504 }
11505
11506 /*
11507  * The getopts builtin.  Shellparam.optnext points to the next argument
11508  * to be processed.  Shellparam.optptr points to the next character to
11509  * be processed in the current argument.  If shellparam.optnext is NULL,
11510  * then it's the first time getopts has been called.
11511  */
11512 static int FAST_FUNC
11513 getoptscmd(int argc, char **argv)
11514 {
11515         char **optbase;
11516
11517         if (argc < 3)
11518                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11519         if (argc == 3) {
11520                 optbase = shellparam.p;
11521                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11522                         shellparam.optind = 1;
11523                         shellparam.optoff = -1;
11524                 }
11525         } else {
11526                 optbase = &argv[3];
11527                 if ((unsigned)shellparam.optind > argc - 2) {
11528                         shellparam.optind = 1;
11529                         shellparam.optoff = -1;
11530                 }
11531         }
11532
11533         return getopts(argv[1], argv[2], optbase);
11534 }
11535 #endif /* ASH_GETOPTS */
11536
11537
11538 /* ============ Shell parser */
11539
11540 struct heredoc {
11541         struct heredoc *next;   /* next here document in list */
11542         union node *here;       /* redirection node */
11543         char *eofmark;          /* string indicating end of input */
11544         smallint striptabs;     /* if set, strip leading tabs */
11545 };
11546
11547 static smallint tokpushback;           /* last token pushed back */
11548 static smallint quoteflag;             /* set if (part of) last token was quoted */
11549 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11550 static struct heredoc *heredoclist;    /* list of here documents to read */
11551 static char *wordtext;                 /* text of last word returned by readtoken */
11552 static struct nodelist *backquotelist;
11553 static union node *redirnode;
11554 static struct heredoc *heredoc;
11555
11556 static const char *
11557 tokname(char *buf, int tok)
11558 {
11559         if (tok < TSEMI)
11560                 return tokname_array[tok];
11561         sprintf(buf, "\"%s\"", tokname_array[tok]);
11562         return buf;
11563 }
11564
11565 /* raise_error_unexpected_syntax:
11566  * Called when an unexpected token is read during the parse.  The argument
11567  * is the token that is expected, or -1 if more than one type of token can
11568  * occur at this point.
11569  */
11570 static void raise_error_unexpected_syntax(int) NORETURN;
11571 static void
11572 raise_error_unexpected_syntax(int token)
11573 {
11574         char msg[64];
11575         char buf[16];
11576         int l;
11577
11578         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11579         if (token >= 0)
11580                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11581         raise_error_syntax(msg);
11582         /* NOTREACHED */
11583 }
11584
11585 /* parsing is heavily cross-recursive, need these forward decls */
11586 static union node *andor(void);
11587 static union node *pipeline(void);
11588 static union node *parse_command(void);
11589 static void parseheredoc(void);
11590 static int peektoken(void);
11591 static int readtoken(void);
11592
11593 static union node *
11594 list(int nlflag)
11595 {
11596         union node *n1, *n2, *n3;
11597         int tok;
11598
11599         n1 = NULL;
11600         for (;;) {
11601                 switch (peektoken()) {
11602                 case TNL:
11603                         if (!(nlflag & 1))
11604                                 break;
11605                         parseheredoc();
11606                         return n1;
11607
11608                 case TEOF:
11609                         if (!n1 && (nlflag & 1))
11610                                 n1 = NODE_EOF;
11611                         parseheredoc();
11612                         return n1;
11613                 }
11614
11615                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11616                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11617                         return n1;
11618                 nlflag |= 2;
11619
11620                 n2 = andor();
11621                 tok = readtoken();
11622                 if (tok == TBACKGND) {
11623                         if (n2->type == NPIPE) {
11624                                 n2->npipe.pipe_backgnd = 1;
11625                         } else {
11626                                 if (n2->type != NREDIR) {
11627                                         n3 = stzalloc(sizeof(struct nredir));
11628                                         n3->nredir.n = n2;
11629                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11630                                         n2 = n3;
11631                                 }
11632                                 n2->type = NBACKGND;
11633                         }
11634                 }
11635                 if (n1 == NULL) {
11636                         n1 = n2;
11637                 } else {
11638                         n3 = stzalloc(sizeof(struct nbinary));
11639                         n3->type = NSEMI;
11640                         n3->nbinary.ch1 = n1;
11641                         n3->nbinary.ch2 = n2;
11642                         n1 = n3;
11643                 }
11644                 switch (tok) {
11645                 case TNL:
11646                 case TEOF:
11647                         tokpushback = 1;
11648                         /* fall through */
11649                 case TBACKGND:
11650                 case TSEMI:
11651                         break;
11652                 default:
11653                         if ((nlflag & 1))
11654                                 raise_error_unexpected_syntax(-1);
11655                         tokpushback = 1;
11656                         return n1;
11657                 }
11658         }
11659 }
11660
11661 static union node *
11662 andor(void)
11663 {
11664         union node *n1, *n2, *n3;
11665         int t;
11666
11667         n1 = pipeline();
11668         for (;;) {
11669                 t = readtoken();
11670                 if (t == TAND) {
11671                         t = NAND;
11672                 } else if (t == TOR) {
11673                         t = NOR;
11674                 } else {
11675                         tokpushback = 1;
11676                         return n1;
11677                 }
11678                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11679                 n2 = pipeline();
11680                 n3 = stzalloc(sizeof(struct nbinary));
11681                 n3->type = t;
11682                 n3->nbinary.ch1 = n1;
11683                 n3->nbinary.ch2 = n2;
11684                 n1 = n3;
11685         }
11686 }
11687
11688 static union node *
11689 pipeline(void)
11690 {
11691         union node *n1, *n2, *pipenode;
11692         struct nodelist *lp, *prev;
11693         int negate;
11694
11695         negate = 0;
11696         TRACE(("pipeline: entered\n"));
11697         if (readtoken() == TNOT) {
11698                 negate = !negate;
11699                 checkkwd = CHKKWD | CHKALIAS;
11700         } else
11701                 tokpushback = 1;
11702         n1 = parse_command();
11703         if (readtoken() == TPIPE) {
11704                 pipenode = stzalloc(sizeof(struct npipe));
11705                 pipenode->type = NPIPE;
11706                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11707                 lp = stzalloc(sizeof(struct nodelist));
11708                 pipenode->npipe.cmdlist = lp;
11709                 lp->n = n1;
11710                 do {
11711                         prev = lp;
11712                         lp = stzalloc(sizeof(struct nodelist));
11713                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11714                         lp->n = parse_command();
11715                         prev->next = lp;
11716                 } while (readtoken() == TPIPE);
11717                 lp->next = NULL;
11718                 n1 = pipenode;
11719         }
11720         tokpushback = 1;
11721         if (negate) {
11722                 n2 = stzalloc(sizeof(struct nnot));
11723                 n2->type = NNOT;
11724                 n2->nnot.com = n1;
11725                 return n2;
11726         }
11727         return n1;
11728 }
11729
11730 static union node *
11731 makename(void)
11732 {
11733         union node *n;
11734
11735         n = stzalloc(sizeof(struct narg));
11736         n->type = NARG;
11737         /*n->narg.next = NULL; - stzalloc did it */
11738         n->narg.text = wordtext;
11739         n->narg.backquote = backquotelist;
11740         return n;
11741 }
11742
11743 static void
11744 fixredir(union node *n, const char *text, int err)
11745 {
11746         int fd;
11747
11748         TRACE(("Fix redir %s %d\n", text, err));
11749         if (!err)
11750                 n->ndup.vname = NULL;
11751
11752         fd = bb_strtou(text, NULL, 10);
11753         if (!errno && fd >= 0)
11754                 n->ndup.dupfd = fd;
11755         else if (LONE_DASH(text))
11756                 n->ndup.dupfd = -1;
11757         else {
11758                 if (err)
11759                         raise_error_syntax("bad fd number");
11760                 n->ndup.vname = makename();
11761         }
11762 }
11763
11764 static void
11765 parsefname(void)
11766 {
11767         union node *n = redirnode;
11768
11769         if (n->type == NHERE)
11770                 checkkwd = CHKEOFMARK;
11771         if (readtoken() != TWORD)
11772                 raise_error_unexpected_syntax(-1);
11773         if (n->type == NHERE) {
11774                 struct heredoc *here = heredoc;
11775                 struct heredoc *p;
11776
11777                 if (quoteflag == 0)
11778                         n->type = NXHERE;
11779                 TRACE(("Here document %d\n", n->type));
11780                 rmescapes(wordtext, 0, NULL);
11781                 here->eofmark = wordtext;
11782                 here->next = NULL;
11783                 if (heredoclist == NULL)
11784                         heredoclist = here;
11785                 else {
11786                         for (p = heredoclist; p->next; p = p->next)
11787                                 continue;
11788                         p->next = here;
11789                 }
11790         } else if (n->type == NTOFD || n->type == NFROMFD) {
11791                 fixredir(n, wordtext, 0);
11792         } else {
11793                 n->nfile.fname = makename();
11794         }
11795 }
11796
11797 static union node *
11798 simplecmd(void)
11799 {
11800         union node *args, **app;
11801         union node *n = NULL;
11802         union node *vars, **vpp;
11803         union node **rpp, *redir;
11804         int savecheckkwd;
11805         int savelinno;
11806 #if BASH_TEST2
11807         smallint double_brackets_flag = 0;
11808 #endif
11809         IF_BASH_FUNCTION(smallint function_flag = 0;)
11810
11811         args = NULL;
11812         app = &args;
11813         vars = NULL;
11814         vpp = &vars;
11815         redir = NULL;
11816         rpp = &redir;
11817
11818         savecheckkwd = CHKALIAS;
11819         savelinno = g_parsefile->linno;
11820         for (;;) {
11821                 int t;
11822                 checkkwd = savecheckkwd;
11823                 t = readtoken();
11824                 switch (t) {
11825 #if BASH_FUNCTION
11826                 case TFUNCTION:
11827                         if (peektoken() != TWORD)
11828                                 raise_error_unexpected_syntax(TWORD);
11829                         function_flag = 1;
11830                         break;
11831 #endif
11832 #if BASH_TEST2
11833                 case TAND: /* "&&" */
11834                 case TOR: /* "||" */
11835                         if (!double_brackets_flag) {
11836                                 tokpushback = 1;
11837                                 goto out;
11838                         }
11839                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11840 #endif
11841                 case TWORD:
11842                         n = stzalloc(sizeof(struct narg));
11843                         n->type = NARG;
11844                         /*n->narg.next = NULL; - stzalloc did it */
11845                         n->narg.text = wordtext;
11846 #if BASH_TEST2
11847                         if (strcmp("[[", wordtext) == 0)
11848                                 double_brackets_flag = 1;
11849                         else if (strcmp("]]", wordtext) == 0)
11850                                 double_brackets_flag = 0;
11851 #endif
11852                         n->narg.backquote = backquotelist;
11853                         if (savecheckkwd && isassignment(wordtext)) {
11854                                 *vpp = n;
11855                                 vpp = &n->narg.next;
11856                         } else {
11857                                 *app = n;
11858                                 app = &n->narg.next;
11859                                 savecheckkwd = 0;
11860                         }
11861 #if BASH_FUNCTION
11862                         if (function_flag) {
11863                                 checkkwd = CHKNL | CHKKWD;
11864                                 switch (peektoken()) {
11865                                 case TBEGIN:
11866                                 case TIF:
11867                                 case TCASE:
11868                                 case TUNTIL:
11869                                 case TWHILE:
11870                                 case TFOR:
11871                                         goto do_func;
11872                                 case TLP:
11873                                         function_flag = 0;
11874                                         break;
11875 # if BASH_TEST2
11876                                 case TWORD:
11877                                         if (strcmp("[[", wordtext) == 0)
11878                                                 goto do_func;
11879                                         /* fall through */
11880 # endif
11881                                 default:
11882                                         raise_error_unexpected_syntax(-1);
11883                                 }
11884                         }
11885 #endif
11886                         break;
11887                 case TREDIR:
11888                         *rpp = n = redirnode;
11889                         rpp = &n->nfile.next;
11890                         parsefname();   /* read name of redirection file */
11891                         break;
11892                 case TLP:
11893  IF_BASH_FUNCTION(do_func:)
11894                         if (args && app == &args->narg.next
11895                          && !vars && !redir
11896                         ) {
11897                                 struct builtincmd *bcmd;
11898                                 const char *name;
11899
11900                                 /* We have a function */
11901                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11902                                         raise_error_unexpected_syntax(TRP);
11903                                 name = n->narg.text;
11904                                 if (!goodname(name)
11905                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11906                                 ) {
11907                                         raise_error_syntax("bad function name");
11908                                 }
11909                                 n->type = NDEFUN;
11910                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11911                                 n->ndefun.text = n->narg.text;
11912                                 n->ndefun.linno = g_parsefile->linno;
11913                                 n->ndefun.body = parse_command();
11914                                 return n;
11915                         }
11916                         IF_BASH_FUNCTION(function_flag = 0;)
11917                         /* fall through */
11918                 default:
11919                         tokpushback = 1;
11920                         goto out;
11921                 }
11922         }
11923  out:
11924         *app = NULL;
11925         *vpp = NULL;
11926         *rpp = NULL;
11927         n = stzalloc(sizeof(struct ncmd));
11928         if (NCMD != 0)
11929                 n->type = NCMD;
11930         n->ncmd.linno = savelinno;
11931         n->ncmd.args = args;
11932         n->ncmd.assign = vars;
11933         n->ncmd.redirect = redir;
11934         return n;
11935 }
11936
11937 static union node *
11938 parse_command(void)
11939 {
11940         union node *n1, *n2;
11941         union node *ap, **app;
11942         union node *cp, **cpp;
11943         union node *redir, **rpp;
11944         union node **rpp2;
11945         int t;
11946         int savelinno;
11947
11948         redir = NULL;
11949         rpp2 = &redir;
11950
11951         savelinno = g_parsefile->linno;
11952
11953         switch (readtoken()) {
11954         default:
11955                 raise_error_unexpected_syntax(-1);
11956                 /* NOTREACHED */
11957         case TIF:
11958                 n1 = stzalloc(sizeof(struct nif));
11959                 n1->type = NIF;
11960                 n1->nif.test = list(0);
11961                 if (readtoken() != TTHEN)
11962                         raise_error_unexpected_syntax(TTHEN);
11963                 n1->nif.ifpart = list(0);
11964                 n2 = n1;
11965                 while (readtoken() == TELIF) {
11966                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11967                         n2 = n2->nif.elsepart;
11968                         n2->type = NIF;
11969                         n2->nif.test = list(0);
11970                         if (readtoken() != TTHEN)
11971                                 raise_error_unexpected_syntax(TTHEN);
11972                         n2->nif.ifpart = list(0);
11973                 }
11974                 if (lasttoken == TELSE)
11975                         n2->nif.elsepart = list(0);
11976                 else {
11977                         n2->nif.elsepart = NULL;
11978                         tokpushback = 1;
11979                 }
11980                 t = TFI;
11981                 break;
11982         case TWHILE:
11983         case TUNTIL: {
11984                 int got;
11985                 n1 = stzalloc(sizeof(struct nbinary));
11986                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11987                 n1->nbinary.ch1 = list(0);
11988                 got = readtoken();
11989                 if (got != TDO) {
11990                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11991                                         got == TWORD ? wordtext : ""));
11992                         raise_error_unexpected_syntax(TDO);
11993                 }
11994                 n1->nbinary.ch2 = list(0);
11995                 t = TDONE;
11996                 break;
11997         }
11998         case TFOR:
11999                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
12000                         raise_error_syntax("bad for loop variable");
12001                 n1 = stzalloc(sizeof(struct nfor));
12002                 n1->type = NFOR;
12003                 n1->nfor.linno = savelinno;
12004                 n1->nfor.var = wordtext;
12005                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
12006                 if (readtoken() == TIN) {
12007                         app = &ap;
12008                         while (readtoken() == TWORD) {
12009                                 n2 = stzalloc(sizeof(struct narg));
12010                                 n2->type = NARG;
12011                                 /*n2->narg.next = NULL; - stzalloc did it */
12012                                 n2->narg.text = wordtext;
12013                                 n2->narg.backquote = backquotelist;
12014                                 *app = n2;
12015                                 app = &n2->narg.next;
12016                         }
12017                         *app = NULL;
12018                         n1->nfor.args = ap;
12019                         if (lasttoken != TNL && lasttoken != TSEMI)
12020                                 raise_error_unexpected_syntax(-1);
12021                 } else {
12022                         n2 = stzalloc(sizeof(struct narg));
12023                         n2->type = NARG;
12024                         /*n2->narg.next = NULL; - stzalloc did it */
12025                         n2->narg.text = (char *)dolatstr;
12026                         /*n2->narg.backquote = NULL;*/
12027                         n1->nfor.args = n2;
12028                         /*
12029                          * Newline or semicolon here is optional (but note
12030                          * that the original Bourne shell only allowed NL).
12031                          */
12032                         if (lasttoken != TSEMI)
12033                                 tokpushback = 1;
12034                 }
12035                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
12036                 if (readtoken() != TDO)
12037                         raise_error_unexpected_syntax(TDO);
12038                 n1->nfor.body = list(0);
12039                 t = TDONE;
12040                 break;
12041         case TCASE:
12042                 n1 = stzalloc(sizeof(struct ncase));
12043                 n1->type = NCASE;
12044                 n1->ncase.linno = savelinno;
12045                 if (readtoken() != TWORD)
12046                         raise_error_unexpected_syntax(TWORD);
12047                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
12048                 n2->type = NARG;
12049                 /*n2->narg.next = NULL; - stzalloc did it */
12050                 n2->narg.text = wordtext;
12051                 n2->narg.backquote = backquotelist;
12052                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
12053                 if (readtoken() != TIN)
12054                         raise_error_unexpected_syntax(TIN);
12055                 cpp = &n1->ncase.cases;
12056  next_case:
12057                 checkkwd = CHKNL | CHKKWD;
12058                 t = readtoken();
12059                 while (t != TESAC) {
12060                         if (lasttoken == TLP)
12061                                 readtoken();
12062                         *cpp = cp = stzalloc(sizeof(struct nclist));
12063                         cp->type = NCLIST;
12064                         app = &cp->nclist.pattern;
12065                         for (;;) {
12066                                 *app = ap = stzalloc(sizeof(struct narg));
12067                                 ap->type = NARG;
12068                                 /*ap->narg.next = NULL; - stzalloc did it */
12069                                 ap->narg.text = wordtext;
12070                                 ap->narg.backquote = backquotelist;
12071                                 if (readtoken() != TPIPE)
12072                                         break;
12073                                 app = &ap->narg.next;
12074                                 readtoken();
12075                         }
12076                         //ap->narg.next = NULL;
12077                         if (lasttoken != TRP)
12078                                 raise_error_unexpected_syntax(TRP);
12079                         cp->nclist.body = list(2);
12080
12081                         cpp = &cp->nclist.next;
12082
12083                         checkkwd = CHKNL | CHKKWD;
12084                         t = readtoken();
12085                         if (t != TESAC) {
12086                                 if (t != TENDCASE)
12087                                         raise_error_unexpected_syntax(TENDCASE);
12088                                 goto next_case;
12089                         }
12090                 }
12091                 *cpp = NULL;
12092                 goto redir;
12093         case TLP:
12094                 n1 = stzalloc(sizeof(struct nredir));
12095                 n1->type = NSUBSHELL;
12096                 n1->nredir.linno = savelinno;
12097                 n1->nredir.n = list(0);
12098                 /*n1->nredir.redirect = NULL; - stzalloc did it */
12099                 t = TRP;
12100                 break;
12101         case TBEGIN:
12102                 n1 = list(0);
12103                 t = TEND;
12104                 break;
12105         IF_BASH_FUNCTION(case TFUNCTION:)
12106         case TWORD:
12107         case TREDIR:
12108                 tokpushback = 1;
12109                 return simplecmd();
12110         }
12111
12112         if (readtoken() != t)
12113                 raise_error_unexpected_syntax(t);
12114
12115  redir:
12116         /* Now check for redirection which may follow command */
12117         checkkwd = CHKKWD | CHKALIAS;
12118         rpp = rpp2;
12119         while (readtoken() == TREDIR) {
12120                 *rpp = n2 = redirnode;
12121                 rpp = &n2->nfile.next;
12122                 parsefname();
12123         }
12124         tokpushback = 1;
12125         *rpp = NULL;
12126         if (redir) {
12127                 if (n1->type != NSUBSHELL) {
12128                         n2 = stzalloc(sizeof(struct nredir));
12129                         n2->type = NREDIR;
12130                         n2->nredir.linno = savelinno;
12131                         n2->nredir.n = n1;
12132                         n1 = n2;
12133                 }
12134                 n1->nredir.redirect = redir;
12135         }
12136         return n1;
12137 }
12138
12139 #if BASH_DOLLAR_SQUOTE
12140 static int
12141 decode_dollar_squote(void)
12142 {
12143         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
12144         int c, cnt;
12145         char *p;
12146         char buf[4];
12147
12148         c = pgetc();
12149         p = strchr(C_escapes, c);
12150         if (p) {
12151                 buf[0] = c;
12152                 p = buf;
12153                 cnt = 3;
12154                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
12155                         do {
12156                                 c = pgetc();
12157                                 *++p = c;
12158                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
12159                         pungetc();
12160                 } else if (c == 'x') { /* \xHH */
12161                         do {
12162                                 c = pgetc();
12163                                 *++p = c;
12164                         } while (isxdigit(c) && --cnt);
12165                         pungetc();
12166                         if (cnt == 3) { /* \x but next char is "bad" */
12167                                 c = 'x';
12168                                 goto unrecognized;
12169                         }
12170                 } else { /* simple seq like \\ or \t */
12171                         p++;
12172                 }
12173                 *p = '\0';
12174                 p = buf;
12175                 c = bb_process_escape_sequence((void*)&p);
12176         } else { /* unrecognized "\z": print both chars unless ' or " */
12177                 if (c != '\'' && c != '"') {
12178  unrecognized:
12179                         c |= 0x100; /* "please encode \, then me" */
12180                 }
12181         }
12182         return c;
12183 }
12184 #endif
12185
12186 /* Used by expandstr to get here-doc like behaviour. */
12187 #define FAKEEOFMARK ((char*)(uintptr_t)1)
12188
12189 static ALWAYS_INLINE int
12190 realeofmark(const char *eofmark)
12191 {
12192         return eofmark && eofmark != FAKEEOFMARK;
12193 }
12194
12195 /*
12196  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
12197  * is not NULL, read a here document.  In the latter case, eofmark is the
12198  * word which marks the end of the document and striptabs is true if
12199  * leading tabs should be stripped from the document.  The argument c
12200  * is the first character of the input token or document.
12201  *
12202  * Because C does not have internal subroutines, I have simulated them
12203  * using goto's to implement the subroutine linkage.  The following macros
12204  * will run code that appears at the end of readtoken1.
12205  */
12206 #define CHECKEND()      {goto checkend; checkend_return:;}
12207 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
12208 #define PARSESUB()      {goto parsesub; parsesub_return:;}
12209 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
12210 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
12211 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
12212 static int
12213 readtoken1(int c, int syntax, char *eofmark, int striptabs)
12214 {
12215         /* NB: syntax parameter fits into smallint */
12216         /* c parameter is an unsigned char or PEOF or PEOA */
12217         char *out;
12218         size_t len;
12219         struct nodelist *bqlist;
12220         smallint quotef;
12221         smallint oldstyle;
12222         smallint pssyntax;   /* we are expanding a prompt string */
12223         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
12224         /* syntax stack */
12225         struct synstack synbase = { };
12226         struct synstack *synstack = &synbase;
12227
12228 #if ENABLE_ASH_EXPAND_PRMT
12229         pssyntax = (syntax == PSSYNTAX);
12230         if (pssyntax)
12231                 syntax = DQSYNTAX;
12232 #else
12233         pssyntax = 0; /* constant */
12234 #endif
12235         synstack->syntax = syntax;
12236
12237         if (syntax == DQSYNTAX)
12238                 synstack->dblquote = 1;
12239         quotef = 0;
12240         bqlist = NULL;
12241
12242         STARTSTACKSTR(out);
12243  loop:
12244         /* For each line, until end of word */
12245         CHECKEND();     /* set c to PEOF if at end of here document */
12246         for (;;) {      /* until end of line or end of word */
12247                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
12248                 switch (SIT(c, synstack->syntax)) {
12249                 case CNL:       /* '\n' */
12250                         if (synstack->syntax == BASESYNTAX
12251                          && !synstack->varnest
12252                         ) {
12253                                 goto endword;   /* exit outer loop */
12254                         }
12255                         USTPUTC(c, out);
12256                         nlprompt();
12257                         c = pgetc_top(synstack);
12258                         goto loop;              /* continue outer loop */
12259                 case CWORD:
12260                         USTPUTC(c, out);
12261                         break;
12262                 case CCTL:
12263 #if BASH_DOLLAR_SQUOTE
12264                         if (c == '\\' && bash_dollar_squote) {
12265                                 c = decode_dollar_squote();
12266                                 if (c == '\0') {
12267                                         /* skip $'\000', $'\x00' (like bash) */
12268                                         break;
12269                                 }
12270                                 if (c & 0x100) {
12271                                         /* Unknown escape. Encode as '\z' */
12272                                         c = (unsigned char)c;
12273                                         if (eofmark == NULL || synstack->dblquote)
12274                                                 USTPUTC(CTLESC, out);
12275                                         USTPUTC('\\', out);
12276                                 }
12277                         }
12278 #endif
12279                         if (!eofmark || synstack->dblquote || synstack->varnest)
12280                                 USTPUTC(CTLESC, out);
12281                         USTPUTC(c, out);
12282                         break;
12283                 case CBACK:     /* backslash */
12284                         c = pgetc_without_PEOA();
12285                         if (c == PEOF) {
12286                                 USTPUTC(CTLESC, out);
12287                                 USTPUTC('\\', out);
12288                                 pungetc();
12289                         } else {
12290                                 if (pssyntax && c == '$') {
12291                                         USTPUTC(CTLESC, out);
12292                                         USTPUTC('\\', out);
12293                                 }
12294                                 /* Backslash is retained if we are in "str"
12295                                  * and next char isn't dquote-special.
12296                                  */
12297                                 if (synstack->dblquote
12298                                  && c != '\\'
12299                                  && c != '`'
12300                                  && c != '$'
12301                                  && (c != '"' || (eofmark != NULL && !synstack->varnest))
12302                                  && (c != '}' || !synstack->varnest)
12303                                 ) {
12304                                         USTPUTC(CTLESC, out); /* protect '\' from glob */
12305                                         USTPUTC('\\', out);
12306                                 }
12307                                 USTPUTC(CTLESC, out);
12308                                 USTPUTC(c, out);
12309                                 quotef = 1;
12310                         }
12311                         break;
12312                 case CSQUOTE:
12313                         synstack->syntax = SQSYNTAX;
12314  quotemark:
12315                         if (eofmark == NULL) {
12316                                 USTPUTC(CTLQUOTEMARK, out);
12317                         }
12318                         break;
12319                 case CDQUOTE:
12320                         synstack->syntax = DQSYNTAX;
12321                         synstack->dblquote = 1;
12322  toggledq:
12323                         if (synstack->varnest)
12324                                 synstack->innerdq ^= 1;
12325                         goto quotemark;
12326                 case CENDQUOTE:
12327                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
12328                         if (eofmark != NULL && synstack->varnest == 0) {
12329                                 USTPUTC(c, out);
12330                                 break;
12331                         }
12332
12333                         if (synstack->dqvarnest == 0) {
12334                                 synstack->syntax = BASESYNTAX;
12335                                 synstack->dblquote = 0;
12336                         }
12337
12338                         quotef = 1;
12339
12340                         if (c == '"')
12341                                 goto toggledq;
12342
12343                         goto quotemark;
12344                 case CVAR:      /* '$' */
12345                         PARSESUB();             /* parse substitution */
12346                         break;
12347                 case CENDVAR:   /* '}' */
12348                         if (!synstack->innerdq && synstack->varnest > 0) {
12349                                 if (!--synstack->varnest && synstack->varpushed)
12350                                         synstack_pop(&synstack);
12351                                 else if (synstack->dqvarnest > 0)
12352                                         synstack->dqvarnest--;
12353                                 c = CTLENDVAR;
12354                         }
12355                         USTPUTC(c, out);
12356                         break;
12357 #if ENABLE_FEATURE_SH_MATH
12358                 case CLP:       /* '(' in arithmetic */
12359                         synstack->parenlevel++;
12360                         USTPUTC(c, out);
12361                         break;
12362                 case CRP:       /* ')' in arithmetic */
12363                         if (synstack->parenlevel > 0) {
12364                                 synstack->parenlevel--;
12365                         } else {
12366                                 if (pgetc_eatbnl() == ')') {
12367                                         c = CTLENDARI;
12368                                         synstack_pop(&synstack);
12369                                 } else {
12370                                         /*
12371                                          * unbalanced parens
12372                                          * (don't 2nd guess - no error)
12373                                          */
12374                                         pungetc();
12375                                 }
12376                         }
12377                         USTPUTC(c, out);
12378                         break;
12379 #endif
12380                 case CBQUOTE:   /* '`' */
12381                         if (checkkwd & CHKEOFMARK) {
12382                                 quotef = 1;
12383                                 USTPUTC('`', out);
12384                                 break;
12385                         }
12386
12387                         PARSEBACKQOLD();
12388                         break;
12389                 case CENDFILE:
12390                         goto endword;           /* exit outer loop */
12391                 case CIGN:
12392                         break;
12393                 default:
12394                         if (synstack->varnest == 0) {
12395 #if BASH_REDIR_OUTPUT
12396                                 if (c == '&') {
12397 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
12398                                         if (pgetc() == '>')
12399                                                 c = 0x100 + '>'; /* flag &> */
12400                                         pungetc();
12401                                 }
12402 #endif
12403                                 goto endword;   /* exit outer loop */
12404                         }
12405                         IF_ASH_ALIAS(if (c != PEOA))
12406                                 USTPUTC(c, out);
12407                 }
12408                 c = pgetc_top(synstack);
12409         } /* for (;;) */
12410  endword:
12411
12412 #if ENABLE_FEATURE_SH_MATH
12413         if (synstack->syntax == ARISYNTAX)
12414                 raise_error_syntax("missing '))'");
12415 #endif
12416         if (synstack->syntax != BASESYNTAX && eofmark == NULL)
12417                 raise_error_syntax("unterminated quoted string");
12418         if (synstack->varnest != 0) {
12419                 /* { */
12420                 raise_error_syntax("missing '}'");
12421         }
12422         USTPUTC('\0', out);
12423         len = out - (char *)stackblock();
12424         out = stackblock();
12425         if (eofmark == NULL) {
12426                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
12427                  && quotef == 0
12428                 ) {
12429                         if (isdigit_str9(out)) {
12430                                 PARSEREDIR(); /* passed as params: out, c */
12431                                 lasttoken = TREDIR;
12432                                 return lasttoken;
12433                         }
12434                         /* else: non-number X seen, interpret it
12435                          * as "NNNX>file" = "NNNX >file" */
12436                 }
12437                 pungetc();
12438         }
12439         quoteflag = quotef;
12440         backquotelist = bqlist;
12441         grabstackblock(len);
12442         wordtext = out;
12443         lasttoken = TWORD;
12444         return lasttoken;
12445 /* end of readtoken routine */
12446
12447 /*
12448  * Check to see whether we are at the end of the here document.  When this
12449  * is called, c is set to the first character of the next input line.  If
12450  * we are at the end of the here document, this routine sets the c to PEOF.
12451  */
12452 checkend: {
12453         if (realeofmark(eofmark)) {
12454                 int markloc;
12455                 char *p;
12456
12457 #if ENABLE_ASH_ALIAS
12458                 if (c == PEOA)
12459                         c = pgetc_without_PEOA();
12460 #endif
12461                 if (striptabs) {
12462                         while (c == '\t') {
12463                                 c = pgetc_without_PEOA();
12464                         }
12465                 }
12466
12467                 markloc = out - (char *)stackblock();
12468                 for (p = eofmark; STPUTC(c, out), *p; p++) {
12469                         if (c != *p)
12470                                 goto more_heredoc;
12471                         /* FIXME: fails for backslash-newlined terminator:
12472                          * cat <<EOF
12473                          * ...
12474                          * EO\
12475                          * F
12476                          * (see heredoc_bkslash_newline2.tests)
12477                          */
12478                         c = pgetc_without_PEOA();
12479                 }
12480
12481                 if (c == '\n' || c == PEOF) {
12482                         c = PEOF;
12483                         g_parsefile->linno++;
12484                         needprompt = doprompt;
12485                 } else {
12486                         int len_here;
12487
12488  more_heredoc:
12489                         p = (char *)stackblock() + markloc + 1;
12490                         len_here = out - p;
12491
12492                         if (len_here) {
12493                                 len_here -= (c >= PEOF);
12494                                 c = p[-1];
12495
12496                                 if (len_here) {
12497                                         char *str;
12498
12499                                         str = alloca(len_here + 1);
12500                                         *(char *)mempcpy(str, p, len_here) = '\0';
12501
12502                                         pushstring(str, NULL);
12503                                 }
12504                         }
12505                 }
12506
12507                 STADJUST((char *)stackblock() + markloc - out, out);
12508         }
12509         goto checkend_return;
12510 }
12511
12512 /*
12513  * Parse a redirection operator.  The variable "out" points to a string
12514  * specifying the fd to be redirected.  The variable "c" contains the
12515  * first character of the redirection operator.
12516  */
12517 parseredir: {
12518         /* out is already checked to be a valid number or "" */
12519         int fd = (*out == '\0' ? -1 : atoi(out));
12520         union node *np;
12521
12522         np = stzalloc(sizeof(struct nfile));
12523         if (c == '>') {
12524                 np->nfile.fd = 1;
12525                 c = pgetc_eatbnl();
12526                 if (c == '>')
12527                         np->type = NAPPEND;
12528                 else if (c == '|')
12529                         np->type = NCLOBBER;
12530                 else if (c == '&')
12531                         np->type = NTOFD;
12532                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12533                 else {
12534                         np->type = NTO;
12535                         pungetc();
12536                 }
12537         }
12538 #if BASH_REDIR_OUTPUT
12539         else if (c == 0x100 + '>') { /* this flags &> redirection */
12540                 np->nfile.fd = 1;
12541                 pgetc(); /* this is '>', no need to check */
12542                 np->type = NTO2;
12543         }
12544 #endif
12545         else { /* c == '<' */
12546                 /*np->nfile.fd = 0; - stzalloc did it */
12547                 c = pgetc_eatbnl();
12548                 switch (c) {
12549                 case '<':
12550                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12551                                 np = stzalloc(sizeof(struct nhere));
12552                                 /*np->nfile.fd = 0; - stzalloc did it */
12553                         }
12554                         np->type = NHERE;
12555                         heredoc = stzalloc(sizeof(struct heredoc));
12556                         heredoc->here = np;
12557                         c = pgetc_eatbnl();
12558                         if (c == '-') {
12559                                 heredoc->striptabs = 1;
12560                         } else {
12561                                 /*heredoc->striptabs = 0; - stzalloc did it */
12562                                 pungetc();
12563                         }
12564                         break;
12565
12566                 case '&':
12567                         np->type = NFROMFD;
12568                         break;
12569
12570                 case '>':
12571                         np->type = NFROMTO;
12572                         break;
12573
12574                 default:
12575                         np->type = NFROM;
12576                         pungetc();
12577                         break;
12578                 }
12579         }
12580         if (fd >= 0)
12581                 np->nfile.fd = fd;
12582         redirnode = np;
12583         goto parseredir_return;
12584 }
12585
12586 /*
12587  * Parse a substitution.  At this point, we have read the dollar sign
12588  * and nothing else.
12589  */
12590
12591 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12592  * (assuming ascii char codes, as the original implementation did) */
12593 #define is_special(c) \
12594         (((unsigned)(c) - 33 < 32) \
12595                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12596 parsesub: {
12597         unsigned char subtype;
12598         int typeloc;
12599
12600         c = pgetc_eatbnl();
12601         if ((checkkwd & CHKEOFMARK)
12602          || c > 255 /* PEOA or PEOF */
12603          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12604         ) {
12605 #if BASH_DOLLAR_SQUOTE
12606                 if (synstack->syntax != DQSYNTAX && c == '\'')
12607                         bash_dollar_squote = 1;
12608                 else
12609 #endif
12610                         USTPUTC('$', out);
12611                 pungetc();
12612         } else if (c == '(') {
12613                 /* $(command) or $((arith)) */
12614                 if (pgetc_eatbnl() == '(') {
12615 #if ENABLE_FEATURE_SH_MATH
12616                         PARSEARITH();
12617 #else
12618                         raise_error_syntax("support for $((arith)) is disabled");
12619 #endif
12620                 } else {
12621                         pungetc();
12622                         PARSEBACKQNEW();
12623                 }
12624         } else {
12625                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12626                 smalluint newsyn = synstack->syntax;
12627
12628                 USTPUTC(CTLVAR, out);
12629                 typeloc = out - (char *)stackblock();
12630                 STADJUST(1, out);
12631                 subtype = VSNORMAL;
12632                 if (c == '{') {
12633                         c = pgetc_eatbnl();
12634                         subtype = 0;
12635                 }
12636  varname:
12637                 if (is_name(c)) {
12638                         /* $[{[#]]NAME[}] */
12639                         do {
12640                                 STPUTC(c, out);
12641                                 c = pgetc_eatbnl();
12642                         } while (is_in_name(c));
12643                 } else if (isdigit(c)) {
12644                         /* $[{[#]]NUM[}] */
12645                         do {
12646                                 STPUTC(c, out);
12647                                 c = pgetc_eatbnl();
12648                         } while (!subtype && isdigit(c));
12649                 } else if (c != '}') {
12650                         /* $[{[#]]<specialchar>[}] */
12651                         int cc = c;
12652
12653                         c = pgetc_eatbnl();
12654                         if (!subtype && cc == '#') {
12655                                 subtype = VSLENGTH;
12656                                 if (c == '_' || isalnum(c))
12657                                         goto varname;
12658                                 cc = c;
12659                                 c = pgetc_eatbnl();
12660                                 if (cc == '}' || c != '}') {
12661                                         pungetc();
12662                                         subtype = 0;
12663                                         c = cc;
12664                                         cc = '#';
12665                                 }
12666                         }
12667
12668                         if (!is_special(cc)) {
12669                                 if (subtype == VSLENGTH)
12670                                         subtype = 0;
12671                                 goto badsub;
12672                         }
12673
12674                         USTPUTC(cc, out);
12675                 } else
12676                         goto badsub;
12677
12678                 if (c != '}' && subtype == VSLENGTH) {
12679                         /* ${#VAR didn't end with } */
12680                         goto badsub;
12681                 }
12682
12683                 if (subtype == 0) {
12684                         static const char types[] ALIGN1 = "}-+?=";
12685                         /* ${VAR...} but not $VAR or ${#VAR} */
12686                         /* c == first char after VAR */
12687                         int cc = c;
12688
12689                         switch (c) {
12690                         case ':':
12691                                 c = pgetc_eatbnl();
12692 #if BASH_SUBSTR
12693                                 /* This check is only needed to not misinterpret
12694                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12695                                  * constructs.
12696                                  */
12697                                 if (!strchr(types, c)) {
12698                                         subtype = VSSUBSTR;
12699                                         pungetc();
12700                                         break; /* "goto badsub" is bigger (!) */
12701                                 }
12702 #endif
12703                                 subtype = VSNUL;
12704                                 /*FALLTHROUGH*/
12705                         default: {
12706                                 const char *p = strchr(types, c);
12707                                 if (p == NULL)
12708                                         break;
12709                                 subtype |= p - types + VSNORMAL;
12710                                 break;
12711                         }
12712                         case '%':
12713                         case '#':
12714                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12715                                 c = pgetc_eatbnl();
12716                                 if (c == cc)
12717                                         subtype++;
12718                                 else
12719                                         pungetc();
12720
12721                                 newsyn = BASESYNTAX;
12722                                 break;
12723 #if BASH_PATTERN_SUBST
12724                         case '/':
12725                                 /* ${v/[/]pattern/repl} */
12726 //TODO: encode pattern and repl separately.
12727 // Currently cases like: v=1;echo ${v/$((1/1))/ONE}
12728 // are broken (should print "ONE")
12729                                 subtype = VSREPLACE;
12730                                 newsyn = BASESYNTAX;
12731                                 c = pgetc_eatbnl();
12732                                 if (c != '/')
12733                                         goto badsub;
12734                                 subtype++; /* VSREPLACEALL */
12735                                 break;
12736 #endif
12737                         }
12738                 } else {
12739  badsub:
12740                         pungetc();
12741                 }
12742
12743                 if (newsyn == ARISYNTAX)
12744                         newsyn = DQSYNTAX;
12745
12746                 if ((newsyn != synstack->syntax || synstack->innerdq)
12747                  && subtype != VSNORMAL
12748                 ) {
12749                         synstack_push(&synstack,
12750                                 synstack->prev ?: alloca(sizeof(*synstack)),
12751                                 newsyn);
12752
12753                         synstack->varpushed = 1;
12754                         synstack->dblquote = newsyn != BASESYNTAX;
12755                 }
12756
12757                 ((unsigned char *)stackblock())[typeloc] = subtype;
12758                 if (subtype != VSNORMAL) {
12759                         synstack->varnest++;
12760                         if (synstack->dblquote)
12761                                 synstack->dqvarnest++;
12762                 }
12763                 STPUTC('=', out);
12764         }
12765         goto parsesub_return;
12766 }
12767
12768 /*
12769  * Called to parse command substitutions.  Newstyle is set if the command
12770  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12771  * list of commands (passed by reference), and savelen is the number of
12772  * characters on the top of the stack which must be preserved.
12773  */
12774 parsebackq: {
12775         struct nodelist **nlpp;
12776         union node *n;
12777         char *str;
12778         size_t savelen;
12779         struct heredoc *saveheredoclist;
12780         smallint saveprompt = 0;
12781
12782         str = NULL;
12783         savelen = out - (char *)stackblock();
12784         if (savelen > 0) {
12785                 /*
12786                  * FIXME: this can allocate very large block on stack and SEGV.
12787                  * Example:
12788                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12789                  * allocates 100kb for every command subst. With about
12790                  * a hundred command substitutions stack overflows.
12791                  * With larger prepended string, SEGV happens sooner.
12792                  */
12793                 str = alloca(savelen);
12794                 memcpy(str, stackblock(), savelen);
12795         }
12796
12797         if (oldstyle) {
12798                 /* We must read until the closing backquote, giving special
12799                  * treatment to some slashes, and then push the string and
12800                  * reread it as input, interpreting it normally.
12801                  */
12802                 char *pout;
12803                 size_t psavelen;
12804                 char *pstr;
12805
12806                 STARTSTACKSTR(pout);
12807                 for (;;) {
12808                         int pc;
12809
12810                         setprompt_if(needprompt, 2);
12811                         pc = pgetc_eatbnl();
12812                         switch (pc) {
12813                         case '`':
12814                                 goto done;
12815
12816                         case '\\':
12817                                 pc = pgetc(); /* or pgetc_eatbnl()? why (example)? */
12818                                 if (pc != '\\' && pc != '`' && pc != '$'
12819                                  && (!synstack->dblquote || pc != '"')
12820                                 ) {
12821                                         STPUTC('\\', pout);
12822                                 }
12823                                 if (pc <= 255 /* not PEOA or PEOF */) {
12824                                         break;
12825                                 }
12826                                 /* fall through */
12827
12828                         case PEOF:
12829                         IF_ASH_ALIAS(case PEOA:)
12830                                 raise_error_syntax("EOF in backquote substitution");
12831
12832                         case '\n':
12833                                 nlnoprompt();
12834                                 break;
12835
12836                         default:
12837                                 break;
12838                         }
12839                         STPUTC(pc, pout);
12840                 }
12841  done:
12842                 STPUTC('\0', pout);
12843                 psavelen = pout - (char *)stackblock();
12844                 if (psavelen > 0) {
12845                         pstr = grabstackstr(pout);
12846                         setinputstring(pstr);
12847                 }
12848         }
12849         nlpp = &bqlist;
12850         while (*nlpp)
12851                 nlpp = &(*nlpp)->next;
12852         *nlpp = stzalloc(sizeof(**nlpp));
12853         /* (*nlpp)->next = NULL; - stzalloc did it */
12854
12855         saveheredoclist = heredoclist;
12856         heredoclist = NULL;
12857
12858         if (oldstyle) {
12859                 saveprompt = doprompt;
12860                 doprompt = 0;
12861         }
12862
12863         n = list(2);
12864
12865         if (oldstyle)
12866                 doprompt = saveprompt;
12867         else {
12868                 if (readtoken() != TRP)
12869                         raise_error_unexpected_syntax(TRP);
12870                 setinputstring(nullstr);
12871                 parseheredoc();
12872         }
12873
12874         heredoclist = saveheredoclist;
12875
12876         (*nlpp)->n = n;
12877         /* Start reading from old file again. */
12878         popfile();
12879         /* Ignore any pushed back tokens left from the backquote parsing. */
12880         if (oldstyle)
12881                 tokpushback = 0;
12882         out = growstackto(savelen + 1);
12883         if (str) {
12884                 memcpy(out, str, savelen);
12885                 STADJUST(savelen, out);
12886         }
12887         USTPUTC(CTLBACKQ, out);
12888         if (oldstyle)
12889                 goto parsebackq_oldreturn;
12890         goto parsebackq_newreturn;
12891 }
12892
12893 #if ENABLE_FEATURE_SH_MATH
12894 /*
12895  * Parse an arithmetic expansion (indicate start of one and set state)
12896  */
12897 parsearith: {
12898
12899         synstack_push(&synstack,
12900                         synstack->prev ?: alloca(sizeof(*synstack)),
12901                         ARISYNTAX);
12902         synstack->dblquote = 1;
12903         USTPUTC(CTLARI, out);
12904         goto parsearith_return;
12905 }
12906 #endif
12907 } /* end of readtoken */
12908
12909 /*
12910  * Read the next input token.
12911  * If the token is a word, we set backquotelist to the list of cmds in
12912  *      backquotes.  We set quoteflag to true if any part of the word was
12913  *      quoted.
12914  * If the token is TREDIR, then we set redirnode to a structure containing
12915  *      the redirection.
12916  *
12917  * [Change comment:  here documents and internal procedures]
12918  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12919  *  word parsing code into a separate routine.  In this case, readtoken
12920  *  doesn't need to have any internal procedures, but parseword does.
12921  *  We could also make parseoperator in essence the main routine, and
12922  *  have parseword (readtoken1?) handle both words and redirection.]
12923  */
12924 #define NEW_xxreadtoken
12925 #ifdef NEW_xxreadtoken
12926 /* singles must be first! */
12927 static const char xxreadtoken_chars[7] ALIGN1 = {
12928         '\n', '(', ')', /* singles */
12929         '&', '|', ';',  /* doubles */
12930         0
12931 };
12932
12933 #define xxreadtoken_singles 3
12934 #define xxreadtoken_doubles 3
12935
12936 static const char xxreadtoken_tokens[] ALIGN1 = {
12937         TNL, TLP, TRP,          /* only single occurrence allowed */
12938         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12939         TEOF,                   /* corresponds to trailing nul */
12940         TAND, TOR, TENDCASE     /* if double occurrence */
12941 };
12942
12943 static int
12944 xxreadtoken(void)
12945 {
12946         int c;
12947
12948         if (tokpushback) {
12949                 tokpushback = 0;
12950                 return lasttoken;
12951         }
12952         setprompt_if(needprompt, 2);
12953         for (;;) {                      /* until token or start of word found */
12954                 c = pgetc_eatbnl();
12955                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12956                         continue;
12957
12958                 if (c == '#') {
12959                         while ((c = pgetc()) != '\n' && c != PEOF)
12960                                 continue;
12961                         pungetc();
12962                 } else if (c == '\\') {
12963                         break; /* return readtoken1(...) */
12964                 } else {
12965                         const char *p;
12966
12967                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12968                         if (c != PEOF) {
12969                                 if (c == '\n') {
12970                                         nlnoprompt();
12971                                 }
12972
12973                                 p = strchr(xxreadtoken_chars, c);
12974                                 if (p == NULL)
12975                                         break; /* return readtoken1(...) */
12976
12977                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12978                                         int cc = pgetc_eatbnl();
12979                                         if (cc == c) {    /* double occurrence? */
12980                                                 p += xxreadtoken_doubles + 1;
12981                                         } else {
12982                                                 pungetc();
12983 #if BASH_REDIR_OUTPUT
12984                                                 if (c == '&' && cc == '>') /* &> */
12985                                                         break; /* return readtoken1(...) */
12986 #endif
12987                                         }
12988                                 }
12989                         }
12990                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12991                         return lasttoken;
12992                 }
12993         } /* for (;;) */
12994
12995         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12996 }
12997 #else /* old xxreadtoken */
12998 #define RETURN(token)   return lasttoken = token
12999 static int
13000 xxreadtoken(void)
13001 {
13002         int c;
13003
13004         if (tokpushback) {
13005                 tokpushback = 0;
13006                 return lasttoken;
13007         }
13008         setprompt_if(needprompt, 2);
13009         for (;;) {      /* until token or start of word found */
13010                 c = pgetc_eatbnl();
13011                 switch (c) {
13012                 case ' ': case '\t':
13013                 IF_ASH_ALIAS(case PEOA:)
13014                         continue;
13015                 case '#':
13016                         while ((c = pgetc()) != '\n' && c != PEOF)
13017                                 continue;
13018                         pungetc();
13019                         continue;
13020                 case '\n':
13021                         nlnoprompt();
13022                         RETURN(TNL);
13023                 case PEOF:
13024                         RETURN(TEOF);
13025                 case '&':
13026                         if (pgetc_eatbnl() == '&')
13027                                 RETURN(TAND);
13028                         pungetc();
13029                         RETURN(TBACKGND);
13030                 case '|':
13031                         if (pgetc_eatbnl() == '|')
13032                                 RETURN(TOR);
13033                         pungetc();
13034                         RETURN(TPIPE);
13035                 case ';':
13036                         if (pgetc_eatbnl() == ';')
13037                                 RETURN(TENDCASE);
13038                         pungetc();
13039                         RETURN(TSEMI);
13040                 case '(':
13041                         RETURN(TLP);
13042                 case ')':
13043                         RETURN(TRP);
13044                 }
13045                 break;
13046         }
13047         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
13048 #undef RETURN
13049 }
13050 #endif /* old xxreadtoken */
13051
13052 static int
13053 readtoken(void)
13054 {
13055         int t;
13056         int kwd = checkkwd;
13057 #if DEBUG
13058         smallint alreadyseen = tokpushback;
13059 #endif
13060
13061 #if ENABLE_ASH_ALIAS
13062  top:
13063 #endif
13064
13065         t = xxreadtoken();
13066
13067         /*
13068          * eat newlines
13069          */
13070         if (kwd & CHKNL) {
13071                 while (t == TNL) {
13072                         parseheredoc();
13073                         t = xxreadtoken();
13074                 }
13075         }
13076
13077         if (t != TWORD || quoteflag) {
13078                 goto out;
13079         }
13080
13081         /*
13082          * check for keywords
13083          */
13084         if (kwd & CHKKWD) {
13085                 const char *const *pp;
13086
13087                 pp = findkwd(wordtext);
13088                 if (pp) {
13089                         lasttoken = t = pp - tokname_array;
13090                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
13091                         goto out;
13092                 }
13093         }
13094
13095         if (checkkwd & CHKALIAS) {
13096 #if ENABLE_ASH_ALIAS
13097                 struct alias *ap;
13098                 ap = lookupalias(wordtext, 1);
13099                 if (ap != NULL) {
13100                         if (*ap->val) {
13101                                 pushstring(ap->val, ap);
13102                         }
13103                         goto top;
13104                 }
13105 #endif
13106         }
13107  out:
13108         checkkwd = 0;
13109 #if DEBUG
13110         if (!alreadyseen)
13111                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
13112         else
13113                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
13114 #endif
13115         return t;
13116 }
13117
13118 static int
13119 peektoken(void)
13120 {
13121         int t;
13122
13123         t = readtoken();
13124         tokpushback = 1;
13125         return t;
13126 }
13127
13128 /*
13129  * Read and parse a command.  Returns NODE_EOF on end of file.
13130  * (NULL is a valid parse tree indicating a blank line.)
13131  */
13132 static union node *
13133 parsecmd(int interact)
13134 {
13135         tokpushback = 0;
13136         checkkwd = 0;
13137         heredoclist = 0;
13138         doprompt = interact;
13139         setprompt_if(doprompt, doprompt);
13140         needprompt = 0;
13141         return list(1);
13142 }
13143
13144 /*
13145  * Input any here documents.
13146  */
13147 static void
13148 parseheredoc(void)
13149 {
13150         struct heredoc *here;
13151         union node *n;
13152
13153         here = heredoclist;
13154         heredoclist = NULL;
13155
13156         while (here) {
13157                 tokpushback = 0;
13158                 setprompt_if(needprompt, 2);
13159                 if (here->here->type == NHERE)
13160                         readtoken1(pgetc(), SQSYNTAX, here->eofmark, here->striptabs);
13161                 else
13162                         readtoken1(pgetc_eatbnl(), DQSYNTAX, here->eofmark, here->striptabs);
13163                 n = stzalloc(sizeof(struct narg));
13164                 n->narg.type = NARG;
13165                 /*n->narg.next = NULL; - stzalloc did it */
13166                 n->narg.text = wordtext;
13167                 n->narg.backquote = backquotelist;
13168                 here->here->nhere.doc = n;
13169                 here = here->next;
13170         }
13171 }
13172
13173
13174 static const char *
13175 expandstr(const char *ps, int syntax_type)
13176 {
13177         union node n;
13178         int saveprompt;
13179         struct parsefile *file_stop = g_parsefile;
13180         volatile int saveint;
13181         struct jmploc *volatile savehandler = exception_handler;
13182         struct jmploc jmploc;
13183         const char *volatile result;
13184         int err;
13185
13186         /* XXX Fix (char *) cast. */
13187         setinputstring((char *)ps);
13188
13189         saveprompt = doprompt;
13190         doprompt = 0;
13191         result = ps;
13192
13193         SAVE_INT(saveint);
13194         err = setjmp(jmploc.loc);
13195         if (err)
13196                 goto out;
13197
13198         /* readtoken1() might die horribly.
13199          * Try a prompt with syntactically wrong command:
13200          * PS1='$(date "+%H:%M:%S) > '
13201          */
13202         exception_handler = &jmploc;
13203         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
13204
13205         n.narg.type = NARG;
13206         n.narg.next = NULL;
13207         n.narg.text = wordtext;
13208         n.narg.backquote = backquotelist;
13209
13210         /* expandarg() might fail too:
13211          * PS1='$((123+))'
13212          */
13213         expandarg(&n, NULL, EXP_QUOTED);
13214         result = stackblock();
13215
13216 out:
13217         exception_handler = savehandler;
13218         if (err && exception_type != EXERROR)
13219                 longjmp(exception_handler->loc, 1);
13220         RESTORE_INT(saveint);
13221
13222         doprompt = saveprompt;
13223         /* Try: PS1='`xxx(`' */
13224         unwindfiles(file_stop);
13225
13226         return result;
13227 }
13228
13229 static inline int
13230 parser_eof(void)
13231 {
13232         return tokpushback && lasttoken == TEOF;
13233 }
13234
13235 /*
13236  * Execute a command or commands contained in a string.
13237  */
13238 static int
13239 evalstring(char *s, int flags)
13240 {
13241         struct jmploc *volatile savehandler;
13242         struct jmploc jmploc;
13243         int ex;
13244
13245         union node *n;
13246         struct stackmark smark;
13247         int status;
13248
13249         s = sstrdup(s);
13250         setinputstring(s);
13251         setstackmark(&smark);
13252
13253         status = 0;
13254         /* On exception inside execution loop, we must popfile().
13255          * Try interactively:
13256          *      readonly a=a
13257          *      command eval "a=b"  # throws "is read only" error
13258          * "command BLTIN" is not supposed to abort (even in non-interactive use).
13259          * But if we skip popfile(), we hit EOF in eval's string, and exit.
13260          */
13261         savehandler = exception_handler;
13262         ex = setjmp(jmploc.loc);
13263         if (ex)
13264                 goto out;
13265         exception_handler = &jmploc;
13266
13267         while ((n = parsecmd(0)) != NODE_EOF) {
13268                 int i;
13269
13270                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
13271                 if (n)
13272                         status = i;
13273                 popstackmark(&smark);
13274                 if (evalskip)
13275                         break;
13276         }
13277  out:
13278         popstackmark(&smark);
13279         popfile();
13280         stunalloc(s);
13281
13282         exception_handler = savehandler;
13283         if (ex)
13284                 longjmp(exception_handler->loc, ex);
13285
13286         return status;
13287 }
13288
13289 /*
13290  * The eval command.
13291  */
13292 static int FAST_FUNC
13293 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
13294 {
13295         char *p;
13296         char *concat;
13297
13298         if (argv[1]) {
13299                 p = argv[1];
13300                 argv += 2;
13301                 if (argv[0]) {
13302                         STARTSTACKSTR(concat);
13303                         for (;;) {
13304                                 concat = stack_putstr(p, concat);
13305                                 p = *argv++;
13306                                 if (p == NULL)
13307                                         break;
13308                                 STPUTC(' ', concat);
13309                         }
13310                         STPUTC('\0', concat);
13311                         p = grabstackstr(concat);
13312                 }
13313                 return evalstring(p, flags & EV_TESTED);
13314         }
13315         return 0;
13316 }
13317
13318 /*
13319  * Read and execute commands.
13320  * "Top" is nonzero for the top level command loop;
13321  * it turns on prompting if the shell is interactive.
13322  */
13323 static int
13324 cmdloop(int top)
13325 {
13326         union node *n;
13327         struct stackmark smark;
13328         int inter;
13329         int status = 0;
13330         int numeof = 0;
13331
13332         TRACE(("cmdloop(%d) called\n", top));
13333         for (;;) {
13334                 int skip;
13335
13336                 setstackmark(&smark);
13337 #if JOBS
13338                 if (doing_jobctl)
13339                         showjobs(SHOW_CHANGED|SHOW_STDERR);
13340 #endif
13341                 inter = 0;
13342                 if (iflag && top) {
13343                         inter++;
13344                         chkmail();
13345                 }
13346                 n = parsecmd(inter);
13347 #if DEBUG
13348                 if (DEBUG > 2 && debug && (n != NODE_EOF))
13349                         showtree(n);
13350 #endif
13351                 if (n == NODE_EOF) {
13352                         if (!top || numeof >= 50)
13353                                 break;
13354                         if (!stoppedjobs()) {
13355                                 if (!Iflag) {
13356                                         if (iflag) {
13357                                                 newline_and_flush(stderr);
13358                                         }
13359                                         break;
13360                                 }
13361                                 out2str("\nUse \"exit\" to leave shell.\n");
13362                         }
13363                         numeof++;
13364                 } else if (nflag == 0) {
13365                         int i;
13366
13367                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
13368                         job_warning >>= 1;
13369                         numeof = 0;
13370                         i = evaltree(n, 0);
13371                         if (n)
13372                                 status = i;
13373                 }
13374                 popstackmark(&smark);
13375                 skip = evalskip;
13376
13377                 if (skip) {
13378                         evalskip &= ~SKIPFUNC;
13379                         break;
13380                 }
13381         }
13382         return status;
13383 }
13384
13385 /*
13386  * Take commands from a file.  To be compatible we should do a path
13387  * search for the file, which is necessary to find sub-commands.
13388  */
13389 static char *
13390 find_dot_file(char *basename)
13391 {
13392         char *fullname;
13393         const char *path = pathval();
13394         struct stat statb;
13395         int len;
13396
13397         /* don't try this for absolute or relative paths */
13398         if (strchr(basename, '/'))
13399                 return basename;
13400
13401         while ((len = padvance(&path, basename)) >= 0) {
13402                 fullname = stackblock();
13403                 if ((!pathopt || *pathopt == 'f')
13404                  && !stat(fullname, &statb) && S_ISREG(statb.st_mode)
13405                 ) {
13406                         /* This will be freed by the caller. */
13407                         return stalloc(len);
13408                 }
13409         }
13410         /* not found in PATH */
13411
13412 #if ENABLE_ASH_BASH_SOURCE_CURDIR
13413         return basename;
13414 #else
13415         ash_msg_and_raise_error("%s: not found", basename);
13416         /* NOTREACHED */
13417 #endif
13418 }
13419
13420 static int FAST_FUNC
13421 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
13422 {
13423         /* "false; . empty_file; echo $?" should print 0, not 1: */
13424         int status = 0;
13425         char *fullname;
13426         char **argv;
13427         char *args_need_save;
13428         volatile struct shparam saveparam;
13429
13430 //???
13431 //      struct strlist *sp;
13432 //      for (sp = cmdenviron; sp; sp = sp->next)
13433 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
13434
13435         nextopt(nullstr); /* handle possible "--" */
13436         argv = argptr;
13437
13438         if (!argv[0]) {
13439                 /* bash says: "bash: .: filename argument required" */
13440                 return 2; /* bash compat */
13441         }
13442
13443         /* This aborts if file isn't found, which is POSIXly correct.
13444          * bash returns exitcode 1 instead.
13445          */
13446         fullname = find_dot_file(argv[0]);
13447         argv++;
13448         args_need_save = argv[0];
13449         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
13450                 int argc;
13451                 saveparam = shellparam;
13452                 shellparam.malloced = 0;
13453                 argc = 1;
13454                 while (argv[argc])
13455                         argc++;
13456                 shellparam.nparam = argc;
13457                 shellparam.p = argv;
13458         };
13459
13460         /* This aborts if file can't be opened, which is POSIXly correct.
13461          * bash returns exitcode 1 instead.
13462          */
13463         setinputfile(fullname, INPUT_PUSH_FILE);
13464         commandname = fullname;
13465         status = cmdloop(0);
13466         popfile();
13467
13468         if (args_need_save) {
13469                 freeparam(&shellparam);
13470                 shellparam = saveparam;
13471         };
13472
13473         return status;
13474 }
13475
13476 static int FAST_FUNC
13477 exitcmd(int argc UNUSED_PARAM, char **argv)
13478 {
13479         if (stoppedjobs())
13480                 return 0;
13481
13482         if (argv[1])
13483                 savestatus = number(argv[1]);
13484
13485         raise_exception(EXEXIT);
13486         /* NOTREACHED */
13487 }
13488
13489 /*
13490  * Read a file containing shell functions.
13491  */
13492 static void
13493 readcmdfile(char *name)
13494 {
13495         setinputfile(name, INPUT_PUSH_FILE);
13496         cmdloop(0);
13497         popfile();
13498 }
13499
13500
13501 /* ============ find_command inplementation */
13502
13503 /*
13504  * Resolve a command name.  If you change this routine, you may have to
13505  * change the shellexec routine as well.
13506  */
13507 static void
13508 find_command(char *name, struct cmdentry *entry, int act, const char *path)
13509 {
13510         struct tblentry *cmdp;
13511         int idx;
13512         int prev;
13513         char *fullname;
13514         struct stat statb;
13515         int e;
13516         int updatetbl;
13517         struct builtincmd *bcmd;
13518         int len;
13519
13520         /* If name contains a slash, don't use PATH or hash table */
13521         if (strchr(name, '/') != NULL) {
13522                 entry->u.index = -1;
13523                 if (act & DO_ABS) {
13524                         while (stat(name, &statb) < 0) {
13525 #ifdef SYSV
13526                                 if (errno == EINTR)
13527                                         continue;
13528 #endif
13529                                 entry->cmdtype = CMDUNKNOWN;
13530                                 return;
13531                         }
13532                 }
13533                 entry->cmdtype = CMDNORMAL;
13534                 return;
13535         }
13536
13537 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
13538
13539         updatetbl = (path == pathval());
13540         if (!updatetbl) {
13541                 act |= DO_ALTPATH;
13542                 if (strstr(path, "%builtin") != NULL)
13543                         act |= DO_ALTBLTIN;
13544         }
13545
13546         /* If name is in the table, check answer will be ok */
13547         cmdp = cmdlookup(name, 0);
13548         if (cmdp != NULL) {
13549                 int bit;
13550
13551                 switch (cmdp->cmdtype) {
13552                 default:
13553 #if DEBUG
13554                         abort();
13555 #endif
13556                 case CMDNORMAL:
13557                         bit = DO_ALTPATH;
13558                         break;
13559                 case CMDFUNCTION:
13560                         bit = DO_NOFUNC;
13561                         break;
13562                 case CMDBUILTIN:
13563                         bit = IS_BUILTIN_REGULAR(cmdp->param.cmd) ? 0 : DO_ALTBLTIN;
13564                         break;
13565                 }
13566                 if (act & bit) {
13567                         updatetbl = 0;
13568                         cmdp = NULL;
13569                 } else if (cmdp->rehash == 0)
13570                         /* if not invalidated by cd, we're done */
13571                         goto success;
13572         }
13573
13574         /* If %builtin not in path, check for builtin next */
13575         bcmd = find_builtin(name);
13576         if (bcmd) {
13577                 if (IS_BUILTIN_REGULAR(bcmd))
13578                         goto builtin_success;
13579                 if (act & DO_ALTPATH) {
13580                         if (!(act & DO_ALTBLTIN))
13581                                 goto builtin_success;
13582                 } else if (builtinloc <= 0) {
13583                         goto builtin_success;
13584                 }
13585         }
13586
13587 #if ENABLE_FEATURE_SH_STANDALONE
13588         {
13589                 int applet_no = find_applet_by_name(name);
13590                 if (applet_no >= 0) {
13591                         entry->cmdtype = CMDNORMAL;
13592                         entry->u.index = -2 - applet_no;
13593                         return;
13594                 }
13595         }
13596 #endif
13597
13598         /* We have to search path. */
13599         prev = -1;              /* where to start */
13600         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13601                 if (cmdp->cmdtype == CMDBUILTIN)
13602                         prev = builtinloc;
13603                 else
13604                         prev = cmdp->param.index;
13605         }
13606
13607         e = ENOENT;
13608         idx = -1;
13609  loop:
13610         while ((len = padvance(&path, name)) >= 0) {
13611                 const char *lpathopt = pathopt;
13612
13613                 fullname = stackblock();
13614                 idx++;
13615                 if (lpathopt) {
13616                         if (*lpathopt == 'b') {
13617                                 if (bcmd)
13618                                         goto builtin_success;
13619                                 continue;
13620                         } else if (!(act & DO_NOFUNC)) {
13621                                 /* handled below */
13622                         } else {
13623                                 /* ignore unimplemented options */
13624                                 continue;
13625                         }
13626                 }
13627                 /* if rehash, don't redo absolute path names */
13628                 if (fullname[0] == '/' && idx <= prev) {
13629                         if (idx < prev)
13630                                 continue;
13631                         TRACE(("searchexec \"%s\": no change\n", name));
13632                         goto success;
13633                 }
13634                 while (stat(fullname, &statb) < 0) {
13635 #ifdef SYSV
13636                         if (errno == EINTR)
13637                                 continue;
13638 #endif
13639                         if (errno != ENOENT && errno != ENOTDIR)
13640                                 e = errno;
13641                         goto loop;
13642                 }
13643                 e = EACCES;     /* if we fail, this will be the error */
13644                 if (!S_ISREG(statb.st_mode))
13645                         continue;
13646                 if (lpathopt) {          /* this is a %func directory */
13647                         stalloc(len);
13648                         /* NB: stalloc will return space pointed by fullname
13649                          * (because we don't have any intervening allocations
13650                          * between stunalloc above and this stalloc) */
13651                         readcmdfile(fullname);
13652                         cmdp = cmdlookup(name, 0);
13653                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13654                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13655                         stunalloc(fullname);
13656                         goto success;
13657                 }
13658                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13659                 if (!updatetbl) {
13660                         entry->cmdtype = CMDNORMAL;
13661                         entry->u.index = idx;
13662                         return;
13663                 }
13664                 INT_OFF;
13665                 cmdp = cmdlookup(name, 1);
13666                 cmdp->cmdtype = CMDNORMAL;
13667                 cmdp->param.index = idx;
13668                 INT_ON;
13669                 goto success;
13670         }
13671
13672         /* We failed.  If there was an entry for this command, delete it */
13673         if (cmdp && updatetbl)
13674                 delete_cmd_entry();
13675         if (act & DO_ERR) {
13676 #if ENABLE_ASH_BASH_NOT_FOUND_HOOK
13677                 struct tblentry *hookp = cmdlookup("command_not_found_handle", 0);
13678                 if (hookp && hookp->cmdtype == CMDFUNCTION) {
13679                         char *argv[3];
13680                         argv[0] = (char*) "command_not_found_handle";
13681                         argv[1] = name;
13682                         argv[2] = NULL;
13683                         evalfun(hookp->param.func, 2, argv, 0);
13684                         entry->cmdtype = CMDUNKNOWN;
13685                         return;
13686                 }
13687 #endif
13688                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13689         }
13690         entry->cmdtype = CMDUNKNOWN;
13691         return;
13692
13693  builtin_success:
13694         if (!updatetbl) {
13695                 entry->cmdtype = CMDBUILTIN;
13696                 entry->u.cmd = bcmd;
13697                 return;
13698         }
13699         INT_OFF;
13700         cmdp = cmdlookup(name, 1);
13701         cmdp->cmdtype = CMDBUILTIN;
13702         cmdp->param.cmd = bcmd;
13703         INT_ON;
13704  success:
13705         cmdp->rehash = 0;
13706         entry->cmdtype = cmdp->cmdtype;
13707         entry->u = cmdp->param;
13708 }
13709
13710
13711 /*
13712  * The trap builtin.
13713  */
13714 static int FAST_FUNC
13715 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13716 {
13717         char *action;
13718         char **ap;
13719         int signo, exitcode;
13720
13721         nextopt(nullstr);
13722         ap = argptr;
13723         if (!*ap) {
13724                 for (signo = 0; signo < NSIG; signo++) {
13725                         char *tr = trap_ptr[signo];
13726                         if (tr) {
13727                                 /* note: bash adds "SIG", but only if invoked
13728                                  * as "bash". If called as "sh", or if set -o posix,
13729                                  * then it prints short signal names.
13730                                  * We are printing short names: */
13731                                 out1fmt("trap -- %s %s\n",
13732                                                 single_quote(tr),
13733                                                 get_signame(signo));
13734                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13735                  * In this case, we will exit very soon, no need to free(). */
13736                                 /* if (trap_ptr != trap && tp[0]) */
13737                                 /*      free(tr); */
13738                         }
13739                 }
13740                 /*
13741                 if (trap_ptr != trap) {
13742                         free(trap_ptr);
13743                         trap_ptr = trap;
13744                 }
13745                 */
13746                 return 0;
13747         }
13748
13749         /* Why the second check?
13750          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13751          * In this case, NUM is signal no, not an action.
13752          */
13753         action = NULL;
13754         if (ap[1] && !is_number(ap[0]))
13755                 action = *ap++;
13756
13757         exitcode = 0;
13758         while (*ap) {
13759                 signo = get_signum(*ap);
13760                 if (signo < 0) {
13761                         /* Mimic bash message exactly */
13762                         ash_msg("%s: invalid signal specification", *ap);
13763                         exitcode = 1;
13764                         goto next;
13765                 }
13766                 INT_OFF;
13767                 if (action) {
13768                         if (LONE_DASH(action))
13769                                 action = NULL;
13770                         else {
13771                                 if (action[0]) /* not NULL and not "" and not "-" */
13772                                         may_have_traps = 1;
13773                                 action = ckstrdup(action);
13774                         }
13775                 }
13776                 free(trap[signo]);
13777                 trap[signo] = action;
13778                 if (signo != 0)
13779                         setsignal(signo);
13780                 INT_ON;
13781  next:
13782                 ap++;
13783         }
13784         return exitcode;
13785 }
13786
13787
13788 /* ============ Builtins */
13789
13790 #if ENABLE_ASH_HELP
13791 static int FAST_FUNC
13792 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13793 {
13794         unsigned col;
13795         unsigned i;
13796
13797         out1fmt(
13798                 "Built-in commands:\n"
13799                 "------------------\n");
13800         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13801                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13802                                         builtintab[i].name + 1);
13803                 if (col > 60) {
13804                         out1fmt("\n");
13805                         col = 0;
13806                 }
13807         }
13808 # if ENABLE_FEATURE_SH_STANDALONE
13809         {
13810                 const char *a = applet_names;
13811                 while (*a) {
13812                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13813                         if (col > 60) {
13814                                 out1fmt("\n");
13815                                 col = 0;
13816                         }
13817                         while (*a++ != '\0')
13818                                 continue;
13819                 }
13820         }
13821 # endif
13822         newline_and_flush(stdout);
13823         return EXIT_SUCCESS;
13824 }
13825 #endif
13826
13827 #if MAX_HISTORY
13828 static int FAST_FUNC
13829 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13830 {
13831         if (line_input_state)
13832                 show_history(line_input_state);
13833         return EXIT_SUCCESS;
13834 }
13835 #endif
13836
13837 /*
13838  * The export and readonly commands.
13839  */
13840 static int FAST_FUNC
13841 exportcmd(int argc UNUSED_PARAM, char **argv)
13842 {
13843         struct var *vp;
13844         char *name;
13845         const char *p;
13846         char **aptr;
13847         char opt;
13848         int flag;
13849         int flag_off;
13850
13851         /* "readonly" in bash accepts, but ignores -n.
13852          * We do the same: it saves a conditional in nextopt's param.
13853          */
13854         flag_off = 0;
13855         while ((opt = nextopt("np")) != '\0') {
13856                 if (opt == 'n')
13857                         flag_off = VEXPORT;
13858         }
13859         flag = VEXPORT;
13860         if (argv[0][0] == 'r') {
13861                 flag = VREADONLY;
13862                 flag_off = 0; /* readonly ignores -n */
13863         }
13864         flag_off = ~flag_off;
13865
13866         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13867         {
13868                 aptr = argptr;
13869                 name = *aptr;
13870                 if (name) {
13871                         do {
13872                                 p = strchr(name, '=');
13873                                 if (p != NULL) {
13874                                         p++;
13875                                 } else {
13876                                         vp = *findvar(hashvar(name), name);
13877                                         if (vp) {
13878                                                 vp->flags = ((vp->flags | flag) & flag_off);
13879                                                 continue;
13880                                         }
13881                                 }
13882                                 setvar(name, p, (flag & flag_off));
13883                         } while ((name = *++aptr) != NULL);
13884                         return 0;
13885                 }
13886         }
13887
13888         /* No arguments. Show the list of exported or readonly vars.
13889          * -n is ignored.
13890          */
13891         showvars(argv[0], flag, 0);
13892         return 0;
13893 }
13894
13895 /*
13896  * Delete a function if it exists.
13897  */
13898 static void
13899 unsetfunc(const char *name)
13900 {
13901         struct tblentry *cmdp;
13902
13903         cmdp = cmdlookup(name, 0);
13904         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13905                 delete_cmd_entry();
13906 }
13907
13908 /*
13909  * The unset builtin command.  We unset the function before we unset the
13910  * variable to allow a function to be unset when there is a readonly variable
13911  * with the same name.
13912  */
13913 static int FAST_FUNC
13914 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13915 {
13916         char **ap;
13917         int i;
13918         int flag = 0;
13919
13920         while ((i = nextopt("vf")) != 0) {
13921                 flag = i;
13922         }
13923
13924         for (ap = argptr; *ap; ap++) {
13925                 if (flag != 'f') {
13926                         unsetvar(*ap);
13927                         continue;
13928                 }
13929                 if (flag != 'v')
13930                         unsetfunc(*ap);
13931         }
13932         return 0;
13933 }
13934
13935 static const unsigned char timescmd_str[] ALIGN1 = {
13936         ' ',  offsetof(struct tms, tms_utime),
13937         '\n', offsetof(struct tms, tms_stime),
13938         ' ',  offsetof(struct tms, tms_cutime),
13939         '\n', offsetof(struct tms, tms_cstime),
13940         0
13941 };
13942 static int FAST_FUNC
13943 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13944 {
13945         unsigned clk_tck;
13946         const unsigned char *p;
13947         struct tms buf;
13948
13949         clk_tck = bb_clk_tck();
13950
13951         times(&buf);
13952         p = timescmd_str;
13953         do {
13954                 unsigned sec, frac;
13955                 unsigned long t;
13956                 t = *(clock_t *)(((char *) &buf) + p[1]);
13957                 sec = t / clk_tck;
13958                 frac = t % clk_tck;
13959                 out1fmt("%um%u.%03us%c",
13960                         sec / 60, sec % 60,
13961                         (frac * 1000) / clk_tck,
13962                         p[0]);
13963                 p += 2;
13964         } while (*p);
13965
13966         return 0;
13967 }
13968
13969 #if ENABLE_FEATURE_SH_MATH
13970 /*
13971  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13972  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13973  *
13974  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13975  */
13976 static int FAST_FUNC
13977 letcmd(int argc UNUSED_PARAM, char **argv)
13978 {
13979         arith_t i;
13980
13981         argv++;
13982         if (!*argv)
13983                 ash_msg_and_raise_error("expression expected");
13984         do {
13985                 i = ash_arith(*argv);
13986         } while (*++argv);
13987
13988         return !i;
13989 }
13990 #endif
13991
13992 /*
13993  * The read builtin. Options:
13994  *      -r              Do not interpret '\' specially
13995  *      -s              Turn off echo (tty only)
13996  *      -n NCHARS       Read NCHARS max
13997  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13998  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13999  *      -u FD           Read from given FD instead of fd 0
14000  *      -d DELIM        End on DELIM char, not newline
14001  * This uses unbuffered input, which may be avoidable in some cases.
14002  * TODO: bash also has:
14003  *      -a ARRAY        Read into array[0],[1],etc
14004  *      -e              Use line editing (tty only)
14005  */
14006 static int FAST_FUNC
14007 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
14008 {
14009         struct builtin_read_params params;
14010         const char *r;
14011         int i;
14012
14013         memset(&params, 0, sizeof(params));
14014
14015         while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
14016                 switch (i) {
14017                 case 'p':
14018                         params.opt_p = optionarg;
14019                         break;
14020                 case 'n':
14021                         params.opt_n = optionarg;
14022                         break;
14023                 case 's':
14024                         params.read_flags |= BUILTIN_READ_SILENT;
14025                         break;
14026                 case 't':
14027                         params.opt_t = optionarg;
14028                         break;
14029                 case 'r':
14030                         params.read_flags |= BUILTIN_READ_RAW;
14031                         break;
14032                 case 'u':
14033                         params.opt_u = optionarg;
14034                         break;
14035 #if BASH_READ_D
14036                 case 'd':
14037                         params.opt_d = optionarg;
14038                         break;
14039 #endif
14040                 default:
14041                         break;
14042                 }
14043         }
14044
14045         params.argv = argptr;
14046         params.setvar = setvar0;
14047         params.ifs = bltinlookup("IFS"); /* can be NULL */
14048
14049         /* "read -s" needs to save/restore termios, can't allow ^C
14050          * to jump out of it.
14051          */
14052  again:
14053         INT_OFF;
14054         r = shell_builtin_read(&params);
14055         INT_ON;
14056
14057         if ((uintptr_t)r == 1 && errno == EINTR) {
14058                 /* To get SIGCHLD: sleep 1 & read x; echo $x
14059                  * Correct behavior is to not exit "read"
14060                  */
14061                 if (pending_sig == 0)
14062                         goto again;
14063         }
14064
14065         if ((uintptr_t)r > 1)
14066                 ash_msg_and_raise_error(r);
14067
14068         return (uintptr_t)r;
14069 }
14070
14071 static int FAST_FUNC
14072 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
14073 {
14074         static const char permuser[3] ALIGN1 = "ogu";
14075
14076         mode_t mask;
14077         int symbolic_mode = 0;
14078
14079         while (nextopt("S") != '\0') {
14080                 symbolic_mode = 1;
14081         }
14082
14083         INT_OFF;
14084         mask = umask(0);
14085         umask(mask);
14086         INT_ON;
14087
14088         if (*argptr == NULL) {
14089                 if (symbolic_mode) {
14090                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
14091                         char *p = buf;
14092                         int i;
14093
14094                         i = 2;
14095                         for (;;) {
14096                                 *p++ = ',';
14097                                 *p++ = permuser[i];
14098                                 *p++ = '=';
14099                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
14100                                 if (!(mask & 0400)) *p++ = 'r';
14101                                 if (!(mask & 0200)) *p++ = 'w';
14102                                 if (!(mask & 0100)) *p++ = 'x';
14103                                 mask <<= 3;
14104                                 if (--i < 0)
14105                                         break;
14106                         }
14107                         *p = '\0';
14108                         puts(buf + 1);
14109                 } else {
14110                         out1fmt("%04o\n", mask);
14111                 }
14112         } else {
14113                 char *modestr = *argptr;
14114                 /* numeric umasks are taken as-is */
14115                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
14116                 if (!isdigit(modestr[0]))
14117                         mask ^= 0777;
14118                 mask = bb_parse_mode(modestr, mask);
14119                 if ((unsigned)mask > 0777) {
14120                         ash_msg_and_raise_error("illegal mode: %s", modestr);
14121                 }
14122                 if (!isdigit(modestr[0]))
14123                         mask ^= 0777;
14124                 umask(mask);
14125         }
14126         return 0;
14127 }
14128
14129 static int FAST_FUNC
14130 ulimitcmd(int argc UNUSED_PARAM, char **argv)
14131 {
14132         return shell_builtin_ulimit(argv);
14133 }
14134
14135 /* ============ main() and helpers */
14136
14137 /*
14138  * Called to exit the shell.
14139  */
14140 static void
14141 exitshell(void)
14142 {
14143         struct jmploc loc;
14144         char *p;
14145
14146 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
14147         if (line_input_state)
14148                 save_history(line_input_state);
14149 #endif
14150         savestatus = exitstatus;
14151         TRACE(("pid %d, exitshell(%d)\n", getpid(), savestatus));
14152         if (setjmp(loc.loc))
14153                 goto out;
14154         exception_handler = &loc;
14155         p = trap[0];
14156         if (p) {
14157                 trap[0] = NULL;
14158                 evalskip = 0;
14159                 evalstring(p, 0);
14160                 /*free(p); - we'll exit soon */
14161         }
14162  out:
14163         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
14164          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
14165          */
14166         setjobctl(0);
14167         flush_stdout_stderr();
14168         _exit(savestatus);
14169         /* NOTREACHED */
14170 }
14171
14172 /* Don't inline: conserve stack of caller from having our locals too */
14173 static NOINLINE void
14174 init(void)
14175 {
14176         /* we will never free this */
14177         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
14178         basepf.linno = 1;
14179
14180         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
14181         setsignal(SIGCHLD);
14182
14183         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
14184          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
14185          */
14186         signal(SIGHUP, SIG_DFL);
14187
14188         {
14189                 char **envp;
14190                 const char *p;
14191
14192                 initvar();
14193                 for (envp = environ; envp && *envp; envp++) {
14194 /* Used to have
14195  *                      p = endofname(*envp);
14196  *                      if (p != *envp && *p == '=') {
14197  * here to weed out badly-named variables, but this breaks
14198  * scenarios where people do want them passed to children:
14199  * import os
14200  * os.environ["test-test"]="test"
14201  * if os.fork() == 0:
14202  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
14203  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])  # breaks this
14204  */
14205                         if (strchr(*envp, '=')) {
14206                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
14207                         }
14208                 }
14209
14210                 setvareq((char*)defifsvar, VTEXTFIXED);
14211                 setvareq((char*)defoptindvar, VTEXTFIXED);
14212
14213                 setvar0("PPID", utoa(getppid()));
14214 #if BASH_SHLVL_VAR
14215                 p = lookupvar("SHLVL");
14216                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
14217 #endif
14218 #if BASH_HOSTNAME_VAR
14219                 if (!lookupvar("HOSTNAME")) {
14220                         struct utsname uts;
14221                         uname(&uts);
14222                         setvar0("HOSTNAME", uts.nodename);
14223                 }
14224 #endif
14225                 p = lookupvar("PWD");
14226                 if (p) {
14227                         struct stat st1, st2;
14228                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
14229                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
14230                         ) {
14231                                 p = NULL;
14232                         }
14233                 }
14234                 setpwd(p, 0);
14235         }
14236 }
14237
14238
14239 //usage:#define ash_trivial_usage
14240 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS] / -s [ARGS]]"
14241 //usage:#define ash_full_usage "\n\n"
14242 //usage:        "Unix shell interpreter"
14243
14244 /*
14245  * Process the shell command line arguments.
14246  */
14247 static int
14248 procargs(char **argv)
14249 {
14250         int i;
14251         const char *xminusc;
14252         char **xargv;
14253         int login_sh;
14254
14255         xargv = argv;
14256         login_sh = xargv[0] && xargv[0][0] == '-';
14257 #if NUM_SCRIPTS > 0
14258         if (minusc)
14259                 goto setarg0;
14260 #endif
14261         arg0 = xargv[0];
14262         /* if (xargv[0]) - mmm, this is always true! */
14263                 xargv++;
14264         argptr = xargv;
14265         for (i = 0; i < NOPTS; i++)
14266                 optlist[i] = 2;
14267         if (options(&login_sh)) {
14268                 /* it already printed err message */
14269                 raise_exception(EXERROR);
14270         }
14271         xargv = argptr;
14272         xminusc = minusc;
14273         if (*xargv == NULL) {
14274                 if (xminusc)
14275                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
14276                 sflag = 1;
14277         }
14278         if (iflag == 2 /* no explicit -i given */
14279          && sflag == 1 /* -s given (or implied) */
14280          && !minusc /* bash compat: ash -sc 'echo $-' is not interactive (dash is) */
14281          && isatty(0) && isatty(1) /* we are on tty */
14282         ) {
14283                 iflag = 1;
14284         }
14285         if (mflag == 2)
14286                 mflag = iflag;
14287         for (i = 0; i < NOPTS; i++)
14288                 if (optlist[i] == 2)
14289                         optlist[i] = 0;
14290 #if DEBUG == 2
14291         debug = 1;
14292 #endif
14293         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
14294         if (xminusc) {
14295                 minusc = *xargv++;
14296                 if (*xargv)
14297                         goto setarg0;
14298         } else if (!sflag) {
14299                 setinputfile(*xargv, 0);
14300  setarg0:
14301                 arg0 = *xargv++;
14302                 commandname = arg0;
14303         }
14304
14305         shellparam.p = xargv;
14306 #if ENABLE_ASH_GETOPTS
14307         shellparam.optind = 1;
14308         shellparam.optoff = -1;
14309 #endif
14310         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
14311         while (*xargv) {
14312                 shellparam.nparam++;
14313                 xargv++;
14314         }
14315         optschanged();
14316
14317         return login_sh;
14318 }
14319
14320 /*
14321  * Read /etc/profile, ~/.profile, $ENV.
14322  */
14323 static void
14324 read_profile(const char *name)
14325 {
14326         name = expandstr(name, DQSYNTAX);
14327         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
14328                 return;
14329         cmdloop(0);
14330         popfile();
14331 }
14332
14333 /*
14334  * This routine is called when an error or an interrupt occurs in an
14335  * interactive shell and control is returned to the main command loop
14336  * but prior to exitshell.
14337  */
14338 static void
14339 exitreset(void)
14340 {
14341         /* from eval.c: */
14342         evalskip = 0;
14343         loopnest = 0;
14344         if (savestatus >= 0) {
14345                 exitstatus = savestatus;
14346                 savestatus = -1;
14347         }
14348
14349         /* from expand.c: */
14350         ifsfree();
14351
14352         /* from redir.c: */
14353         unwindredir(NULL);
14354 }
14355
14356 /*
14357  * This routine is called when an error or an interrupt occurs in an
14358  * interactive shell and control is returned to the main command loop.
14359  * (In dash, this function is auto-generated by build machinery).
14360  */
14361 static void
14362 reset(void)
14363 {
14364         /* from input.c: */
14365         g_parsefile->left_in_buffer = 0;
14366         g_parsefile->left_in_line = 0;      /* clear input buffer */
14367         popallfiles();
14368
14369         /* from var.c: */
14370         unwindlocalvars(NULL);
14371 }
14372
14373 #if PROFILE
14374 static short profile_buf[16384];
14375 extern int etext();
14376 #endif
14377
14378 /*
14379  * Main routine.  We initialize things, parse the arguments, execute
14380  * profiles if we're a login shell, and then call cmdloop to execute
14381  * commands.  The setjmp call sets up the location to jump to when an
14382  * exception occurs.  When an exception occurs the variable "state"
14383  * is used to figure out how far we had gotten.
14384  */
14385 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
14386 #if NUM_SCRIPTS > 0
14387 int ash_main(int argc, char **argv)
14388 #else
14389 int ash_main(int argc UNUSED_PARAM, char **argv)
14390 #endif
14391 /* note: 'argc' is used only if embedded scripts are enabled */
14392 {
14393         volatile smallint state;
14394         struct jmploc jmploc;
14395         struct stackmark smark;
14396         int login_sh;
14397
14398         /* Initialize global data */
14399         INIT_G_misc();
14400         INIT_G_memstack();
14401         INIT_G_var();
14402 #if ENABLE_ASH_ALIAS
14403         INIT_G_alias();
14404 #endif
14405         INIT_G_cmdtable();
14406
14407 #if PROFILE
14408         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
14409 #endif
14410
14411         state = 0;
14412         if (setjmp(jmploc.loc)) {
14413                 smallint e;
14414                 smallint s;
14415
14416                 exitreset();
14417
14418                 e = exception_type;
14419                 s = state;
14420                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
14421                         exitshell();
14422                 }
14423
14424                 reset();
14425
14426                 if (e == EXINT) {
14427                         newline_and_flush(stderr);
14428                 }
14429
14430                 popstackmark(&smark);
14431                 FORCE_INT_ON; /* enable interrupts */
14432                 if (s == 1)
14433                         goto state1;
14434                 if (s == 2)
14435                         goto state2;
14436                 if (s == 3)
14437                         goto state3;
14438                 goto state4;
14439         }
14440         exception_handler = &jmploc;
14441         rootpid = getpid();
14442
14443         init();
14444         setstackmark(&smark);
14445
14446 #if NUM_SCRIPTS > 0
14447         if (argc < 0)
14448                 /* Non-NULL minusc tells procargs that an embedded script is being run */
14449                 minusc = get_script_content(-argc - 1);
14450 #endif
14451         login_sh = procargs(argv);
14452 #if DEBUG
14453         TRACE(("Shell args: "));
14454         trace_puts_args(argv);
14455 #endif
14456
14457         if (login_sh) {
14458                 const char *hp;
14459
14460                 state = 1;
14461                 read_profile("/etc/profile");
14462  state1:
14463                 state = 2;
14464                 hp = lookupvar("HOME");
14465                 if (hp)
14466                         read_profile("$HOME/.profile");
14467         }
14468  state2:
14469         state = 3;
14470         if (
14471 #ifndef linux
14472          getuid() == geteuid() && getgid() == getegid() &&
14473 #endif
14474          iflag
14475         ) {
14476                 const char *shinit = lookupvar("ENV");
14477                 if (shinit != NULL && *shinit != '\0')
14478                         read_profile(shinit);
14479         }
14480         popstackmark(&smark);
14481  state3:
14482         state = 4;
14483         if (minusc) {
14484                 /* evalstring pushes parsefile stack.
14485                  * Ensure we don't falsely claim that 0 (stdin)
14486                  * is one of stacked source fds.
14487                  * Testcase: ash -c 'exec 1>&0' must not complain. */
14488
14489                 // if (!sflag) g_parsefile->pf_fd = -1;
14490                 // ^^ not necessary since now we special-case fd 0
14491                 // in save_fd_on_redirect()
14492
14493                 // dash: evalstring(minusc, sflag ? 0 : EV_EXIT);
14494                 // The above makes
14495                 //  ash -sc 'echo $-'
14496                 // continue reading input from stdin after running 'echo'.
14497                 // bash does not do this: it prints "hBcs" and exits.
14498                 evalstring(minusc, EV_EXIT);
14499         }
14500
14501         if (sflag || minusc == NULL) {
14502 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
14503                 if (iflag) {
14504                         const char *hp = lookupvar("HISTFILE");
14505                         if (!hp) {
14506                                 hp = lookupvar("HOME");
14507                                 if (hp) {
14508                                         INT_OFF;
14509                                         hp = concat_path_file(hp, ".ash_history");
14510                                         setvar0("HISTFILE", hp);
14511                                         free((char*)hp);
14512                                         INT_ON;
14513                                         hp = lookupvar("HISTFILE");
14514                                 }
14515                         }
14516                         if (hp)
14517                                 line_input_state->hist_file = hp;
14518 # if ENABLE_FEATURE_SH_HISTFILESIZE
14519                         hp = lookupvar("HISTFILESIZE");
14520                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
14521 # endif
14522                 }
14523 #endif
14524  state4: /* XXX ??? - why isn't this before the "if" statement */
14525                 cmdloop(1);
14526         }
14527 #if PROFILE
14528         monitor(0);
14529 #endif
14530 #ifdef GPROF
14531         {
14532                 extern void _mcleanup(void);
14533                 _mcleanup();
14534         }
14535 #endif
14536         TRACE(("End of main reached\n"));
14537         exitshell();
14538         /* NOTREACHED */
14539 }
14540
14541
14542 /*-
14543  * Copyright (c) 1989, 1991, 1993, 1994
14544  *      The Regents of the University of California.  All rights reserved.
14545  *
14546  * This code is derived from software contributed to Berkeley by
14547  * Kenneth Almquist.
14548  *
14549  * Redistribution and use in source and binary forms, with or without
14550  * modification, are permitted provided that the following conditions
14551  * are met:
14552  * 1. Redistributions of source code must retain the above copyright
14553  *    notice, this list of conditions and the following disclaimer.
14554  * 2. Redistributions in binary form must reproduce the above copyright
14555  *    notice, this list of conditions and the following disclaimer in the
14556  *    documentation and/or other materials provided with the distribution.
14557  * 3. Neither the name of the University nor the names of its contributors
14558  *    may be used to endorse or promote products derived from this software
14559  *    without specific prior written permission.
14560  *
14561  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
14562  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14563  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14564  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
14565  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14566  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14567  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14568  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14569  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14570  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14571  * SUCH DAMAGE.
14572  */