shell: add comments about [[, no code changes
[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 (77 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
185 /* So far, all bash compat is controlled by one config option */
186 /* Separate defines document which part of code implements what */
187 /* function keyword */
188 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
189 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
190 /* &>file */
191 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
192 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
193 /* $'...' */
194 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
195 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
196 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
197 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
198 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
199 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
200 /* BASH_TEST2: [[ EXPR ]]
201  * Status of [[ support:
202  * We replace && and || with -a and -o
203  * TODO:
204  * singleword+noglob expansion:
205  *   v='a b'; [[ $v = 'a b' ]]; echo 0:$?
206  *   [[ /bin/* ]]; echo 0:$?
207  * -a/-o are not AND/OR ops! (they are just strings)
208  * quoting needs to be considered (-f is an operator, "-f" and ""-f are not; etc)
209  * = is glob match operator, not equality operator: STR = GLOB
210  * (in GLOB, quoting is significant on char-by-char basis: a*cd"*")
211  * == same as =
212  * add =~ regex match operator: STR =~ REGEX
213  */
214 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
215 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
216 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
217 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
218 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
219 #define    BASH_XTRACEFD        ENABLE_ASH_BASH_COMPAT
220 #define    BASH_READ_D          ENABLE_ASH_BASH_COMPAT
221 #define IF_BASH_READ_D              IF_ASH_BASH_COMPAT
222
223 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
224 /* Bionic at least up to version 24 has no glob() */
225 # undef  ENABLE_ASH_INTERNAL_GLOB
226 # define ENABLE_ASH_INTERNAL_GLOB 1
227 #endif
228
229 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
230 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
231 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
232 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
233 # error glob() should unbackslash them and match. uClibc does not unbackslash,
234 # error fails to match dirname, subsequently not expanding <pattern> in it.
235 // Testcase:
236 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
237 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
238 #endif
239
240 #if !ENABLE_ASH_INTERNAL_GLOB
241 # include <glob.h>
242 #endif
243
244 #include "unicode.h"
245 #include "shell_common.h"
246 #if ENABLE_FEATURE_SH_MATH
247 # include "math.h"
248 #else
249 typedef long arith_t;
250 # define ARITH_FMT "%ld"
251 #endif
252 #if ENABLE_ASH_RANDOM_SUPPORT
253 # include "random.h"
254 #else
255 # define CLEAR_RANDOM_T(rnd) ((void)0)
256 #endif
257
258 #include "NUM_APPLETS.h"
259 #if NUM_APPLETS == 1
260 /* STANDALONE does not make sense, and won't compile */
261 # undef CONFIG_FEATURE_SH_STANDALONE
262 # undef ENABLE_FEATURE_SH_STANDALONE
263 # undef IF_FEATURE_SH_STANDALONE
264 # undef IF_NOT_FEATURE_SH_STANDALONE
265 # define ENABLE_FEATURE_SH_STANDALONE 0
266 # define IF_FEATURE_SH_STANDALONE(...)
267 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
268 #endif
269
270 #ifndef F_DUPFD_CLOEXEC
271 # define F_DUPFD_CLOEXEC F_DUPFD
272 #endif
273 #ifndef O_CLOEXEC
274 # define O_CLOEXEC 0
275 #endif
276 #ifndef PIPE_BUF
277 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
278 #endif
279
280 #if !BB_MMU
281 # error "Do not even bother, ash will not run on NOMMU machine"
282 #endif
283
284 /* We use a trick to have more optimized code (fewer pointer reloads):
285  *  ash.c:   extern struct globals *const ash_ptr_to_globals;
286  *  ash_ptr_hack.c: struct globals *ash_ptr_to_globals;
287  * This way, compiler in ash.c knows the pointer can not change.
288  *
289  * However, this may break on weird arches or toolchains. In this case,
290  * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable
291  * this optimization.
292  */
293 #ifndef BB_GLOBAL_CONST
294 # define BB_GLOBAL_CONST const
295 #endif
296
297
298 /* ============ Hash table sizes. Configurable. */
299
300 #define VTABSIZE 39
301 #define ATABSIZE 39
302 #define CMDTABLESIZE 31         /* should be prime */
303
304
305 /* ============ Shell options */
306
307 static const char *const optletters_optnames[] = {
308         "e"   "errexit",
309         "f"   "noglob",
310         "I"   "ignoreeof",
311         "i"   "interactive",
312         "m"   "monitor",
313         "n"   "noexec",
314         "s"   "stdin",
315         "x"   "xtrace",
316         "v"   "verbose",
317         "C"   "noclobber",
318         "a"   "allexport",
319         "b"   "notify",
320         "u"   "nounset",
321         "\0"  "vi"
322 #if BASH_PIPEFAIL
323         ,"\0"  "pipefail"
324 #endif
325 #if DEBUG
326         ,"\0"  "nolog"
327         ,"\0"  "debug"
328 #endif
329 };
330
331 #define optletters(n)  optletters_optnames[n][0]
332 #define optnames(n)   (optletters_optnames[n] + 1)
333
334 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
335
336
337 /* ============ Misc data */
338
339 #define msg_illnum "Illegal number: %s"
340
341 /*
342  * We enclose jmp_buf in a structure so that we can declare pointers to
343  * jump locations.  The global variable handler contains the location to
344  * jump to when an exception occurs, and the global variable exception_type
345  * contains a code identifying the exception.  To implement nested
346  * exception handlers, the user should save the value of handler on entry
347  * to an inner scope, set handler to point to a jmploc structure for the
348  * inner scope, and restore handler on exit from the scope.
349  */
350 struct jmploc {
351         jmp_buf loc;
352 };
353
354 struct globals_misc {
355         uint8_t exitstatus;     /* exit status of last command */
356         uint8_t back_exitstatus;/* exit status of backquoted command */
357         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
358         int rootpid;            /* pid of main shell */
359         /* shell level: 0 for the main shell, 1 for its children, and so on */
360         int shlvl;
361 #define rootshell (!shlvl)
362         int errlinno;
363
364         char *minusc;  /* argument to -c option */
365
366         char *curdir; // = nullstr;     /* current working directory */
367         char *physdir; // = nullstr;    /* physical working directory */
368
369         char *arg0; /* value of $0 */
370
371         struct jmploc *exception_handler;
372
373         volatile int suppress_int; /* counter */
374         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
375         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
376         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
377         smallint exception_type; /* kind of exception (0..5) */
378         /* exceptions */
379 #define EXINT 0         /* SIGINT received */
380 #define EXERROR 1       /* a generic error */
381 #define EXEXIT 4        /* exit the shell */
382
383         char nullstr[1];        /* zero length string */
384
385         char optlist[NOPTS];
386 #define eflag optlist[0]
387 #define fflag optlist[1]
388 #define Iflag optlist[2]
389 #define iflag optlist[3]
390 #define mflag optlist[4]
391 #define nflag optlist[5]
392 #define sflag optlist[6]
393 #define xflag optlist[7]
394 #define vflag optlist[8]
395 #define Cflag optlist[9]
396 #define aflag optlist[10]
397 #define bflag optlist[11]
398 #define uflag optlist[12]
399 #define viflag optlist[13]
400 #if BASH_PIPEFAIL
401 # define pipefail optlist[14]
402 #else
403 # define pipefail 0
404 #endif
405 #if DEBUG
406 # define nolog optlist[14 + BASH_PIPEFAIL]
407 # define debug optlist[15 + BASH_PIPEFAIL]
408 #endif
409
410         /* trap handler commands */
411         /*
412          * Sigmode records the current value of the signal handlers for the various
413          * modes.  A value of zero means that the current handler is not known.
414          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
415          */
416         char sigmode[NSIG - 1];
417 #define S_DFL      1            /* default signal handling (SIG_DFL) */
418 #define S_CATCH    2            /* signal is caught */
419 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
420 #define S_HARD_IGN 4            /* signal is ignored permanently (it was SIG_IGN on entry to shell) */
421
422         /* indicates specified signal received */
423         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
424         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
425         char *trap[NSIG];
426         char **trap_ptr;        /* used only by "trap hack" */
427
428         /* Rarely referenced stuff */
429 #if ENABLE_ASH_RANDOM_SUPPORT
430         random_t random_gen;
431 #endif
432         pid_t backgndpid;        /* pid of last background process */
433 };
434 extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc;
435 #define G_misc (*ash_ptr_to_globals_misc)
436 #define exitstatus        (G_misc.exitstatus )
437 #define back_exitstatus   (G_misc.back_exitstatus )
438 #define job_warning       (G_misc.job_warning)
439 #define rootpid     (G_misc.rootpid    )
440 #define shlvl       (G_misc.shlvl      )
441 #define errlinno    (G_misc.errlinno   )
442 #define minusc      (G_misc.minusc     )
443 #define curdir      (G_misc.curdir     )
444 #define physdir     (G_misc.physdir    )
445 #define arg0        (G_misc.arg0       )
446 #define exception_handler (G_misc.exception_handler)
447 #define exception_type    (G_misc.exception_type   )
448 #define suppress_int      (G_misc.suppress_int     )
449 #define pending_int       (G_misc.pending_int      )
450 #define got_sigchld       (G_misc.got_sigchld      )
451 #define pending_sig       (G_misc.pending_sig      )
452 #define nullstr     (G_misc.nullstr    )
453 #define optlist     (G_misc.optlist    )
454 #define sigmode     (G_misc.sigmode    )
455 #define gotsig      (G_misc.gotsig     )
456 #define may_have_traps    (G_misc.may_have_traps   )
457 #define trap        (G_misc.trap       )
458 #define trap_ptr    (G_misc.trap_ptr   )
459 #define random_gen  (G_misc.random_gen )
460 #define backgndpid  (G_misc.backgndpid )
461 #define INIT_G_misc() do { \
462         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
463         barrier(); \
464         curdir = nullstr; \
465         physdir = nullstr; \
466         trap_ptr = trap; \
467 } while (0)
468
469
470 /* ============ DEBUG */
471 #if DEBUG
472 static void trace_printf(const char *fmt, ...);
473 static void trace_vprintf(const char *fmt, va_list va);
474 # define TRACE(param)    trace_printf param
475 # define TRACEV(param)   trace_vprintf param
476 # define close(fd) do { \
477         int dfd = (fd); \
478         if (close(dfd) < 0) \
479                 bb_error_msg("bug on %d: closing %d(0x%x)", \
480                         __LINE__, dfd, dfd); \
481 } while (0)
482 #else
483 # define TRACE(param)
484 # define TRACEV(param)
485 #endif
486
487
488 /* ============ Utility functions */
489 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
490 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
491
492 static int
493 isdigit_str9(const char *str)
494 {
495         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
496         while (--maxlen && isdigit(*str))
497                 str++;
498         return (*str == '\0');
499 }
500
501 static const char *
502 var_end(const char *var)
503 {
504         while (*var)
505                 if (*var++ == '=')
506                         break;
507         return var;
508 }
509
510
511 /* ============ Interrupts / exceptions */
512
513 static void exitshell(void) NORETURN;
514
515 /*
516  * These macros allow the user to suspend the handling of interrupt signals
517  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
518  * much more efficient and portable.  (But hacking the kernel is so much
519  * more fun than worrying about efficiency and portability. :-))
520  */
521 #if DEBUG_INTONOFF
522 # define INT_OFF do { \
523         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
524         suppress_int++; \
525         barrier(); \
526 } while (0)
527 #else
528 # define INT_OFF do { \
529         suppress_int++; \
530         barrier(); \
531 } while (0)
532 #endif
533
534 /*
535  * Called to raise an exception.  Since C doesn't include exceptions, we
536  * just do a longjmp to the exception handler.  The type of exception is
537  * stored in the global variable "exception_type".
538  */
539 static void raise_exception(int) NORETURN;
540 static void
541 raise_exception(int e)
542 {
543 #if DEBUG
544         if (exception_handler == NULL)
545                 abort();
546 #endif
547         INT_OFF;
548         exception_type = e;
549         longjmp(exception_handler->loc, 1);
550 }
551 #if DEBUG
552 #define raise_exception(e) do { \
553         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
554         raise_exception(e); \
555 } while (0)
556 #endif
557
558 /*
559  * Called when a SIGINT is received.  (If the user specifies
560  * that SIGINT is to be trapped or ignored using the trap builtin, then
561  * this routine is not called.)  Suppressint is nonzero when interrupts
562  * are held using the INT_OFF macro.  (The test for iflag is just
563  * defensive programming.)
564  */
565 static void raise_interrupt(void) NORETURN;
566 static void
567 raise_interrupt(void)
568 {
569         pending_int = 0;
570         /* Signal is not automatically unmasked after it is raised,
571          * do it ourself - unmask all signals */
572         sigprocmask_allsigs(SIG_UNBLOCK);
573         /* pending_sig = 0; - now done in signal_handler() */
574
575         if (!(rootshell && iflag)) {
576                 /* Kill ourself with SIGINT */
577                 signal(SIGINT, SIG_DFL);
578                 raise(SIGINT);
579         }
580         /* bash: ^C even on empty command line sets $? */
581         exitstatus = SIGINT + 128;
582         raise_exception(EXINT);
583         /* NOTREACHED */
584 }
585 #if DEBUG
586 #define raise_interrupt() do { \
587         TRACE(("raising interrupt on line %d\n", __LINE__)); \
588         raise_interrupt(); \
589 } while (0)
590 #endif
591
592 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
593 int_on(void)
594 {
595         barrier();
596         if (--suppress_int == 0 && pending_int) {
597                 raise_interrupt();
598         }
599 }
600 #if DEBUG_INTONOFF
601 # define INT_ON do { \
602         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
603         int_on(); \
604 } while (0)
605 #else
606 # define INT_ON int_on()
607 #endif
608 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
609 force_int_on(void)
610 {
611         barrier();
612         suppress_int = 0;
613         if (pending_int)
614                 raise_interrupt();
615 }
616 #define FORCE_INT_ON force_int_on()
617
618 #define SAVE_INT(v) ((v) = suppress_int)
619
620 #define RESTORE_INT(v) do { \
621         barrier(); \
622         suppress_int = (v); \
623         if (suppress_int == 0 && pending_int) \
624                 raise_interrupt(); \
625 } while (0)
626
627
628 /* ============ Stdout/stderr output */
629
630 static void
631 outstr(const char *p, FILE *file)
632 {
633         INT_OFF;
634         fputs(p, file);
635         INT_ON;
636 }
637
638 static void
639 flush_stdout_stderr(void)
640 {
641         INT_OFF;
642         fflush_all();
643         INT_ON;
644 }
645
646 /* Was called outcslow(c,FILE*), but c was always '\n' */
647 static void
648 newline_and_flush(FILE *dest)
649 {
650         INT_OFF;
651         putc('\n', dest);
652         fflush(dest);
653         INT_ON;
654 }
655
656 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
657 static int
658 out1fmt(const char *fmt, ...)
659 {
660         va_list ap;
661         int r;
662
663         INT_OFF;
664         va_start(ap, fmt);
665         r = vprintf(fmt, ap);
666         va_end(ap);
667         INT_ON;
668         return r;
669 }
670
671 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
672 static int
673 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
674 {
675         va_list ap;
676         int ret;
677
678         INT_OFF;
679         va_start(ap, fmt);
680         ret = vsnprintf(outbuf, length, fmt, ap);
681         va_end(ap);
682         INT_ON;
683         return ret;
684 }
685
686 static void
687 out1str(const char *p)
688 {
689         outstr(p, stdout);
690 }
691
692 static void
693 out2str(const char *p)
694 {
695         outstr(p, stderr);
696         flush_stdout_stderr();
697 }
698
699
700 /* ============ Parser structures */
701
702 /* control characters in argument strings */
703 #define CTL_FIRST CTLESC
704 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
705 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
706 #define CTLENDVAR    ((unsigned char)'\203')
707 #define CTLBACKQ     ((unsigned char)'\204')
708 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
709 #define CTLENDARI    ((unsigned char)'\207')
710 #define CTLQUOTEMARK ((unsigned char)'\210')
711 #define CTL_LAST CTLQUOTEMARK
712
713 /* variable substitution byte (follows CTLVAR) */
714 #define VSTYPE  0x0f            /* type of variable substitution */
715 #define VSNUL   0x10            /* colon--treat the empty string as unset */
716
717 /* values of VSTYPE field */
718 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
719 #define VSMINUS         0x2     /* ${var-text} */
720 #define VSPLUS          0x3     /* ${var+text} */
721 #define VSQUESTION      0x4     /* ${var?message} */
722 #define VSASSIGN        0x5     /* ${var=text} */
723 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
724 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
725 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
726 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
727 #define VSLENGTH        0xa     /* ${#var} */
728 #if BASH_SUBSTR
729 #define VSSUBSTR        0xc     /* ${var:position:length} */
730 #endif
731 #if BASH_PATTERN_SUBST
732 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
733 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
734 #endif
735
736 static const char dolatstr[] ALIGN1 = {
737         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
738 };
739 #define DOLATSTRLEN 6
740
741 #define NCMD      0
742 #define NPIPE     1
743 #define NREDIR    2
744 #define NBACKGND  3
745 #define NSUBSHELL 4
746 #define NAND      5
747 #define NOR       6
748 #define NSEMI     7
749 #define NIF       8
750 #define NWHILE    9
751 #define NUNTIL   10
752 #define NFOR     11
753 #define NCASE    12
754 #define NCLIST   13
755 #define NDEFUN   14
756 #define NARG     15
757 #define NTO      16
758 #if BASH_REDIR_OUTPUT
759 #define NTO2     17
760 #endif
761 #define NCLOBBER 18
762 #define NFROM    19
763 #define NFROMTO  20
764 #define NAPPEND  21
765 #define NTOFD    22
766 #define NFROMFD  23
767 #define NHERE    24
768 #define NXHERE   25
769 #define NNOT     26
770 #define N_NUMBER 27
771
772 union node;
773
774 struct ncmd {
775         smallint type; /* Nxxxx */
776         int linno;
777         union node *assign;
778         union node *args;
779         union node *redirect;
780 };
781
782 struct npipe {
783         smallint type;
784         smallint pipe_backgnd;
785         struct nodelist *cmdlist;
786 };
787
788 struct nredir {
789         smallint type;
790         int linno;
791         union node *n;
792         union node *redirect;
793 };
794
795 struct nbinary {
796         smallint type;
797         union node *ch1;
798         union node *ch2;
799 };
800
801 struct nif {
802         smallint type;
803         union node *test;
804         union node *ifpart;
805         union node *elsepart;
806 };
807
808 struct nfor {
809         smallint type;
810         int linno;
811         union node *args;
812         union node *body;
813         char *var;
814 };
815
816 struct ncase {
817         smallint type;
818         int linno;
819         union node *expr;
820         union node *cases;
821 };
822
823 struct nclist {
824         smallint type;
825         union node *next;
826         union node *pattern;
827         union node *body;
828 };
829
830 struct ndefun {
831         smallint type;
832         int linno;
833         char *text;
834         union node *body;
835 };
836
837 struct narg {
838         smallint type;
839         union node *next;
840         char *text;
841         struct nodelist *backquote;
842 };
843
844 /* nfile and ndup layout must match!
845  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
846  * that it is actually NTO2 (>&file), and change its type.
847  */
848 struct nfile {
849         smallint type;
850         union node *next;
851         int fd;
852         int _unused_dupfd;
853         union node *fname;
854         char *expfname;
855 };
856
857 struct ndup {
858         smallint type;
859         union node *next;
860         int fd;
861         int dupfd;
862         union node *vname;
863         char *_unused_expfname;
864 };
865
866 struct nhere {
867         smallint type;
868         union node *next;
869         int fd;
870         union node *doc;
871 };
872
873 struct nnot {
874         smallint type;
875         union node *com;
876 };
877
878 union node {
879         smallint type;
880         struct ncmd ncmd;
881         struct npipe npipe;
882         struct nredir nredir;
883         struct nbinary nbinary;
884         struct nif nif;
885         struct nfor nfor;
886         struct ncase ncase;
887         struct nclist nclist;
888         struct ndefun ndefun;
889         struct narg narg;
890         struct nfile nfile;
891         struct ndup ndup;
892         struct nhere nhere;
893         struct nnot nnot;
894 };
895
896 /*
897  * NODE_EOF is returned by parsecmd when it encounters an end of file.
898  * It must be distinct from NULL.
899  */
900 #define NODE_EOF ((union node *) -1L)
901
902 struct nodelist {
903         struct nodelist *next;
904         union node *n;
905 };
906
907 struct funcnode {
908         int count;
909         union node n;
910 };
911
912 /*
913  * Free a parse tree.
914  */
915 static void
916 freefunc(struct funcnode *f)
917 {
918         if (f && --f->count < 0)
919                 free(f);
920 }
921
922
923 /* ============ Debugging output */
924
925 #if DEBUG
926
927 static FILE *tracefile;
928
929 static void
930 trace_printf(const char *fmt, ...)
931 {
932         va_list va;
933
934         if (debug != 1)
935                 return;
936         if (DEBUG_TIME)
937                 fprintf(tracefile, "%u ", (int) time(NULL));
938         if (DEBUG_PID)
939                 fprintf(tracefile, "[%u] ", (int) getpid());
940         if (DEBUG_SIG)
941                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
942         va_start(va, fmt);
943         vfprintf(tracefile, fmt, va);
944         va_end(va);
945 }
946
947 static void
948 trace_vprintf(const char *fmt, va_list va)
949 {
950         if (debug != 1)
951                 return;
952         vfprintf(tracefile, fmt, va);
953         fprintf(tracefile, "\n");
954 }
955
956 static void
957 trace_puts(const char *s)
958 {
959         if (debug != 1)
960                 return;
961         fputs(s, tracefile);
962 }
963
964 static void
965 trace_puts_quoted(char *s)
966 {
967         char *p;
968         char c;
969
970         if (debug != 1)
971                 return;
972         putc('"', tracefile);
973         for (p = s; *p; p++) {
974                 switch ((unsigned char)*p) {
975                 case '\n': c = 'n'; goto backslash;
976                 case '\t': c = 't'; goto backslash;
977                 case '\r': c = 'r'; goto backslash;
978                 case '\"': c = '\"'; goto backslash;
979                 case '\\': c = '\\'; goto backslash;
980                 case CTLESC: c = 'e'; goto backslash;
981                 case CTLVAR: c = 'v'; goto backslash;
982                 case CTLBACKQ: c = 'q'; goto backslash;
983  backslash:
984                         putc('\\', tracefile);
985                         putc(c, tracefile);
986                         break;
987                 default:
988                         if (*p >= ' ' && *p <= '~')
989                                 putc(*p, tracefile);
990                         else {
991                                 putc('\\', tracefile);
992                                 putc((*p >> 6) & 03, tracefile);
993                                 putc((*p >> 3) & 07, tracefile);
994                                 putc(*p & 07, tracefile);
995                         }
996                         break;
997                 }
998         }
999         putc('"', tracefile);
1000 }
1001
1002 static void
1003 trace_puts_args(char **ap)
1004 {
1005         if (debug != 1)
1006                 return;
1007         if (!*ap)
1008                 return;
1009         while (1) {
1010                 trace_puts_quoted(*ap);
1011                 if (!*++ap) {
1012                         putc('\n', tracefile);
1013                         break;
1014                 }
1015                 putc(' ', tracefile);
1016         }
1017 }
1018
1019 static void
1020 opentrace(void)
1021 {
1022         char s[100];
1023 #ifdef O_APPEND
1024         int flags;
1025 #endif
1026
1027         if (debug != 1) {
1028                 if (tracefile)
1029                         fflush(tracefile);
1030                 /* leave open because libedit might be using it */
1031                 return;
1032         }
1033         strcpy(s, "./trace");
1034         if (tracefile) {
1035                 if (!freopen(s, "a", tracefile)) {
1036                         fprintf(stderr, "Can't re-open %s\n", s);
1037                         debug = 0;
1038                         return;
1039                 }
1040         } else {
1041                 tracefile = fopen(s, "a");
1042                 if (tracefile == NULL) {
1043                         fprintf(stderr, "Can't open %s\n", s);
1044                         debug = 0;
1045                         return;
1046                 }
1047         }
1048 #ifdef O_APPEND
1049         flags = fcntl(fileno(tracefile), F_GETFL);
1050         if (flags >= 0)
1051                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
1052 #endif
1053         setlinebuf(tracefile);
1054         fputs("\nTracing started.\n", tracefile);
1055 }
1056
1057 static void
1058 indent(int amount, char *pfx, FILE *fp)
1059 {
1060         int i;
1061
1062         for (i = 0; i < amount; i++) {
1063                 if (pfx && i == amount - 1)
1064                         fputs(pfx, fp);
1065                 putc('\t', fp);
1066         }
1067 }
1068
1069 /* little circular references here... */
1070 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1071
1072 static void
1073 sharg(union node *arg, FILE *fp)
1074 {
1075         char *p;
1076         struct nodelist *bqlist;
1077         unsigned char subtype;
1078
1079         if (arg->type != NARG) {
1080                 out1fmt("<node type %d>\n", arg->type);
1081                 abort();
1082         }
1083         bqlist = arg->narg.backquote;
1084         for (p = arg->narg.text; *p; p++) {
1085                 switch ((unsigned char)*p) {
1086                 case CTLESC:
1087                         p++;
1088                         putc(*p, fp);
1089                         break;
1090                 case CTLVAR:
1091                         putc('$', fp);
1092                         putc('{', fp);
1093                         subtype = *++p;
1094                         if (subtype == VSLENGTH)
1095                                 putc('#', fp);
1096
1097                         while (*p != '=') {
1098                                 putc(*p, fp);
1099                                 p++;
1100                         }
1101
1102                         if (subtype & VSNUL)
1103                                 putc(':', fp);
1104
1105                         switch (subtype & VSTYPE) {
1106                         case VSNORMAL:
1107                                 putc('}', fp);
1108                                 break;
1109                         case VSMINUS:
1110                                 putc('-', fp);
1111                                 break;
1112                         case VSPLUS:
1113                                 putc('+', fp);
1114                                 break;
1115                         case VSQUESTION:
1116                                 putc('?', fp);
1117                                 break;
1118                         case VSASSIGN:
1119                                 putc('=', fp);
1120                                 break;
1121                         case VSTRIMLEFT:
1122                                 putc('#', fp);
1123                                 break;
1124                         case VSTRIMLEFTMAX:
1125                                 putc('#', fp);
1126                                 putc('#', fp);
1127                                 break;
1128                         case VSTRIMRIGHT:
1129                                 putc('%', fp);
1130                                 break;
1131                         case VSTRIMRIGHTMAX:
1132                                 putc('%', fp);
1133                                 putc('%', fp);
1134                                 break;
1135                         case VSLENGTH:
1136                                 break;
1137                         default:
1138                                 out1fmt("<subtype %d>", subtype);
1139                         }
1140                         break;
1141                 case CTLENDVAR:
1142                         putc('}', fp);
1143                         break;
1144                 case CTLBACKQ:
1145                         putc('$', fp);
1146                         putc('(', fp);
1147                         shtree(bqlist->n, -1, NULL, fp);
1148                         putc(')', fp);
1149                         break;
1150                 default:
1151                         putc(*p, fp);
1152                         break;
1153                 }
1154         }
1155 }
1156
1157 static void
1158 shcmd(union node *cmd, FILE *fp)
1159 {
1160         union node *np;
1161         int first;
1162         const char *s;
1163         int dftfd;
1164
1165         first = 1;
1166         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1167                 if (!first)
1168                         putc(' ', fp);
1169                 sharg(np, fp);
1170                 first = 0;
1171         }
1172         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1173                 if (!first)
1174                         putc(' ', fp);
1175                 dftfd = 0;
1176                 switch (np->nfile.type) {
1177                 case NTO:      s = ">>"+1; dftfd = 1; break;
1178                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1179                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1180 #if BASH_REDIR_OUTPUT
1181                 case NTO2:
1182 #endif
1183                 case NTOFD:    s = ">&"; dftfd = 1; break;
1184                 case NFROM:    s = "<"; break;
1185                 case NFROMFD:  s = "<&"; break;
1186                 case NFROMTO:  s = "<>"; break;
1187                 default:       s = "*error*"; break;
1188                 }
1189                 if (np->nfile.fd != dftfd)
1190                         fprintf(fp, "%d", np->nfile.fd);
1191                 fputs(s, fp);
1192                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1193                         fprintf(fp, "%d", np->ndup.dupfd);
1194                 } else {
1195                         sharg(np->nfile.fname, fp);
1196                 }
1197                 first = 0;
1198         }
1199 }
1200
1201 static void
1202 shtree(union node *n, int ind, char *pfx, FILE *fp)
1203 {
1204         struct nodelist *lp;
1205         const char *s;
1206
1207         if (n == NULL)
1208                 return;
1209
1210         indent(ind, pfx, fp);
1211
1212         if (n == NODE_EOF) {
1213                 fputs("<EOF>", fp);
1214                 return;
1215         }
1216
1217         switch (n->type) {
1218         case NSEMI:
1219                 s = "; ";
1220                 goto binop;
1221         case NAND:
1222                 s = " && ";
1223                 goto binop;
1224         case NOR:
1225                 s = " || ";
1226  binop:
1227                 shtree(n->nbinary.ch1, ind, NULL, fp);
1228                 /* if (ind < 0) */
1229                         fputs(s, fp);
1230                 shtree(n->nbinary.ch2, ind, NULL, fp);
1231                 break;
1232         case NCMD:
1233                 shcmd(n, fp);
1234                 if (ind >= 0)
1235                         putc('\n', fp);
1236                 break;
1237         case NPIPE:
1238                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1239                         shtree(lp->n, 0, NULL, fp);
1240                         if (lp->next)
1241                                 fputs(" | ", fp);
1242                 }
1243                 if (n->npipe.pipe_backgnd)
1244                         fputs(" &", fp);
1245                 if (ind >= 0)
1246                         putc('\n', fp);
1247                 break;
1248         default:
1249                 fprintf(fp, "<node type %d>", n->type);
1250                 if (ind >= 0)
1251                         putc('\n', fp);
1252                 break;
1253         }
1254 }
1255
1256 static void
1257 showtree(union node *n)
1258 {
1259         trace_puts("showtree called\n");
1260         shtree(n, 1, NULL, stderr);
1261 }
1262
1263 #endif /* DEBUG */
1264
1265
1266 /* ============ Parser data */
1267
1268 /*
1269  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1270  */
1271 struct strlist {
1272         struct strlist *next;
1273         char *text;
1274 };
1275
1276 struct alias;
1277
1278 struct strpush {
1279         struct strpush *prev;   /* preceding string on stack */
1280         char *prev_string;
1281         int prev_left_in_line;
1282 #if ENABLE_ASH_ALIAS
1283         struct alias *ap;       /* if push was associated with an alias */
1284 #endif
1285         char *string;           /* remember the string since it may change */
1286
1287         /* Remember last two characters for pungetc. */
1288         int lastc[2];
1289
1290         /* Number of outstanding calls to pungetc. */
1291         int unget;
1292 };
1293
1294 /*
1295  * The parsefile structure pointed to by the global variable parsefile
1296  * contains information about the current file being read.
1297  */
1298 struct parsefile {
1299         struct parsefile *prev; /* preceding file on stack */
1300         int linno;              /* current line */
1301         int pf_fd;              /* file descriptor (or -1 if string) */
1302         int left_in_line;       /* number of chars left in this line */
1303         int left_in_buffer;     /* number of chars left in this buffer past the line */
1304         char *next_to_pgetc;    /* next char in buffer */
1305         char *buf;              /* input buffer */
1306         struct strpush *strpush; /* for pushing strings at this level */
1307         struct strpush basestrpush; /* so pushing one is fast */
1308
1309         /* Remember last two characters for pungetc. */
1310         int lastc[2];
1311
1312         /* Number of outstanding calls to pungetc. */
1313         int unget;
1314 };
1315
1316 static struct parsefile basepf;        /* top level input file */
1317 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1318 static char *commandname;              /* currently executing command */
1319
1320
1321 /* ============ Message printing */
1322
1323 static void
1324 ash_vmsg(const char *msg, va_list ap)
1325 {
1326         fprintf(stderr, "%s: ", arg0);
1327         if (commandname) {
1328                 if (strcmp(arg0, commandname))
1329                         fprintf(stderr, "%s: ", commandname);
1330                 if (!iflag || g_parsefile->pf_fd > 0)
1331                         fprintf(stderr, "line %d: ", errlinno);
1332         }
1333         vfprintf(stderr, msg, ap);
1334         newline_and_flush(stderr);
1335 }
1336
1337 /*
1338  * Exverror is called to raise the error exception.  If the second argument
1339  * is not NULL then error prints an error message using printf style
1340  * formatting.  It then raises the error exception.
1341  */
1342 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1343 static void
1344 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1345 {
1346 #if DEBUG
1347         if (msg) {
1348                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1349                 TRACEV((msg, ap));
1350         } else
1351                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1352         if (msg)
1353 #endif
1354                 ash_vmsg(msg, ap);
1355
1356         flush_stdout_stderr();
1357         raise_exception(cond);
1358         /* NOTREACHED */
1359 }
1360
1361 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1362 static void
1363 ash_msg_and_raise_error(const char *msg, ...)
1364 {
1365         va_list ap;
1366
1367         exitstatus = 2;
1368
1369         va_start(ap, msg);
1370         ash_vmsg_and_raise(EXERROR, msg, ap);
1371         /* NOTREACHED */
1372         va_end(ap);
1373 }
1374
1375 /*
1376  * 'fmt' must be a string literal.
1377  */
1378 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": "STRERROR_FMT, ##__VA_ARGS__ STRERROR_ERRNO)
1379
1380 static void raise_error_syntax(const char *) NORETURN;
1381 static void
1382 raise_error_syntax(const char *msg)
1383 {
1384         errlinno = g_parsefile->linno;
1385         ash_msg_and_raise_error("syntax error: %s", msg);
1386         /* NOTREACHED */
1387 }
1388
1389 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1390 static void
1391 ash_msg_and_raise(int cond, const char *msg, ...)
1392 {
1393         va_list ap;
1394
1395         va_start(ap, msg);
1396         ash_vmsg_and_raise(cond, msg, ap);
1397         /* NOTREACHED */
1398         va_end(ap);
1399 }
1400
1401 /*
1402  * error/warning routines for external builtins
1403  */
1404 static void
1405 ash_msg(const char *fmt, ...)
1406 {
1407         va_list ap;
1408
1409         va_start(ap, fmt);
1410         ash_vmsg(fmt, ap);
1411         va_end(ap);
1412 }
1413
1414 /*
1415  * Return a string describing an error.  The returned string may be a
1416  * pointer to a static buffer that will be overwritten on the next call.
1417  * Action describes the operation that got the error.
1418  */
1419 static const char *
1420 errmsg(int e, const char *em)
1421 {
1422         if (e == ENOENT || e == ENOTDIR) {
1423                 return em;
1424         }
1425         return strerror(e);
1426 }
1427
1428
1429 /* ============ Memory allocation */
1430
1431 #if 0
1432 /* I consider these wrappers nearly useless:
1433  * ok, they return you to nearest exception handler, but
1434  * how much memory do you leak in the process, making
1435  * memory starvation worse?
1436  */
1437 static void *
1438 ckrealloc(void * p, size_t nbytes)
1439 {
1440         p = realloc(p, nbytes);
1441         if (!p)
1442                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1443         return p;
1444 }
1445
1446 static void *
1447 ckmalloc(size_t nbytes)
1448 {
1449         return ckrealloc(NULL, nbytes);
1450 }
1451
1452 static void *
1453 ckzalloc(size_t nbytes)
1454 {
1455         return memset(ckmalloc(nbytes), 0, nbytes);
1456 }
1457
1458 static char *
1459 ckstrdup(const char *s)
1460 {
1461         char *p = strdup(s);
1462         if (!p)
1463                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1464         return p;
1465 }
1466 #else
1467 /* Using bbox equivalents. They exit if out of memory */
1468 # define ckrealloc xrealloc
1469 # define ckmalloc  xmalloc
1470 # define ckzalloc  xzalloc
1471 # define ckstrdup  xstrdup
1472 #endif
1473
1474 /*
1475  * It appears that grabstackstr() will barf with such alignments
1476  * because stalloc() will return a string allocated in a new stackblock.
1477  */
1478 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1479 enum {
1480         /* Most machines require the value returned from malloc to be aligned
1481          * in some way.  The following macro will get this right
1482          * on many machines.  */
1483         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1484         /* Minimum size of a block */
1485         MINSIZE = SHELL_ALIGN(504),
1486 };
1487
1488 struct stack_block {
1489         struct stack_block *prev;
1490         char space[MINSIZE];
1491 };
1492
1493 struct stackmark {
1494         struct stack_block *stackp;
1495         char *stacknxt;
1496         size_t stacknleft;
1497 };
1498
1499
1500 struct globals_memstack {
1501         struct stack_block *g_stackp; // = &stackbase;
1502         char *g_stacknxt; // = stackbase.space;
1503         char *sstrend; // = stackbase.space + MINSIZE;
1504         size_t g_stacknleft; // = MINSIZE;
1505         struct stack_block stackbase;
1506 };
1507 extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack;
1508 #define G_memstack (*ash_ptr_to_globals_memstack)
1509 #define g_stackp     (G_memstack.g_stackp    )
1510 #define g_stacknxt   (G_memstack.g_stacknxt  )
1511 #define sstrend      (G_memstack.sstrend     )
1512 #define g_stacknleft (G_memstack.g_stacknleft)
1513 #define stackbase    (G_memstack.stackbase   )
1514 #define INIT_G_memstack() do { \
1515         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1516         barrier(); \
1517         g_stackp = &stackbase; \
1518         g_stacknxt = stackbase.space; \
1519         g_stacknleft = MINSIZE; \
1520         sstrend = stackbase.space + MINSIZE; \
1521 } while (0)
1522
1523
1524 #define stackblock()     ((void *)g_stacknxt)
1525 #define stackblocksize() g_stacknleft
1526
1527 /*
1528  * Parse trees for commands are allocated in lifo order, so we use a stack
1529  * to make this more efficient, and also to avoid all sorts of exception
1530  * handling code to handle interrupts in the middle of a parse.
1531  *
1532  * The size 504 was chosen because the Ultrix malloc handles that size
1533  * well.
1534  */
1535 static void *
1536 stalloc(size_t nbytes)
1537 {
1538         char *p;
1539         size_t aligned;
1540
1541         aligned = SHELL_ALIGN(nbytes);
1542         if (aligned > g_stacknleft) {
1543                 size_t len;
1544                 size_t blocksize;
1545                 struct stack_block *sp;
1546
1547                 blocksize = aligned;
1548                 if (blocksize < MINSIZE)
1549                         blocksize = MINSIZE;
1550                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1551                 if (len < blocksize)
1552                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1553                 INT_OFF;
1554                 sp = ckmalloc(len);
1555                 sp->prev = g_stackp;
1556                 g_stacknxt = sp->space;
1557                 g_stacknleft = blocksize;
1558                 sstrend = g_stacknxt + blocksize;
1559                 g_stackp = sp;
1560                 INT_ON;
1561         }
1562         p = g_stacknxt;
1563         g_stacknxt += aligned;
1564         g_stacknleft -= aligned;
1565         return p;
1566 }
1567
1568 static void *
1569 stzalloc(size_t nbytes)
1570 {
1571         return memset(stalloc(nbytes), 0, nbytes);
1572 }
1573
1574 static void
1575 stunalloc(void *p)
1576 {
1577 #if DEBUG
1578         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1579                 write(STDERR_FILENO, "stunalloc\n", 10);
1580                 abort();
1581         }
1582 #endif
1583         g_stacknleft += g_stacknxt - (char *)p;
1584         g_stacknxt = p;
1585 }
1586
1587 /*
1588  * Like strdup but works with the ash stack.
1589  */
1590 static char *
1591 sstrdup(const char *p)
1592 {
1593         size_t len = strlen(p) + 1;
1594         return memcpy(stalloc(len), p, len);
1595 }
1596
1597 static ALWAYS_INLINE void
1598 grabstackblock(size_t len)
1599 {
1600         stalloc(len);
1601 }
1602
1603 static void
1604 pushstackmark(struct stackmark *mark, size_t len)
1605 {
1606         mark->stackp = g_stackp;
1607         mark->stacknxt = g_stacknxt;
1608         mark->stacknleft = g_stacknleft;
1609         grabstackblock(len);
1610 }
1611
1612 static void
1613 setstackmark(struct stackmark *mark)
1614 {
1615         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1616 }
1617
1618 static void
1619 popstackmark(struct stackmark *mark)
1620 {
1621         struct stack_block *sp;
1622
1623         if (!mark->stackp)
1624                 return;
1625
1626         INT_OFF;
1627         while (g_stackp != mark->stackp) {
1628                 sp = g_stackp;
1629                 g_stackp = sp->prev;
1630                 free(sp);
1631         }
1632         g_stacknxt = mark->stacknxt;
1633         g_stacknleft = mark->stacknleft;
1634         sstrend = mark->stacknxt + mark->stacknleft;
1635         INT_ON;
1636 }
1637
1638 /*
1639  * When the parser reads in a string, it wants to stick the string on the
1640  * stack and only adjust the stack pointer when it knows how big the
1641  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1642  * of space on top of the stack and stackblocklen returns the length of
1643  * this block.  Growstackblock will grow this space by at least one byte,
1644  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1645  * part of the block that has been used.
1646  */
1647 static void
1648 growstackblock(void)
1649 {
1650         size_t newlen;
1651
1652         newlen = g_stacknleft * 2;
1653         if (newlen < g_stacknleft)
1654                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1655         if (newlen < 128)
1656                 newlen += 128;
1657
1658         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1659                 struct stack_block *sp;
1660                 struct stack_block *prevstackp;
1661                 size_t grosslen;
1662
1663                 INT_OFF;
1664                 sp = g_stackp;
1665                 prevstackp = sp->prev;
1666                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1667                 sp = ckrealloc(sp, grosslen);
1668                 sp->prev = prevstackp;
1669                 g_stackp = sp;
1670                 g_stacknxt = sp->space;
1671                 g_stacknleft = newlen;
1672                 sstrend = sp->space + newlen;
1673                 INT_ON;
1674         } else {
1675                 char *oldspace = g_stacknxt;
1676                 size_t oldlen = g_stacknleft;
1677                 char *p = stalloc(newlen);
1678
1679                 /* free the space we just allocated */
1680                 g_stacknxt = memcpy(p, oldspace, oldlen);
1681                 g_stacknleft += newlen;
1682         }
1683 }
1684
1685 /*
1686  * The following routines are somewhat easier to use than the above.
1687  * The user declares a variable of type STACKSTR, which may be declared
1688  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1689  * the user uses the macro STPUTC to add characters to the string.  In
1690  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1691  * grown as necessary.  When the user is done, she can just leave the
1692  * string there and refer to it using stackblock().  Or she can allocate
1693  * the space for it using grabstackstr().  If it is necessary to allow
1694  * someone else to use the stack temporarily and then continue to grow
1695  * the string, the user should use grabstack to allocate the space, and
1696  * then call ungrabstr(p) to return to the previous mode of operation.
1697  *
1698  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1699  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1700  * is space for at least one character.
1701  */
1702 static void *
1703 growstackstr(void)
1704 {
1705         size_t len = stackblocksize();
1706         growstackblock();
1707         return (char *)stackblock() + len;
1708 }
1709
1710 /*
1711  * Called from CHECKSTRSPACE.
1712  */
1713 static char *
1714 makestrspace(size_t newlen, char *p)
1715 {
1716         size_t len = p - g_stacknxt;
1717         size_t size;
1718
1719         for (;;) {
1720                 size_t nleft;
1721
1722                 size = stackblocksize();
1723                 nleft = size - len;
1724                 if (nleft >= newlen)
1725                         break;
1726                 growstackblock();
1727         }
1728         return (char *)stackblock() + len;
1729 }
1730
1731 static char *
1732 stack_nputstr(const char *s, size_t n, char *p)
1733 {
1734         p = makestrspace(n, p);
1735         p = (char *)mempcpy(p, s, n);
1736         return p;
1737 }
1738
1739 static char *
1740 stack_putstr(const char *s, char *p)
1741 {
1742         return stack_nputstr(s, strlen(s), p);
1743 }
1744
1745 static char *
1746 _STPUTC(int c, char *p)
1747 {
1748         if (p == sstrend)
1749                 p = growstackstr();
1750         *p++ = c;
1751         return p;
1752 }
1753
1754 #define STARTSTACKSTR(p)        ((p) = stackblock())
1755 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1756 #define CHECKSTRSPACE(n, p) do { \
1757         char *q = (p); \
1758         size_t l = (n); \
1759         size_t m = sstrend - q; \
1760         if (l > m) \
1761                 (p) = makestrspace(l, q); \
1762 } while (0)
1763 #define USTPUTC(c, p)           (*(p)++ = (c))
1764 #define STACKSTRNUL(p) do { \
1765         if ((p) == sstrend) \
1766                 (p) = growstackstr(); \
1767         *(p) = '\0'; \
1768 } while (0)
1769 #define STUNPUTC(p)             (--(p))
1770 #define STTOPC(p)               ((p)[-1])
1771 #define STADJUST(amount, p)     ((p) += (amount))
1772
1773 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1774 #define ungrabstackstr(s, p)    stunalloc(s)
1775 #define stackstrend()           ((void *)sstrend)
1776
1777
1778 /* ============ String helpers */
1779
1780 /*
1781  * prefix -- see if pfx is a prefix of string.
1782  */
1783 static char *
1784 prefix(const char *string, const char *pfx)
1785 {
1786         while (*pfx) {
1787                 if (*pfx++ != *string++)
1788                         return NULL;
1789         }
1790         return (char *) string;
1791 }
1792
1793 /*
1794  * Check for a valid number.  This should be elsewhere.
1795  */
1796 static int
1797 is_number(const char *p)
1798 {
1799         do {
1800                 if (!isdigit(*p))
1801                         return 0;
1802         } while (*++p != '\0');
1803         return 1;
1804 }
1805
1806 /*
1807  * Convert a string of digits to an integer, printing an error message on
1808  * failure.
1809  */
1810 static int
1811 number(const char *s)
1812 {
1813         if (!is_number(s))
1814                 ash_msg_and_raise_error(msg_illnum, s);
1815         return atoi(s);
1816 }
1817
1818 /*
1819  * Produce a single quoted string suitable as input to the shell.
1820  * The return string is allocated on the stack.
1821  */
1822 static char *
1823 single_quote(const char *s)
1824 {
1825         char *p;
1826
1827         STARTSTACKSTR(p);
1828
1829         do {
1830                 char *q;
1831                 size_t len;
1832
1833                 len = strchrnul(s, '\'') - s;
1834
1835                 q = p = makestrspace(len + 3, p);
1836
1837                 *q++ = '\'';
1838                 q = (char *)mempcpy(q, s, len);
1839                 *q++ = '\'';
1840                 s += len;
1841
1842                 STADJUST(q - p, p);
1843
1844                 if (*s != '\'')
1845                         break;
1846                 len = 0;
1847                 do len++; while (*++s == '\'');
1848
1849                 q = p = makestrspace(len + 3, p);
1850
1851                 *q++ = '"';
1852                 q = (char *)mempcpy(q, s - len, len);
1853                 *q++ = '"';
1854
1855                 STADJUST(q - p, p);
1856         } while (*s);
1857
1858         USTPUTC('\0', p);
1859
1860         return stackblock();
1861 }
1862
1863 /*
1864  * Produce a possibly single quoted string suitable as input to the shell.
1865  * If quoting was done, the return string is allocated on the stack,
1866  * otherwise a pointer to the original string is returned.
1867  */
1868 static const char *
1869 maybe_single_quote(const char *s)
1870 {
1871         const char *p = s;
1872
1873         while (*p) {
1874                 /* Assuming ACSII */
1875                 /* quote ctrl_chars space !"#$%&'()* */
1876                 if (*p < '+')
1877                         goto need_quoting;
1878                 /* quote ;<=>? */
1879                 if (*p >= ';' && *p <= '?')
1880                         goto need_quoting;
1881                 /* quote `[\ */
1882                 if (*p == '`')
1883                         goto need_quoting;
1884                 if (*p == '[')
1885                         goto need_quoting;
1886                 if (*p == '\\')
1887                         goto need_quoting;
1888                 /* quote {|}~ DEL and high bytes */
1889                 if (*p > 'z')
1890                         goto need_quoting;
1891                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1892                 /* TODO: maybe avoid quoting % */
1893                 p++;
1894         }
1895         return s;
1896
1897  need_quoting:
1898         return single_quote(s);
1899 }
1900
1901
1902 /* ============ nextopt */
1903
1904 static char **argptr;                  /* argument list for builtin commands */
1905 static char *optionarg;                /* set by nextopt (like getopt) */
1906 static char *optptr;                   /* used by nextopt */
1907
1908 /*
1909  * XXX - should get rid of. Have all builtins use getopt(3).
1910  * The library getopt must have the BSD extension static variable
1911  * "optreset", otherwise it can't be used within the shell safely.
1912  *
1913  * Standard option processing (a la getopt) for builtin routines.
1914  * The only argument that is passed to nextopt is the option string;
1915  * the other arguments are unnecessary. It returns the character,
1916  * or '\0' on end of input.
1917  */
1918 static int
1919 nextopt(const char *optstring)
1920 {
1921         char *p;
1922         const char *q;
1923         char c;
1924
1925         p = optptr;
1926         if (p == NULL || *p == '\0') {
1927                 /* We ate entire "-param", take next one */
1928                 p = *argptr;
1929                 if (p == NULL)
1930                         return '\0';
1931                 if (*p != '-')
1932                         return '\0';
1933                 if (*++p == '\0') /* just "-" ? */
1934                         return '\0';
1935                 argptr++;
1936                 if (LONE_DASH(p)) /* "--" ? */
1937                         return '\0';
1938                 /* p => next "-param" */
1939         }
1940         /* p => some option char in the middle of a "-param" */
1941         c = *p++;
1942         for (q = optstring; *q != c;) {
1943                 if (*q == '\0')
1944                         ash_msg_and_raise_error("illegal option -%c", c);
1945                 if (*++q == ':')
1946                         q++;
1947         }
1948         if (*++q == ':') {
1949                 if (*p == '\0') {
1950                         p = *argptr++;
1951                         if (p == NULL)
1952                                 ash_msg_and_raise_error("no arg for -%c option", c);
1953                 }
1954                 optionarg = p;
1955                 p = NULL;
1956         }
1957         optptr = p;
1958         return c;
1959 }
1960
1961
1962 /* ============ Shell variables */
1963
1964 struct shparam {
1965         int nparam;             /* # of positional parameters (without $0) */
1966 #if ENABLE_ASH_GETOPTS
1967         int optind;             /* next parameter to be processed by getopts */
1968         int optoff;             /* used by getopts */
1969 #endif
1970         unsigned char malloced; /* if parameter list dynamically allocated */
1971         char **p;               /* parameter list */
1972 };
1973
1974 /*
1975  * Free the list of positional parameters.
1976  */
1977 static void
1978 freeparam(volatile struct shparam *param)
1979 {
1980         if (param->malloced) {
1981                 char **ap, **ap1;
1982                 ap = ap1 = param->p;
1983                 while (*ap)
1984                         free(*ap++);
1985                 free(ap1);
1986         }
1987 }
1988
1989 #if ENABLE_ASH_GETOPTS
1990 static void FAST_FUNC getoptsreset(const char *value);
1991 #endif
1992
1993 struct var {
1994         struct var *next;               /* next entry in hash list */
1995         int flags;                      /* flags are defined above */
1996         const char *var_text;           /* name=value */
1997         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1998                                         /* the variable gets set/unset */
1999 };
2000
2001 struct localvar {
2002         struct localvar *next;          /* next local variable in list */
2003         struct var *vp;                 /* the variable that was made local */
2004         int flags;                      /* saved flags */
2005         const char *text;               /* saved text */
2006 };
2007
2008 /* flags */
2009 #define VEXPORT         0x01    /* variable is exported */
2010 #define VREADONLY       0x02    /* variable cannot be modified */
2011 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
2012 #define VTEXTFIXED      0x08    /* text is statically allocated */
2013 #define VSTACK          0x10    /* text is allocated on the stack */
2014 #define VUNSET          0x20    /* the variable is not set */
2015 #define VNOFUNC         0x40    /* don't call the callback function */
2016 #define VNOSET          0x80    /* do not set variable - just readonly test */
2017 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
2018 #if ENABLE_ASH_RANDOM_SUPPORT
2019 # define VDYNAMIC       0x200   /* dynamic variable */
2020 #else
2021 # define VDYNAMIC       0
2022 #endif
2023
2024
2025 /* Need to be before varinit_data[] */
2026 #if ENABLE_LOCALE_SUPPORT
2027 static void FAST_FUNC
2028 change_lc_all(const char *value)
2029 {
2030         if (value && *value != '\0')
2031                 setlocale(LC_ALL, value);
2032 }
2033 static void FAST_FUNC
2034 change_lc_ctype(const char *value)
2035 {
2036         if (value && *value != '\0')
2037                 setlocale(LC_CTYPE, value);
2038 }
2039 #endif
2040 #if ENABLE_ASH_MAIL
2041 static void chkmail(void);
2042 static void changemail(const char *var_value) FAST_FUNC;
2043 #else
2044 # define chkmail()  ((void)0)
2045 #endif
2046 static void changepath(const char *) FAST_FUNC;
2047 #if ENABLE_ASH_RANDOM_SUPPORT
2048 static void change_random(const char *) FAST_FUNC;
2049 #endif
2050
2051 static const struct {
2052         int flags;
2053         const char *var_text;
2054         void (*var_func)(const char *) FAST_FUNC;
2055 } varinit_data[] = {
2056         /*
2057          * Note: VEXPORT would not work correctly here for NOFORK applets:
2058          * some environment strings may be constant.
2059          */
2060         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2061 #if ENABLE_ASH_MAIL
2062         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2063         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2064 #endif
2065         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2066         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2067         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2068         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2069 #if ENABLE_ASH_GETOPTS
2070         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2071 #endif
2072         { VSTRFIXED|VTEXTFIXED       , NULL /* inited to linenovar */, NULL },
2073 #if ENABLE_ASH_RANDOM_SUPPORT
2074         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2075 #endif
2076 #if ENABLE_LOCALE_SUPPORT
2077         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2078         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2079 #endif
2080 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2081         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2082 #endif
2083 };
2084
2085 struct redirtab;
2086
2087 struct globals_var {
2088         struct shparam shellparam;      /* $@ current positional parameters */
2089         struct redirtab *redirlist;
2090         int preverrout_fd;   /* stderr fd: usually 2, unless redirect moved it */
2091         struct var *vartab[VTABSIZE];
2092         struct var varinit[ARRAY_SIZE(varinit_data)];
2093         int lineno;
2094         char linenovar[sizeof("LINENO=") + sizeof(int)*3];
2095 };
2096 extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var;
2097 #define G_var (*ash_ptr_to_globals_var)
2098 #define shellparam    (G_var.shellparam   )
2099 //#define redirlist     (G_var.redirlist    )
2100 #define preverrout_fd (G_var.preverrout_fd)
2101 #define vartab        (G_var.vartab       )
2102 #define varinit       (G_var.varinit      )
2103 #define lineno        (G_var.lineno       )
2104 #define linenovar     (G_var.linenovar    )
2105 #define vifs      varinit[0]
2106 #if ENABLE_ASH_MAIL
2107 # define vmail    (&vifs)[1]
2108 # define vmpath   (&vmail)[1]
2109 # define vpath    (&vmpath)[1]
2110 #else
2111 # define vpath    (&vifs)[1]
2112 #endif
2113 #define vps1      (&vpath)[1]
2114 #define vps2      (&vps1)[1]
2115 #define vps4      (&vps2)[1]
2116 #if ENABLE_ASH_GETOPTS
2117 # define voptind  (&vps4)[1]
2118 # define vlineno  (&voptind)[1]
2119 # if ENABLE_ASH_RANDOM_SUPPORT
2120 #  define vrandom (&vlineno)[1]
2121 # endif
2122 #else
2123 # define vlineno  (&vps4)[1]
2124 # if ENABLE_ASH_RANDOM_SUPPORT
2125 #  define vrandom (&vlineno)[1]
2126 # endif
2127 #endif
2128 #define INIT_G_var() do { \
2129         unsigned i; \
2130         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2131         barrier(); \
2132         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2133                 varinit[i].flags    = varinit_data[i].flags; \
2134                 varinit[i].var_text = varinit_data[i].var_text; \
2135                 varinit[i].var_func = varinit_data[i].var_func; \
2136         } \
2137         strcpy(linenovar, "LINENO="); \
2138         vlineno.var_text = linenovar; \
2139 } while (0)
2140
2141 /*
2142  * The following macros access the values of the above variables.
2143  * They have to skip over the name.  They return the null string
2144  * for unset variables.
2145  */
2146 #define ifsval()        (vifs.var_text + 4)
2147 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2148 #if ENABLE_ASH_MAIL
2149 # define mailval()      (vmail.var_text + 5)
2150 # define mpathval()     (vmpath.var_text + 9)
2151 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2152 #endif
2153 #define pathval()       (vpath.var_text + 5)
2154 #define ps1val()        (vps1.var_text + 4)
2155 #define ps2val()        (vps2.var_text + 4)
2156 #define ps4val()        (vps4.var_text + 4)
2157 #if ENABLE_ASH_GETOPTS
2158 # define optindval()    (voptind.var_text + 7)
2159 #endif
2160
2161 #if ENABLE_ASH_GETOPTS
2162 static void FAST_FUNC
2163 getoptsreset(const char *value)
2164 {
2165         shellparam.optind = 1;
2166         if (is_number(value))
2167                 shellparam.optind = number(value) ?: 1;
2168         shellparam.optoff = -1;
2169 }
2170 #endif
2171
2172 /*
2173  * Compares two strings up to the first = or '\0'.  The first
2174  * string must be terminated by '='; the second may be terminated by
2175  * either '=' or '\0'.
2176  */
2177 static int
2178 varcmp(const char *p, const char *q)
2179 {
2180         int c, d;
2181
2182         while ((c = *p) == (d = *q)) {
2183                 if (c == '\0' || c == '=')
2184                         goto out;
2185                 p++;
2186                 q++;
2187         }
2188         if (c == '=')
2189                 c = '\0';
2190         if (d == '=')
2191                 d = '\0';
2192  out:
2193         return c - d;
2194 }
2195
2196 /*
2197  * Find the appropriate entry in the hash table from the name.
2198  */
2199 static struct var **
2200 hashvar(const char *p)
2201 {
2202         unsigned hashval;
2203
2204         hashval = ((unsigned char) *p) << 4;
2205         while (*p && *p != '=')
2206                 hashval += (unsigned char) *p++;
2207         return &vartab[hashval % VTABSIZE];
2208 }
2209
2210 static int
2211 vpcmp(const void *a, const void *b)
2212 {
2213         return varcmp(*(const char **)a, *(const char **)b);
2214 }
2215
2216 /*
2217  * This routine initializes the builtin variables.
2218  */
2219 static void
2220 initvar(void)
2221 {
2222         struct var *vp;
2223         struct var *end;
2224         struct var **vpp;
2225
2226         /*
2227          * PS1 depends on uid
2228          */
2229 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2230         vps1.var_text = "PS1=\\w \\$ ";
2231 #else
2232         if (!geteuid())
2233                 vps1.var_text = "PS1=# ";
2234 #endif
2235         vp = varinit;
2236         end = vp + ARRAY_SIZE(varinit);
2237         do {
2238                 vpp = hashvar(vp->var_text);
2239                 vp->next = *vpp;
2240                 *vpp = vp;
2241         } while (++vp < end);
2242 }
2243
2244 static struct var **
2245 findvar(struct var **vpp, const char *name)
2246 {
2247         for (; *vpp; vpp = &(*vpp)->next) {
2248                 if (varcmp((*vpp)->var_text, name) == 0) {
2249                         break;
2250                 }
2251         }
2252         return vpp;
2253 }
2254
2255 /*
2256  * Find the value of a variable.  Returns NULL if not set.
2257  */
2258 static const char* FAST_FUNC
2259 lookupvar(const char *name)
2260 {
2261         struct var *v;
2262
2263         v = *findvar(hashvar(name), name);
2264         if (v) {
2265 #if ENABLE_ASH_RANDOM_SUPPORT
2266         /*
2267          * Dynamic variables are implemented roughly the same way they are
2268          * in bash. Namely, they're "special" so long as they aren't unset.
2269          * As soon as they're unset, they're no longer dynamic, and dynamic
2270          * lookup will no longer happen at that point. -- PFM.
2271          */
2272                 if (v->flags & VDYNAMIC)
2273                         v->var_func(NULL);
2274 #endif
2275                 if (!(v->flags & VUNSET)) {
2276                         if (v == &vlineno && v->var_text == linenovar) {
2277                                 fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno);
2278                         }
2279                         return var_end(v->var_text);
2280                 }
2281         }
2282         return NULL;
2283 }
2284
2285 #if ENABLE_UNICODE_SUPPORT
2286 static void
2287 reinit_unicode_for_ash(void)
2288 {
2289         /* Unicode support should be activated even if LANG is set
2290          * _during_ shell execution, not only if it was set when
2291          * shell was started. Therefore, re-check LANG every time:
2292          */
2293         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2294          || ENABLE_UNICODE_USING_LOCALE
2295         ) {
2296                 const char *s = lookupvar("LC_ALL");
2297                 if (!s) s = lookupvar("LC_CTYPE");
2298                 if (!s) s = lookupvar("LANG");
2299                 reinit_unicode(s);
2300         }
2301 }
2302 #else
2303 # define reinit_unicode_for_ash() ((void)0)
2304 #endif
2305
2306 /*
2307  * Search the environment of a builtin command.
2308  */
2309 static ALWAYS_INLINE const char *
2310 bltinlookup(const char *name)
2311 {
2312         return lookupvar(name);
2313 }
2314
2315 /*
2316  * Same as setvar except that the variable and value are passed in
2317  * the first argument as name=value.  Since the first argument will
2318  * be actually stored in the table, it should not be a string that
2319  * will go away.
2320  * Called with interrupts off.
2321  */
2322 static struct var *
2323 setvareq(char *s, int flags)
2324 {
2325         struct var *vp, **vpp;
2326
2327         vpp = hashvar(s);
2328         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2329         vpp = findvar(vpp, s);
2330         vp = *vpp;
2331         if (vp) {
2332                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2333                         const char *n;
2334
2335                         if (flags & VNOSAVE)
2336                                 free(s);
2337                         n = vp->var_text;
2338                         exitstatus = 1;
2339                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2340                 }
2341
2342                 if (flags & VNOSET)
2343                         goto out;
2344
2345                 if (vp->var_func && !(flags & VNOFUNC))
2346                         vp->var_func(var_end(s));
2347
2348                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2349                         free((char*)vp->var_text);
2350
2351                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2352                         *vpp = vp->next;
2353                         free(vp);
2354  out_free:
2355                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2356                                 free(s);
2357                         goto out;
2358                 }
2359
2360                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2361         } else {
2362                 /* variable s is not found */
2363                 if (flags & VNOSET)
2364                         goto out;
2365                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2366                         goto out_free;
2367                 vp = ckzalloc(sizeof(*vp));
2368                 vp->next = *vpp;
2369                 /*vp->func = NULL; - ckzalloc did it */
2370                 *vpp = vp;
2371         }
2372         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2373                 s = ckstrdup(s);
2374         vp->var_text = s;
2375         vp->flags = flags;
2376
2377  out:
2378         return vp;
2379 }
2380
2381 /*
2382  * Set the value of a variable.  The flags argument is ored with the
2383  * flags of the variable.  If val is NULL, the variable is unset.
2384  */
2385 static struct var *
2386 setvar(const char *name, const char *val, int flags)
2387 {
2388         const char *q;
2389         char *p;
2390         char *nameeq;
2391         size_t namelen;
2392         size_t vallen;
2393         struct var *vp;
2394
2395         q = endofname(name);
2396         p = strchrnul(q, '=');
2397         namelen = p - name;
2398         if (!namelen || p != q)
2399                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2400         vallen = 0;
2401         if (val == NULL) {
2402                 flags |= VUNSET;
2403         } else {
2404                 vallen = strlen(val);
2405         }
2406
2407         INT_OFF;
2408         nameeq = ckmalloc(namelen + vallen + 2);
2409         p = mempcpy(nameeq, name, namelen);
2410         if (val) {
2411                 *p++ = '=';
2412                 p = mempcpy(p, val, vallen);
2413         }
2414         *p = '\0';
2415         vp = setvareq(nameeq, flags | VNOSAVE);
2416         INT_ON;
2417
2418         return vp;
2419 }
2420
2421 static void FAST_FUNC
2422 setvar0(const char *name, const char *val)
2423 {
2424         setvar(name, val, 0);
2425 }
2426
2427 /*
2428  * Unset the specified variable.
2429  */
2430 static void
2431 unsetvar(const char *s)
2432 {
2433         setvar(s, NULL, 0);
2434 }
2435
2436 /*
2437  * Process a linked list of variable assignments.
2438  */
2439 static void
2440 listsetvar(struct strlist *list_set_var, int flags)
2441 {
2442         struct strlist *lp = list_set_var;
2443
2444         if (!lp)
2445                 return;
2446         INT_OFF;
2447         do {
2448                 setvareq(lp->text, flags);
2449                 lp = lp->next;
2450         } while (lp);
2451         INT_ON;
2452 }
2453
2454 /*
2455  * Generate a list of variables satisfying the given conditions.
2456  */
2457 #if !ENABLE_FEATURE_SH_NOFORK
2458 # define listvars(on, off, lp, end) listvars(on, off, end)
2459 #endif
2460 static char **
2461 listvars(int on, int off, struct strlist *lp, char ***end)
2462 {
2463         struct var **vpp;
2464         struct var *vp;
2465         char **ep;
2466         int mask;
2467
2468         STARTSTACKSTR(ep);
2469         vpp = vartab;
2470         mask = on | off;
2471         do {
2472                 for (vp = *vpp; vp; vp = vp->next) {
2473                         if ((vp->flags & mask) == on) {
2474 #if ENABLE_FEATURE_SH_NOFORK
2475                                 /* If variable with the same name is both
2476                                  * exported and temporarily set for a command:
2477                                  *  export ZVAR=5
2478                                  *  ZVAR=6 printenv
2479                                  * then "ZVAR=6" will be both in vartab and
2480                                  * lp lists. Do not pass it twice to printenv.
2481                                  */
2482                                 struct strlist *lp1 = lp;
2483                                 while (lp1) {
2484                                         if (strcmp(lp1->text, vp->var_text) == 0)
2485                                                 goto skip;
2486                                         lp1 = lp1->next;
2487                                 }
2488 #endif
2489                                 if (ep == stackstrend())
2490                                         ep = growstackstr();
2491                                 *ep++ = (char*)vp->var_text;
2492 #if ENABLE_FEATURE_SH_NOFORK
2493  skip: ;
2494 #endif
2495                         }
2496                 }
2497         } while (++vpp < vartab + VTABSIZE);
2498
2499 #if ENABLE_FEATURE_SH_NOFORK
2500         while (lp) {
2501                 if (ep == stackstrend())
2502                         ep = growstackstr();
2503                 *ep++ = lp->text;
2504                 lp = lp->next;
2505         }
2506 #endif
2507
2508         if (ep == stackstrend())
2509                 ep = growstackstr();
2510         if (end)
2511                 *end = ep;
2512         *ep++ = NULL;
2513         return grabstackstr(ep);
2514 }
2515
2516
2517 /* ============ Path search helper
2518  *
2519  * The variable path (passed by reference) should be set to the start
2520  * of the path before the first call; path_advance will update
2521  * this value as it proceeds.  Successive calls to path_advance will return
2522  * the possible path expansions in sequence.  If an option (indicated by
2523  * a percent sign) appears in the path entry then the global variable
2524  * pathopt will be set to point to it; otherwise pathopt will be set to
2525  * NULL.
2526  */
2527 static const char *pathopt;     /* set by path_advance */
2528
2529 static char *
2530 path_advance(const char **path, const char *name)
2531 {
2532         const char *p;
2533         char *q;
2534         const char *start;
2535         size_t len;
2536
2537         if (*path == NULL)
2538                 return NULL;
2539         start = *path;
2540         for (p = start; *p && *p != ':' && *p != '%'; p++)
2541                 continue;
2542         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2543         while (stackblocksize() < len)
2544                 growstackblock();
2545         q = stackblock();
2546         if (p != start) {
2547                 q = mempcpy(q, start, p - start);
2548                 *q++ = '/';
2549         }
2550         strcpy(q, name);
2551         pathopt = NULL;
2552         if (*p == '%') {
2553                 pathopt = ++p;
2554                 while (*p && *p != ':')
2555                         p++;
2556         }
2557         if (*p == ':')
2558                 *path = p + 1;
2559         else
2560                 *path = NULL;
2561         return stalloc(len);
2562 }
2563
2564
2565 /* ============ Prompt */
2566
2567 static smallint doprompt;                   /* if set, prompt the user */
2568 static smallint needprompt;                 /* true if interactive and at start of line */
2569
2570 #if ENABLE_FEATURE_EDITING
2571 static line_input_t *line_input_state;
2572 static const char *cmdedit_prompt;
2573 static void
2574 putprompt(const char *s)
2575 {
2576         if (ENABLE_ASH_EXPAND_PRMT) {
2577                 free((char*)cmdedit_prompt);
2578                 cmdedit_prompt = ckstrdup(s);
2579                 return;
2580         }
2581         cmdedit_prompt = s;
2582 }
2583 #else
2584 static void
2585 putprompt(const char *s)
2586 {
2587         out2str(s);
2588 }
2589 #endif
2590
2591 /* expandstr() needs parsing machinery, so it is far away ahead... */
2592 static const char *expandstr(const char *ps, int syntax_type);
2593 /* Values for syntax param */
2594 #define BASESYNTAX 0    /* not in quotes */
2595 #define DQSYNTAX   1    /* in double quotes */
2596 #define SQSYNTAX   2    /* in single quotes */
2597 #define ARISYNTAX  3    /* in arithmetic */
2598 #if ENABLE_ASH_EXPAND_PRMT
2599 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2600 #endif
2601 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2602
2603 /*
2604  * called by editline -- any expansions to the prompt should be added here.
2605  */
2606 static void
2607 setprompt_if(smallint do_set, int whichprompt)
2608 {
2609         const char *prompt;
2610         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2611
2612         if (!do_set)
2613                 return;
2614
2615         needprompt = 0;
2616
2617         switch (whichprompt) {
2618         case 1:
2619                 prompt = ps1val();
2620                 break;
2621         case 2:
2622                 prompt = ps2val();
2623                 break;
2624         default:                        /* 0 */
2625                 prompt = nullstr;
2626         }
2627 #if ENABLE_ASH_EXPAND_PRMT
2628         pushstackmark(&smark, stackblocksize());
2629         putprompt(expandstr(prompt, PSSYNTAX));
2630         popstackmark(&smark);
2631 #else
2632         putprompt(prompt);
2633 #endif
2634 }
2635
2636
2637 /* ============ The cd and pwd commands */
2638
2639 #define CD_PHYSICAL 1
2640 #define CD_PRINT 2
2641
2642 static int
2643 cdopt(void)
2644 {
2645         int flags = 0;
2646         int i, j;
2647
2648         j = 'L';
2649         while ((i = nextopt("LP")) != '\0') {
2650                 if (i != j) {
2651                         flags ^= CD_PHYSICAL;
2652                         j = i;
2653                 }
2654         }
2655
2656         return flags;
2657 }
2658
2659 /*
2660  * Update curdir (the name of the current directory) in response to a
2661  * cd command.
2662  */
2663 static const char *
2664 updatepwd(const char *dir)
2665 {
2666         char *new;
2667         char *p;
2668         char *cdcomppath;
2669         const char *lim;
2670
2671         cdcomppath = sstrdup(dir);
2672         STARTSTACKSTR(new);
2673         if (*dir != '/') {
2674                 if (curdir == nullstr)
2675                         return 0;
2676                 new = stack_putstr(curdir, new);
2677         }
2678         new = makestrspace(strlen(dir) + 2, new);
2679         lim = (char *)stackblock() + 1;
2680         if (*dir != '/') {
2681                 if (new[-1] != '/')
2682                         USTPUTC('/', new);
2683                 if (new > lim && *lim == '/')
2684                         lim++;
2685         } else {
2686                 USTPUTC('/', new);
2687                 cdcomppath++;
2688                 if (dir[1] == '/' && dir[2] != '/') {
2689                         USTPUTC('/', new);
2690                         cdcomppath++;
2691                         lim++;
2692                 }
2693         }
2694         p = strtok(cdcomppath, "/");
2695         while (p) {
2696                 switch (*p) {
2697                 case '.':
2698                         if (p[1] == '.' && p[2] == '\0') {
2699                                 while (new > lim) {
2700                                         STUNPUTC(new);
2701                                         if (new[-1] == '/')
2702                                                 break;
2703                                 }
2704                                 break;
2705                         }
2706                         if (p[1] == '\0')
2707                                 break;
2708                         /* fall through */
2709                 default:
2710                         new = stack_putstr(p, new);
2711                         USTPUTC('/', new);
2712                 }
2713                 p = strtok(NULL, "/");
2714         }
2715         if (new > lim)
2716                 STUNPUTC(new);
2717         *new = 0;
2718         return stackblock();
2719 }
2720
2721 /*
2722  * Find out what the current directory is. If we already know the current
2723  * directory, this routine returns immediately.
2724  */
2725 static char *
2726 getpwd(void)
2727 {
2728         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2729         return dir ? dir : nullstr;
2730 }
2731
2732 static void
2733 setpwd(const char *val, int setold)
2734 {
2735         char *oldcur, *dir;
2736
2737         oldcur = dir = curdir;
2738
2739         if (setold) {
2740                 setvar("OLDPWD", oldcur, VEXPORT);
2741         }
2742         INT_OFF;
2743         if (physdir != nullstr) {
2744                 if (physdir != oldcur)
2745                         free(physdir);
2746                 physdir = nullstr;
2747         }
2748         if (oldcur == val || !val) {
2749                 char *s = getpwd();
2750                 physdir = s;
2751                 if (!val)
2752                         dir = s;
2753         } else
2754                 dir = ckstrdup(val);
2755         if (oldcur != dir && oldcur != nullstr) {
2756                 free(oldcur);
2757         }
2758         curdir = dir;
2759         INT_ON;
2760         setvar("PWD", dir, VEXPORT);
2761 }
2762
2763 static void hashcd(void);
2764
2765 /*
2766  * Actually do the chdir.  We also call hashcd to let other routines
2767  * know that the current directory has changed.
2768  */
2769 static int
2770 docd(const char *dest, int flags)
2771 {
2772         const char *dir = NULL;
2773         int err;
2774
2775         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2776
2777         INT_OFF;
2778         if (!(flags & CD_PHYSICAL)) {
2779                 dir = updatepwd(dest);
2780                 if (dir)
2781                         dest = dir;
2782         }
2783         err = chdir(dest);
2784         if (err)
2785                 goto out;
2786         setpwd(dir, 1);
2787         hashcd();
2788  out:
2789         INT_ON;
2790         return err;
2791 }
2792
2793 static int FAST_FUNC
2794 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2795 {
2796         const char *dest;
2797         const char *path;
2798         const char *p;
2799         char c;
2800         struct stat statb;
2801         int flags;
2802
2803         flags = cdopt();
2804         dest = *argptr;
2805         if (!dest)
2806                 dest = bltinlookup("HOME");
2807         else if (LONE_DASH(dest)) {
2808                 dest = bltinlookup("OLDPWD");
2809                 flags |= CD_PRINT;
2810         }
2811         if (!dest)
2812                 dest = nullstr;
2813         if (*dest == '/')
2814                 goto step6;
2815         if (*dest == '.') {
2816                 c = dest[1];
2817  dotdot:
2818                 switch (c) {
2819                 case '\0':
2820                 case '/':
2821                         goto step6;
2822                 case '.':
2823                         c = dest[2];
2824                         if (c != '.')
2825                                 goto dotdot;
2826                 }
2827         }
2828         if (!*dest)
2829                 dest = ".";
2830         path = bltinlookup("CDPATH");
2831         while (path) {
2832                 c = *path;
2833                 p = path_advance(&path, dest);
2834                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2835                         if (c && c != ':')
2836                                 flags |= CD_PRINT;
2837  docd:
2838                         if (!docd(p, flags))
2839                                 goto out;
2840                         goto err;
2841                 }
2842         }
2843
2844  step6:
2845         p = dest;
2846         goto docd;
2847
2848  err:
2849         ash_msg_and_raise_perror("can't cd to %s", dest);
2850         /* NOTREACHED */
2851  out:
2852         if (flags & CD_PRINT)
2853                 out1fmt("%s\n", curdir);
2854         return 0;
2855 }
2856
2857 static int FAST_FUNC
2858 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2859 {
2860         int flags;
2861         const char *dir = curdir;
2862
2863         flags = cdopt();
2864         if (flags) {
2865                 if (physdir == nullstr)
2866                         setpwd(dir, 0);
2867                 dir = physdir;
2868         }
2869         out1fmt("%s\n", dir);
2870         return 0;
2871 }
2872
2873
2874 /* ============ ... */
2875
2876
2877 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2878
2879 /* Syntax classes */
2880 #define CWORD     0             /* character is nothing special */
2881 #define CNL       1             /* newline character */
2882 #define CBACK     2             /* a backslash character */
2883 #define CSQUOTE   3             /* single quote */
2884 #define CDQUOTE   4             /* double quote */
2885 #define CENDQUOTE 5             /* a terminating quote */
2886 #define CBQUOTE   6             /* backwards single quote */
2887 #define CVAR      7             /* a dollar sign */
2888 #define CENDVAR   8             /* a '}' character */
2889 #define CLP       9             /* a left paren in arithmetic */
2890 #define CRP      10             /* a right paren in arithmetic */
2891 #define CENDFILE 11             /* end of file */
2892 #define CCTL     12             /* like CWORD, except it must be escaped */
2893 #define CSPCL    13             /* these terminate a word */
2894 #define CIGN     14             /* character should be ignored */
2895
2896 #define PEOF     256
2897 #if ENABLE_ASH_ALIAS
2898 # define PEOA    257
2899 #endif
2900
2901 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2902
2903 #if ENABLE_FEATURE_SH_MATH
2904 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2905 #else
2906 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2907 #endif
2908 static const uint16_t S_I_T[] ALIGN2 = {
2909 #if ENABLE_ASH_ALIAS
2910         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2911 #endif
2912         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2913         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2914         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2915         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2916         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2917         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2918         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2919         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2920         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2921         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2922         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2923 #if !USE_SIT_FUNCTION
2924         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2925         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2926         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2927 #endif
2928 #undef SIT_ITEM
2929 };
2930 /* Constants below must match table above */
2931 enum {
2932 #if ENABLE_ASH_ALIAS
2933         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2934 #endif
2935         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2936         CNL_CNL_CNL_CNL                    , /*  2 */
2937         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2938         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2939         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2940         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2941         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2942         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2943         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2944         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2945         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2946         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2947         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2948         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2949 };
2950
2951 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2952  * caller must ensure proper cast on it if c is *char_ptr!
2953  */
2954 #if USE_SIT_FUNCTION
2955
2956 static int
2957 SIT(int c, int syntax)
2958 {
2959         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2960         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2961         /*
2962          * This causes '/' to be prepended with CTLESC in dquoted string,
2963          * making "./file"* treated incorrectly because we feed
2964          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2965          * The "homegrown" glob implementation is okay with that,
2966          * but glibc one isn't. With '/' always treated as CWORD,
2967          * both work fine.
2968          */
2969 # if ENABLE_ASH_ALIAS
2970         static const uint8_t syntax_index_table[] ALIGN1 = {
2971                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2972                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2973                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2974                 11, 3                           /* "}~" */
2975         };
2976 # else
2977         static const uint8_t syntax_index_table[] ALIGN1 = {
2978                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2979                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2980                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2981                 10, 2                           /* "}~" */
2982         };
2983 # endif
2984         const char *s;
2985         int indx;
2986
2987         if (c == PEOF)
2988                 return CENDFILE;
2989 # if ENABLE_ASH_ALIAS
2990         if (c == PEOA)
2991                 indx = 0;
2992         else
2993 # endif
2994         {
2995                 /* Cast is purely for paranoia here,
2996                  * just in case someone passed signed char to us */
2997                 if ((unsigned char)c >= CTL_FIRST
2998                  && (unsigned char)c <= CTL_LAST
2999                 ) {
3000                         return CCTL;
3001                 }
3002                 s = strchrnul(spec_symbls, c);
3003                 if (*s == '\0')
3004                         return CWORD;
3005                 indx = syntax_index_table[s - spec_symbls];
3006         }
3007         return (S_I_T[indx] >> (syntax*4)) & 0xf;
3008 }
3009
3010 #else   /* !USE_SIT_FUNCTION */
3011
3012 static const uint8_t syntax_index_table[] ALIGN1 = {
3013         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
3014         /*   0      */ CWORD_CWORD_CWORD_CWORD,
3015         /*   1      */ CWORD_CWORD_CWORD_CWORD,
3016         /*   2      */ CWORD_CWORD_CWORD_CWORD,
3017         /*   3      */ CWORD_CWORD_CWORD_CWORD,
3018         /*   4      */ CWORD_CWORD_CWORD_CWORD,
3019         /*   5      */ CWORD_CWORD_CWORD_CWORD,
3020         /*   6      */ CWORD_CWORD_CWORD_CWORD,
3021         /*   7      */ CWORD_CWORD_CWORD_CWORD,
3022         /*   8      */ CWORD_CWORD_CWORD_CWORD,
3023         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
3024         /*  10 "\n" */ CNL_CNL_CNL_CNL,
3025         /*  11      */ CWORD_CWORD_CWORD_CWORD,
3026         /*  12      */ CWORD_CWORD_CWORD_CWORD,
3027         /*  13      */ CWORD_CWORD_CWORD_CWORD,
3028         /*  14      */ CWORD_CWORD_CWORD_CWORD,
3029         /*  15      */ CWORD_CWORD_CWORD_CWORD,
3030         /*  16      */ CWORD_CWORD_CWORD_CWORD,
3031         /*  17      */ CWORD_CWORD_CWORD_CWORD,
3032         /*  18      */ CWORD_CWORD_CWORD_CWORD,
3033         /*  19      */ CWORD_CWORD_CWORD_CWORD,
3034         /*  20      */ CWORD_CWORD_CWORD_CWORD,
3035         /*  21      */ CWORD_CWORD_CWORD_CWORD,
3036         /*  22      */ CWORD_CWORD_CWORD_CWORD,
3037         /*  23      */ CWORD_CWORD_CWORD_CWORD,
3038         /*  24      */ CWORD_CWORD_CWORD_CWORD,
3039         /*  25      */ CWORD_CWORD_CWORD_CWORD,
3040         /*  26      */ CWORD_CWORD_CWORD_CWORD,
3041         /*  27      */ CWORD_CWORD_CWORD_CWORD,
3042         /*  28      */ CWORD_CWORD_CWORD_CWORD,
3043         /*  29      */ CWORD_CWORD_CWORD_CWORD,
3044         /*  30      */ CWORD_CWORD_CWORD_CWORD,
3045         /*  31      */ CWORD_CWORD_CWORD_CWORD,
3046         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
3047         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
3048         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
3049         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
3050         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
3051         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
3052         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
3053         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
3054         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
3055         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
3056         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
3057         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
3058         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
3059         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
3060         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
3061 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
3062         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
3063         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
3064         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
3065         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
3066         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
3067         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
3068         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
3069         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
3070         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
3071         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
3072         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
3073         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
3074         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
3075         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
3076         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
3077         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
3078         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
3079         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
3080         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
3081         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
3082         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
3083         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
3084         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
3085         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
3086         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
3087         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
3088         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
3089         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
3090         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
3091         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
3092         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
3093         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
3094         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
3095         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
3096         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
3097         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
3098         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
3099         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
3100         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3101         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3102         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3103         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3104         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3105         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3106         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3107         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3108         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3109         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3110         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3111         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3112         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3113         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3114         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3115         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3116         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3117         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3118         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3119         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3120         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3121         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3122         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3123         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3124         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3125         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3126         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3127         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3128         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3129         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3130         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3131         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3132         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3133         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3134         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3135         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3136         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3137         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3138         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3139         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3140         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3141         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3142         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3143         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3144         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3145         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3146         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3147         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3148         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3149         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3150         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3151         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3152         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3165         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3166         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3167         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3168         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3169         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3170         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3171         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3172         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3173         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3174         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3175         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3176         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3177         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3178         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3179         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3180         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3181         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3182         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3183         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3184         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3185         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3186         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3187         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3188         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3189         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3190         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3191         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3192         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3193         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3194         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3195         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3196         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3197         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3198         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3199         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3200         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3201         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3202         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3203         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3204         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3205         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3206         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3207         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3208         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3209         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3210         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3211         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3212         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3213         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3214         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3215         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3216         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3217         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3218         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3219         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3220         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3221         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3222         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3223         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3224         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3225         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3226         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3227         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3228         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3229         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3230         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3231         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3232         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3233         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3234         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3235         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3236         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3237         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3238         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3239         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3240         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3241         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3242         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3243         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3244         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3245         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3246         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3247         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3248         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3249         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3250         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3251         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3252         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3253         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3254         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3255         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3256         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3257         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3258         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3259         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3260         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3261         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3262         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3263         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3264         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3265         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3266         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3267         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3268         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3269         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3270         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3271         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3272 # if ENABLE_ASH_ALIAS
3273         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3274 # endif
3275 };
3276
3277 #if 1
3278 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3279 #else /* debug version, caught one signed char bug */
3280 # define SIT(c, syntax) \
3281         ({ \
3282                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3283                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3284                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3285                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3286                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3287         })
3288 #endif
3289
3290 #endif  /* !USE_SIT_FUNCTION */
3291
3292
3293 /* ============ Alias handling */
3294
3295 #if ENABLE_ASH_ALIAS
3296
3297 #define ALIASINUSE 1
3298 #define ALIASDEAD  2
3299
3300 struct alias {
3301         struct alias *next;
3302         char *name;
3303         char *val;
3304         int flag;
3305 };
3306
3307
3308 static struct alias **atab; // [ATABSIZE];
3309 #define INIT_G_alias() do { \
3310         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3311 } while (0)
3312
3313
3314 static struct alias **
3315 __lookupalias(const char *name)
3316 {
3317         unsigned int hashval;
3318         struct alias **app;
3319         const char *p;
3320         unsigned int ch;
3321
3322         p = name;
3323
3324         ch = (unsigned char)*p;
3325         hashval = ch << 4;
3326         while (ch) {
3327                 hashval += ch;
3328                 ch = (unsigned char)*++p;
3329         }
3330         app = &atab[hashval % ATABSIZE];
3331
3332         for (; *app; app = &(*app)->next) {
3333                 if (strcmp(name, (*app)->name) == 0) {
3334                         break;
3335                 }
3336         }
3337
3338         return app;
3339 }
3340
3341 static struct alias *
3342 lookupalias(const char *name, int check)
3343 {
3344         struct alias *ap = *__lookupalias(name);
3345
3346         if (check && ap && (ap->flag & ALIASINUSE))
3347                 return NULL;
3348         return ap;
3349 }
3350
3351 static struct alias *
3352 freealias(struct alias *ap)
3353 {
3354         struct alias *next;
3355
3356         if (ap->flag & ALIASINUSE) {
3357                 ap->flag |= ALIASDEAD;
3358                 return ap;
3359         }
3360
3361         next = ap->next;
3362         free(ap->name);
3363         free(ap->val);
3364         free(ap);
3365         return next;
3366 }
3367
3368 static void
3369 setalias(const char *name, const char *val)
3370 {
3371         struct alias *ap, **app;
3372
3373         app = __lookupalias(name);
3374         ap = *app;
3375         INT_OFF;
3376         if (ap) {
3377                 if (!(ap->flag & ALIASINUSE)) {
3378                         free(ap->val);
3379                 }
3380                 ap->val = ckstrdup(val);
3381                 ap->flag &= ~ALIASDEAD;
3382         } else {
3383                 /* not found */
3384                 ap = ckzalloc(sizeof(struct alias));
3385                 ap->name = ckstrdup(name);
3386                 ap->val = ckstrdup(val);
3387                 /*ap->flag = 0; - ckzalloc did it */
3388                 /*ap->next = NULL;*/
3389                 *app = ap;
3390         }
3391         INT_ON;
3392 }
3393
3394 static int
3395 unalias(const char *name)
3396 {
3397         struct alias **app;
3398
3399         app = __lookupalias(name);
3400
3401         if (*app) {
3402                 INT_OFF;
3403                 *app = freealias(*app);
3404                 INT_ON;
3405                 return 0;
3406         }
3407
3408         return 1;
3409 }
3410
3411 static void
3412 rmaliases(void)
3413 {
3414         struct alias *ap, **app;
3415         int i;
3416
3417         INT_OFF;
3418         for (i = 0; i < ATABSIZE; i++) {
3419                 app = &atab[i];
3420                 for (ap = *app; ap; ap = *app) {
3421                         *app = freealias(*app);
3422                         if (ap == *app) {
3423                                 app = &ap->next;
3424                         }
3425                 }
3426         }
3427         INT_ON;
3428 }
3429
3430 static void
3431 printalias(const struct alias *ap)
3432 {
3433         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3434 }
3435
3436 /*
3437  * TODO - sort output
3438  */
3439 static int FAST_FUNC
3440 aliascmd(int argc UNUSED_PARAM, char **argv)
3441 {
3442         char *n, *v;
3443         int ret = 0;
3444         struct alias *ap;
3445
3446         if (!argv[1]) {
3447                 int i;
3448
3449                 for (i = 0; i < ATABSIZE; i++) {
3450                         for (ap = atab[i]; ap; ap = ap->next) {
3451                                 printalias(ap);
3452                         }
3453                 }
3454                 return 0;
3455         }
3456         while ((n = *++argv) != NULL) {
3457                 v = strchr(n+1, '=');
3458                 if (v == NULL) { /* n+1: funny ksh stuff */
3459                         ap = *__lookupalias(n);
3460                         if (ap == NULL) {
3461                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3462                                 ret = 1;
3463                         } else
3464                                 printalias(ap);
3465                 } else {
3466                         *v++ = '\0';
3467                         setalias(n, v);
3468                 }
3469         }
3470
3471         return ret;
3472 }
3473
3474 static int FAST_FUNC
3475 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3476 {
3477         int i;
3478
3479         while (nextopt("a") != '\0') {
3480                 rmaliases();
3481                 return 0;
3482         }
3483         for (i = 0; *argptr; argptr++) {
3484                 if (unalias(*argptr)) {
3485                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3486                         i = 1;
3487                 }
3488         }
3489
3490         return i;
3491 }
3492
3493 #endif /* ASH_ALIAS */
3494
3495
3496 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3497 #define FORK_FG    0
3498 #define FORK_BG    1
3499 #define FORK_NOJOB 2
3500
3501 /* mode flags for showjob(s) */
3502 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3503 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3504 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3505 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3506
3507 /*
3508  * A job structure contains information about a job.  A job is either a
3509  * single process or a set of processes contained in a pipeline.  In the
3510  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3511  * array of pids.
3512  */
3513 struct procstat {
3514         pid_t   ps_pid;         /* process id */
3515         int     ps_status;      /* last process status from wait() */
3516         char    *ps_cmd;        /* text of command being run */
3517 };
3518
3519 struct job {
3520         struct procstat ps0;    /* status of process */
3521         struct procstat *ps;    /* status or processes when more than one */
3522 #if JOBS
3523         int stopstatus;         /* status of a stopped job */
3524 #endif
3525         unsigned nprocs;        /* number of processes */
3526
3527 #define JOBRUNNING      0       /* at least one proc running */
3528 #define JOBSTOPPED      1       /* all procs are stopped */
3529 #define JOBDONE         2       /* all procs are completed */
3530         unsigned
3531                 state: 8,
3532 #if JOBS
3533                 sigint: 1,      /* job was killed by SIGINT */
3534                 jobctl: 1,      /* job running under job control */
3535 #endif
3536                 waited: 1,      /* true if this entry has been waited for */
3537                 used: 1,        /* true if this entry is in used */
3538                 changed: 1;     /* true if status has changed */
3539         struct job *prev_job;   /* previous job */
3540 };
3541
3542 static struct job *makejob(/*union node *,*/ int);
3543 static int forkshell(struct job *, union node *, int);
3544 static int waitforjob(struct job *);
3545
3546 #if !JOBS
3547 enum { doing_jobctl = 0 };
3548 #define setjobctl(on) do {} while (0)
3549 #else
3550 static smallint doing_jobctl; //references:8
3551 static void setjobctl(int);
3552 #endif
3553
3554 /*
3555  * Ignore a signal.
3556  */
3557 static void
3558 ignoresig(int signo)
3559 {
3560         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3561         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3562                 /* No, need to do it */
3563                 signal(signo, SIG_IGN);
3564         }
3565         sigmode[signo - 1] = S_HARD_IGN;
3566 }
3567
3568 /*
3569  * Only one usage site - in setsignal()
3570  */
3571 static void
3572 signal_handler(int signo)
3573 {
3574         if (signo == SIGCHLD) {
3575                 got_sigchld = 1;
3576                 if (!trap[SIGCHLD])
3577                         return;
3578         }
3579
3580         gotsig[signo - 1] = 1;
3581         pending_sig = signo;
3582
3583         if (signo == SIGINT && !trap[SIGINT]) {
3584                 if (!suppress_int) {
3585                         pending_sig = 0;
3586                         raise_interrupt(); /* does not return */
3587                 }
3588                 pending_int = 1;
3589         }
3590 }
3591
3592 /*
3593  * Set the signal handler for the specified signal.  The routine figures
3594  * out what it should be set to.
3595  */
3596 static void
3597 setsignal(int signo)
3598 {
3599         char *t;
3600         char cur_act, new_act;
3601         struct sigaction act;
3602
3603         t = trap[signo];
3604         new_act = S_DFL;
3605         if (t != NULL) { /* trap for this sig is set */
3606                 new_act = S_CATCH;
3607                 if (t[0] == '\0') /* trap is "": ignore this sig */
3608                         new_act = S_IGN;
3609         }
3610
3611         if (rootshell && new_act == S_DFL) {
3612                 switch (signo) {
3613                 case SIGINT:
3614                         if (iflag || minusc || sflag == 0)
3615                                 new_act = S_CATCH;
3616                         break;
3617                 case SIGQUIT:
3618 #if DEBUG
3619                         if (debug)
3620                                 break;
3621 #endif
3622                         /* man bash:
3623                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3624                          * commands run by bash have signal handlers
3625                          * set to the values inherited by the shell
3626                          * from its parent". */
3627                         new_act = S_IGN;
3628                         break;
3629                 case SIGTERM:
3630                         if (iflag)
3631                                 new_act = S_IGN;
3632                         break;
3633 #if JOBS
3634                 case SIGTSTP:
3635                 case SIGTTOU:
3636                         if (mflag)
3637                                 new_act = S_IGN;
3638                         break;
3639 #endif
3640                 }
3641         }
3642         /* if !rootshell, we reset SIGQUIT to DFL,
3643          * whereas we have to restore it to what shell got on entry.
3644          * This is handled by the fact that if signal was IGNored on entry,
3645          * then cur_act is S_HARD_IGN and we never change its sigaction
3646          * (see code below).
3647          */
3648
3649         if (signo == SIGCHLD)
3650                 new_act = S_CATCH;
3651
3652         t = &sigmode[signo - 1];
3653         cur_act = *t;
3654         if (cur_act == 0) {
3655                 /* current setting is not yet known */
3656                 if (sigaction(signo, NULL, &act)) {
3657                         /* pretend it worked; maybe we should give a warning,
3658                          * but other shells don't. We don't alter sigmode,
3659                          * so we retry every time.
3660                          * btw, in Linux it never fails. --vda */
3661                         return;
3662                 }
3663                 if (act.sa_handler == SIG_IGN) {
3664                         cur_act = S_HARD_IGN;
3665                         if (mflag
3666                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3667                         ) {
3668                                 cur_act = S_IGN;   /* don't hard ignore these */
3669                         }
3670                 }
3671                 if (act.sa_handler == SIG_DFL && new_act == S_DFL) {
3672                         /* installing SIG_DFL over SIG_DFL is a no-op */
3673                         /* saves one sigaction call in each "sh -c SCRIPT" invocation */
3674                         *t = S_DFL;
3675                         return;
3676                 }
3677         }
3678         if (cur_act == S_HARD_IGN || cur_act == new_act)
3679                 return;
3680
3681         *t = new_act;
3682
3683         act.sa_handler = SIG_DFL;
3684         switch (new_act) {
3685         case S_CATCH:
3686                 act.sa_handler = signal_handler;
3687                 break;
3688         case S_IGN:
3689                 act.sa_handler = SIG_IGN;
3690                 break;
3691         }
3692         /* flags and mask matter only if !DFL and !IGN, but we do it
3693          * for all cases for more deterministic behavior:
3694          */
3695         act.sa_flags = 0; //TODO: why not SA_RESTART?
3696         sigfillset(&act.sa_mask);
3697
3698         sigaction_set(signo, &act);
3699 }
3700
3701 /* mode flags for set_curjob */
3702 #define CUR_DELETE 2
3703 #define CUR_RUNNING 1
3704 #define CUR_STOPPED 0
3705
3706 #if JOBS
3707 /* pgrp of shell on invocation */
3708 static int initialpgrp; //references:2
3709 static int ttyfd = -1; //5
3710 #endif
3711 /* array of jobs */
3712 static struct job *jobtab; //5
3713 /* size of array */
3714 static unsigned njobs; //4
3715 /* current job */
3716 static struct job *curjob; //lots
3717 /* number of presumed living untracked jobs */
3718 static int jobless; //4
3719
3720 #if 0
3721 /* Bash has a feature: it restores termios after a successful wait for
3722  * a foreground job which had at least one stopped or sigkilled member.
3723  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3724  * properly restoring tty state. Should we do this too?
3725  * A reproducer: ^Z an interactive python:
3726  *
3727  * # python
3728  * Python 2.7.12 (...)
3729  * >>> ^Z
3730  *      { python leaves tty in -icanon -echo state. We do survive that... }
3731  *  [1]+  Stopped                    python
3732  *      { ...however, next program (python #2) does not survive it well: }
3733  * # python
3734  * Python 2.7.12 (...)
3735  * >>> Traceback (most recent call last):
3736  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3737  *   File "<stdin>", line 1, in <module>
3738  * NameError: name 'qwerty' is not defined
3739  *
3740  * The implementation below is modeled on bash code and seems to work.
3741  * However, I'm not sure we should do this. For one: what if I'd fg
3742  * the stopped python instead? It'll be confused by "restored" tty state.
3743  */
3744 static struct termios shell_tty_info;
3745 static void
3746 get_tty_state(void)
3747 {
3748         if (rootshell && ttyfd >= 0)
3749                 tcgetattr(ttyfd, &shell_tty_info);
3750 }
3751 static void
3752 set_tty_state(void)
3753 {
3754         /* if (rootshell) - caller ensures this */
3755         if (ttyfd >= 0)
3756                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3757 }
3758 static int
3759 job_signal_status(struct job *jp)
3760 {
3761         int status;
3762         unsigned i;
3763         struct procstat *ps = jp->ps;
3764         for (i = 0; i < jp->nprocs; i++) {
3765                 status = ps[i].ps_status;
3766                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3767                         return status;
3768         }
3769         return 0;
3770 }
3771 static void
3772 restore_tty_if_stopped_or_signaled(struct job *jp)
3773 {
3774 //TODO: check what happens if we come from waitforjob() in expbackq()
3775         if (rootshell) {
3776                 int s = job_signal_status(jp);
3777                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3778                         set_tty_state();
3779         }
3780 }
3781 #else
3782 # define get_tty_state() ((void)0)
3783 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3784 #endif
3785
3786 static void
3787 set_curjob(struct job *jp, unsigned mode)
3788 {
3789         struct job *jp1;
3790         struct job **jpp, **curp;
3791
3792         /* first remove from list */
3793         jpp = curp = &curjob;
3794         while (1) {
3795                 jp1 = *jpp;
3796                 if (jp1 == jp)
3797                         break;
3798                 jpp = &jp1->prev_job;
3799         }
3800         *jpp = jp1->prev_job;
3801
3802         /* Then re-insert in correct position */
3803         jpp = curp;
3804         switch (mode) {
3805         default:
3806 #if DEBUG
3807                 abort();
3808 #endif
3809         case CUR_DELETE:
3810                 /* job being deleted */
3811                 break;
3812         case CUR_RUNNING:
3813                 /* newly created job or backgrounded job,
3814                  * put after all stopped jobs.
3815                  */
3816                 while (1) {
3817                         jp1 = *jpp;
3818 #if JOBS
3819                         if (!jp1 || jp1->state != JOBSTOPPED)
3820 #endif
3821                                 break;
3822                         jpp = &jp1->prev_job;
3823                 }
3824                 /* FALLTHROUGH */
3825 #if JOBS
3826         case CUR_STOPPED:
3827 #endif
3828                 /* newly stopped job - becomes curjob */
3829                 jp->prev_job = *jpp;
3830                 *jpp = jp;
3831                 break;
3832         }
3833 }
3834
3835 #if JOBS || DEBUG
3836 static int
3837 jobno(const struct job *jp)
3838 {
3839         return jp - jobtab + 1;
3840 }
3841 #endif
3842
3843 /*
3844  * Convert a job name to a job structure.
3845  */
3846 #if !JOBS
3847 #define getjob(name, getctl) getjob(name)
3848 #endif
3849 static struct job *
3850 getjob(const char *name, int getctl)
3851 {
3852         struct job *jp;
3853         struct job *found;
3854         const char *err_msg = "%s: no such job";
3855         unsigned num;
3856         int c;
3857         const char *p;
3858         char *(*match)(const char *, const char *);
3859
3860         jp = curjob;
3861         p = name;
3862         if (!p)
3863                 goto currentjob;
3864
3865         if (*p != '%')
3866                 goto err;
3867
3868         c = *++p;
3869         if (!c)
3870                 goto currentjob;
3871
3872         if (!p[1]) {
3873                 if (c == '+' || c == '%') {
3874  currentjob:
3875                         err_msg = "No current job";
3876                         goto check;
3877                 }
3878                 if (c == '-') {
3879                         if (jp)
3880                                 jp = jp->prev_job;
3881                         err_msg = "No previous job";
3882  check:
3883                         if (!jp)
3884                                 goto err;
3885                         goto gotit;
3886                 }
3887         }
3888
3889         if (is_number(p)) {
3890                 num = atoi(p);
3891                 if (num > 0 && num <= njobs) {
3892                         jp = jobtab + num - 1;
3893                         if (jp->used)
3894                                 goto gotit;
3895                         goto err;
3896                 }
3897         }
3898
3899         match = prefix;
3900         if (*p == '?') {
3901                 match = strstr;
3902                 p++;
3903         }
3904
3905         found = NULL;
3906         while (jp) {
3907                 if (match(jp->ps[0].ps_cmd, p)) {
3908                         if (found)
3909                                 goto err;
3910                         found = jp;
3911                         err_msg = "%s: ambiguous";
3912                 }
3913                 jp = jp->prev_job;
3914         }
3915         if (!found)
3916                 goto err;
3917         jp = found;
3918
3919  gotit:
3920 #if JOBS
3921         err_msg = "job %s not created under job control";
3922         if (getctl && jp->jobctl == 0)
3923                 goto err;
3924 #endif
3925         return jp;
3926  err:
3927         ash_msg_and_raise_error(err_msg, name);
3928 }
3929
3930 /*
3931  * Mark a job structure as unused.
3932  */
3933 static void
3934 freejob(struct job *jp)
3935 {
3936         struct procstat *ps;
3937         int i;
3938
3939         INT_OFF;
3940         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3941                 if (ps->ps_cmd != nullstr)
3942                         free(ps->ps_cmd);
3943         }
3944         if (jp->ps != &jp->ps0)
3945                 free(jp->ps);
3946         jp->used = 0;
3947         set_curjob(jp, CUR_DELETE);
3948         INT_ON;
3949 }
3950
3951 #if JOBS
3952 static void
3953 xtcsetpgrp(int fd, pid_t pgrp)
3954 {
3955         if (tcsetpgrp(fd, pgrp))
3956                 ash_msg_and_raise_perror("can't set tty process group");
3957 }
3958
3959 /*
3960  * Turn job control on and off.
3961  *
3962  * Note:  This code assumes that the third arg to ioctl is a character
3963  * pointer, which is true on Berkeley systems but not System V.  Since
3964  * System V doesn't have job control yet, this isn't a problem now.
3965  *
3966  * Called with interrupts off.
3967  */
3968 static void
3969 setjobctl(int on)
3970 {
3971         int fd;
3972         int pgrp;
3973
3974         if (on == doing_jobctl || rootshell == 0)
3975                 return;
3976         if (on) {
3977                 int ofd;
3978                 ofd = fd = open(_PATH_TTY, O_RDWR);
3979                 if (fd < 0) {
3980         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3981          * That sometimes helps to acquire controlling tty.
3982          * Obviously, a workaround for bugs when someone
3983          * failed to provide a controlling tty to bash! :) */
3984                         fd = 2;
3985                         while (!isatty(fd))
3986                                 if (--fd < 0)
3987                                         goto out;
3988                 }
3989                 /* fd is a tty at this point */
3990                 fd = fcntl(fd, F_DUPFD_CLOEXEC, 10);
3991                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3992                         close(ofd);
3993                 if (fd < 0)
3994                         goto out; /* F_DUPFD failed */
3995                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
3996                         close_on_exec_on(fd);
3997                 while (1) { /* while we are in the background */
3998                         pgrp = tcgetpgrp(fd);
3999                         if (pgrp < 0) {
4000  out:
4001                                 ash_msg("can't access tty; job control turned off");
4002                                 mflag = on = 0;
4003                                 goto close;
4004                         }
4005                         if (pgrp == getpgrp())
4006                                 break;
4007                         killpg(0, SIGTTIN);
4008                 }
4009                 initialpgrp = pgrp;
4010
4011                 setsignal(SIGTSTP);
4012                 setsignal(SIGTTOU);
4013                 setsignal(SIGTTIN);
4014                 pgrp = rootpid;
4015                 setpgid(0, pgrp);
4016                 xtcsetpgrp(fd, pgrp);
4017         } else {
4018                 /* turning job control off */
4019                 fd = ttyfd;
4020                 pgrp = initialpgrp;
4021                 /* was xtcsetpgrp, but this can make exiting ash
4022                  * loop forever if pty is already deleted */
4023                 tcsetpgrp(fd, pgrp);
4024                 setpgid(0, pgrp);
4025                 setsignal(SIGTSTP);
4026                 setsignal(SIGTTOU);
4027                 setsignal(SIGTTIN);
4028  close:
4029                 if (fd >= 0)
4030                         close(fd);
4031                 fd = -1;
4032         }
4033         ttyfd = fd;
4034         doing_jobctl = on;
4035 }
4036
4037 static int FAST_FUNC
4038 killcmd(int argc, char **argv)
4039 {
4040         if (argv[1] && strcmp(argv[1], "-l") != 0) {
4041                 int i = 1;
4042                 do {
4043                         if (argv[i][0] == '%') {
4044                                 /*
4045                                  * "kill %N" - job kill
4046                                  * Converting to pgrp / pid kill
4047                                  */
4048                                 struct job *jp;
4049                                 char *dst;
4050                                 int j, n;
4051
4052                                 jp = getjob(argv[i], 0);
4053                                 /*
4054                                  * In jobs started under job control, we signal
4055                                  * entire process group by kill -PGRP_ID.
4056                                  * This happens, f.e., in interactive shell.
4057                                  *
4058                                  * Otherwise, we signal each child via
4059                                  * kill PID1 PID2 PID3.
4060                                  * Testcases:
4061                                  * sh -c 'sleep 1|sleep 1 & kill %1'
4062                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
4063                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
4064                                  */
4065                                 n = jp->nprocs; /* can't be 0 (I hope) */
4066                                 if (jp->jobctl)
4067                                         n = 1;
4068                                 dst = alloca(n * sizeof(int)*4);
4069                                 argv[i] = dst;
4070                                 for (j = 0; j < n; j++) {
4071                                         struct procstat *ps = &jp->ps[j];
4072                                         /* Skip non-running and not-stopped members
4073                                          * (i.e. dead members) of the job
4074                                          */
4075                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
4076                                                 continue;
4077                                         /*
4078                                          * kill_main has matching code to expect
4079                                          * leading space. Needed to not confuse
4080                                          * negative pids with "kill -SIGNAL_NO" syntax
4081                                          */
4082                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
4083                                 }
4084                                 *dst = '\0';
4085                         }
4086                 } while (argv[++i]);
4087         }
4088         return kill_main(argc, argv);
4089 }
4090
4091 static void
4092 showpipe(struct job *jp /*, FILE *out*/)
4093 {
4094         struct procstat *ps;
4095         struct procstat *psend;
4096
4097         psend = jp->ps + jp->nprocs;
4098         for (ps = jp->ps + 1; ps < psend; ps++)
4099                 printf(" | %s", ps->ps_cmd);
4100         newline_and_flush(stdout);
4101         flush_stdout_stderr();
4102 }
4103
4104
4105 static int
4106 restartjob(struct job *jp, int mode)
4107 {
4108         struct procstat *ps;
4109         int i;
4110         int status;
4111         pid_t pgid;
4112
4113         INT_OFF;
4114         if (jp->state == JOBDONE)
4115                 goto out;
4116         jp->state = JOBRUNNING;
4117         pgid = jp->ps[0].ps_pid;
4118         if (mode == FORK_FG) {
4119                 get_tty_state();
4120                 xtcsetpgrp(ttyfd, pgid);
4121         }
4122         killpg(pgid, SIGCONT);
4123         ps = jp->ps;
4124         i = jp->nprocs;
4125         do {
4126                 if (WIFSTOPPED(ps->ps_status)) {
4127                         ps->ps_status = -1;
4128                 }
4129                 ps++;
4130         } while (--i);
4131  out:
4132         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4133         INT_ON;
4134         return status;
4135 }
4136
4137 static int FAST_FUNC
4138 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4139 {
4140         struct job *jp;
4141         int mode;
4142         int retval;
4143
4144         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4145         nextopt(nullstr);
4146         argv = argptr;
4147         do {
4148                 jp = getjob(*argv, 1);
4149                 if (mode == FORK_BG) {
4150                         set_curjob(jp, CUR_RUNNING);
4151                         printf("[%d] ", jobno(jp));
4152                 }
4153                 out1str(jp->ps[0].ps_cmd);
4154                 showpipe(jp /*, stdout*/);
4155                 retval = restartjob(jp, mode);
4156         } while (*argv && *++argv);
4157         return retval;
4158 }
4159 #endif
4160
4161 static int
4162 sprint_status48(char *s, int status, int sigonly)
4163 {
4164         int col;
4165         int st;
4166
4167         col = 0;
4168         if (!WIFEXITED(status)) {
4169 #if JOBS
4170                 if (WIFSTOPPED(status))
4171                         st = WSTOPSIG(status);
4172                 else
4173 #endif
4174                         st = WTERMSIG(status);
4175                 if (sigonly) {
4176                         if (st == SIGINT || st == SIGPIPE)
4177                                 goto out;
4178 #if JOBS
4179                         if (WIFSTOPPED(status))
4180                                 goto out;
4181 #endif
4182                 }
4183                 st &= 0x7f;
4184 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4185                 col = fmtstr(s, 32, strsignal(st));
4186                 if (WCOREDUMP(status)) {
4187                         strcpy(s + col, " (core dumped)");
4188                         col += sizeof(" (core dumped)")-1;
4189                 }
4190         } else if (!sigonly) {
4191                 st = WEXITSTATUS(status);
4192                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4193         }
4194  out:
4195         return col;
4196 }
4197
4198 static int
4199 wait_block_or_sig(int *status)
4200 {
4201         int pid;
4202
4203         do {
4204                 sigset_t mask;
4205
4206                 /* Poll all children for changes in their state */
4207                 got_sigchld = 0;
4208                 /* if job control is active, accept stopped processes too */
4209                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4210                 if (pid != 0)
4211                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4212
4213                 /* Children exist, but none are ready. Sleep until interesting signal */
4214 #if 1
4215                 sigfillset(&mask);
4216                 sigprocmask(SIG_SETMASK, &mask, &mask);
4217                 while (!got_sigchld && !pending_sig)
4218                         sigsuspend(&mask);
4219                 sigprocmask(SIG_SETMASK, &mask, NULL);
4220 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4221                 while (!got_sigchld && !pending_sig)
4222                         pause();
4223 #endif
4224
4225                 /* If it was SIGCHLD, poll children again */
4226         } while (got_sigchld);
4227
4228         return pid;
4229 }
4230
4231 #define DOWAIT_NONBLOCK 0
4232 #define DOWAIT_BLOCK    1
4233 #define DOWAIT_BLOCK_OR_SIG 2
4234
4235 static int
4236 dowait(int block, struct job *job)
4237 {
4238         int pid;
4239         int status;
4240         struct job *jp;
4241         struct job *thisjob = NULL;
4242
4243         TRACE(("dowait(0x%x) called\n", block));
4244
4245         /* It's wrong to call waitpid() outside of INT_OFF region:
4246          * signal can arrive just after syscall return and handler can
4247          * longjmp away, losing stop/exit notification processing.
4248          * Thus, for "jobs" builtin, and for waiting for a fg job,
4249          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4250          *
4251          * However, for "wait" builtin it is wrong to simply call waitpid()
4252          * in INT_OFF region: "wait" needs to wait for any running job
4253          * to change state, but should exit on any trap too.
4254          * In INT_OFF region, a signal just before syscall entry can set
4255          * pending_sig variables, but we can't check them, and we would
4256          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4257          *
4258          * Because of this, we run inside INT_OFF, but use a special routine
4259          * which combines waitpid() and sigsuspend().
4260          * This is the reason why we need to have a handler for SIGCHLD:
4261          * SIG_DFL handler does not wake sigsuspend().
4262          */
4263         INT_OFF;
4264         if (block == DOWAIT_BLOCK_OR_SIG) {
4265                 pid = wait_block_or_sig(&status);
4266         } else {
4267                 int wait_flags = 0;
4268                 if (block == DOWAIT_NONBLOCK)
4269                         wait_flags = WNOHANG;
4270                 /* if job control is active, accept stopped processes too */
4271                 if (doing_jobctl)
4272                         wait_flags |= WUNTRACED;
4273                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4274                 pid = waitpid(-1, &status, wait_flags);
4275         }
4276         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4277                                 pid, status, errno, strerror(errno)));
4278         if (pid <= 0)
4279                 goto out;
4280
4281         thisjob = NULL;
4282         for (jp = curjob; jp; jp = jp->prev_job) {
4283                 int jobstate;
4284                 struct procstat *ps;
4285                 struct procstat *psend;
4286                 if (jp->state == JOBDONE)
4287                         continue;
4288                 jobstate = JOBDONE;
4289                 ps = jp->ps;
4290                 psend = ps + jp->nprocs;
4291                 do {
4292                         if (ps->ps_pid == pid) {
4293                                 TRACE(("Job %d: changing status of proc %d "
4294                                         "from 0x%x to 0x%x\n",
4295                                         jobno(jp), pid, ps->ps_status, status));
4296                                 ps->ps_status = status;
4297                                 thisjob = jp;
4298                         }
4299                         if (ps->ps_status == -1)
4300                                 jobstate = JOBRUNNING;
4301 #if JOBS
4302                         if (jobstate == JOBRUNNING)
4303                                 continue;
4304                         if (WIFSTOPPED(ps->ps_status)) {
4305                                 jp->stopstatus = ps->ps_status;
4306                                 jobstate = JOBSTOPPED;
4307                         }
4308 #endif
4309                 } while (++ps < psend);
4310                 if (!thisjob)
4311                         continue;
4312
4313                 /* Found the job where one of its processes changed its state.
4314                  * Is there at least one live and running process in this job? */
4315                 if (jobstate != JOBRUNNING) {
4316                         /* No. All live processes in the job are stopped
4317                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4318                          */
4319                         thisjob->changed = 1;
4320                         if (thisjob->state != jobstate) {
4321                                 TRACE(("Job %d: changing state from %d to %d\n",
4322                                         jobno(thisjob), thisjob->state, jobstate));
4323                                 thisjob->state = jobstate;
4324 #if JOBS
4325                                 if (jobstate == JOBSTOPPED)
4326                                         set_curjob(thisjob, CUR_STOPPED);
4327 #endif
4328                         }
4329                 }
4330                 goto out;
4331         }
4332         /* The process wasn't found in job list */
4333 #if JOBS
4334         if (!WIFSTOPPED(status))
4335                 jobless--;
4336 #endif
4337  out:
4338         INT_ON;
4339
4340         if (thisjob && thisjob == job) {
4341                 char s[48 + 1];
4342                 int len;
4343
4344                 len = sprint_status48(s, status, 1);
4345                 if (len) {
4346                         s[len] = '\n';
4347                         s[len + 1] = '\0';
4348                         out2str(s);
4349                 }
4350         }
4351         return pid;
4352 }
4353
4354 #if JOBS
4355 static void
4356 showjob(struct job *jp, int mode)
4357 {
4358         struct procstat *ps;
4359         struct procstat *psend;
4360         int col;
4361         int indent_col;
4362         char s[16 + 16 + 48];
4363         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4364
4365         ps = jp->ps;
4366
4367         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4368                 /* just output process (group) id of pipeline */
4369                 fprintf(out, "%d\n", ps->ps_pid);
4370                 return;
4371         }
4372
4373         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4374         indent_col = col;
4375
4376         if (jp == curjob)
4377                 s[col - 3] = '+';
4378         else if (curjob && jp == curjob->prev_job)
4379                 s[col - 3] = '-';
4380
4381         if (mode & SHOW_PIDS)
4382                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4383
4384         psend = ps + jp->nprocs;
4385
4386         if (jp->state == JOBRUNNING) {
4387                 strcpy(s + col, "Running");
4388                 col += sizeof("Running") - 1;
4389         } else {
4390                 int status = psend[-1].ps_status;
4391                 if (jp->state == JOBSTOPPED)
4392                         status = jp->stopstatus;
4393                 col += sprint_status48(s + col, status, 0);
4394         }
4395         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4396
4397         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4398          * or prints several "PID             | <cmdN>" lines,
4399          * depending on SHOW_PIDS bit.
4400          * We do not print status of individual processes
4401          * between PID and <cmdN>. bash does it, but not very well:
4402          * first line shows overall job status, not process status,
4403          * making it impossible to know 1st process status.
4404          */
4405         goto start;
4406         do {
4407                 /* for each process */
4408                 s[0] = '\0';
4409                 col = 33;
4410                 if (mode & SHOW_PIDS)
4411                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4412  start:
4413                 fprintf(out, "%s%*c%s%s",
4414                                 s,
4415                                 33 - col >= 0 ? 33 - col : 0, ' ',
4416                                 ps == jp->ps ? "" : "| ",
4417                                 ps->ps_cmd
4418                 );
4419         } while (++ps != psend);
4420         newline_and_flush(out);
4421
4422         jp->changed = 0;
4423
4424         if (jp->state == JOBDONE) {
4425                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4426                 freejob(jp);
4427         }
4428 }
4429
4430 /*
4431  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4432  * statuses have changed since the last call to showjobs.
4433  */
4434 static void
4435 showjobs(int mode)
4436 {
4437         struct job *jp;
4438
4439         TRACE(("showjobs(0x%x) called\n", mode));
4440
4441         /* Handle all finished jobs */
4442         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4443                 continue;
4444
4445         for (jp = curjob; jp; jp = jp->prev_job) {
4446                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4447                         showjob(jp, mode);
4448                 }
4449         }
4450 }
4451
4452 static int FAST_FUNC
4453 jobscmd(int argc UNUSED_PARAM, char **argv)
4454 {
4455         int mode, m;
4456
4457         mode = 0;
4458         while ((m = nextopt("lp")) != '\0') {
4459                 if (m == 'l')
4460                         mode |= SHOW_PIDS;
4461                 else
4462                         mode |= SHOW_ONLY_PGID;
4463         }
4464
4465         argv = argptr;
4466         if (*argv) {
4467                 do
4468                         showjob(getjob(*argv, 0), mode);
4469                 while (*++argv);
4470         } else {
4471                 showjobs(mode);
4472         }
4473
4474         return 0;
4475 }
4476 #endif /* JOBS */
4477
4478 /* Called only on finished or stopped jobs (no members are running) */
4479 static int
4480 getstatus(struct job *job)
4481 {
4482         int status;
4483         int retval;
4484         struct procstat *ps;
4485
4486         /* Fetch last member's status */
4487         ps = job->ps + job->nprocs - 1;
4488         status = ps->ps_status;
4489         if (pipefail) {
4490                 /* "set -o pipefail" mode: use last _nonzero_ status */
4491                 while (status == 0 && --ps >= job->ps)
4492                         status = ps->ps_status;
4493         }
4494
4495         retval = WEXITSTATUS(status);
4496         if (!WIFEXITED(status)) {
4497 #if JOBS
4498                 retval = WSTOPSIG(status);
4499                 if (!WIFSTOPPED(status))
4500 #endif
4501                 {
4502                         /* XXX: limits number of signals */
4503                         retval = WTERMSIG(status);
4504 #if JOBS
4505                         if (retval == SIGINT)
4506                                 job->sigint = 1;
4507 #endif
4508                 }
4509                 retval += 128;
4510         }
4511         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4512                 jobno(job), job->nprocs, status, retval));
4513         return retval;
4514 }
4515
4516 static int FAST_FUNC
4517 waitcmd(int argc UNUSED_PARAM, char **argv)
4518 {
4519         struct job *job;
4520         int retval;
4521         struct job *jp;
4522
4523         nextopt(nullstr);
4524         retval = 0;
4525
4526         argv = argptr;
4527         if (!*argv) {
4528                 /* wait for all jobs */
4529                 for (;;) {
4530                         jp = curjob;
4531                         while (1) {
4532                                 if (!jp) /* no running procs */
4533                                         goto ret;
4534                                 if (jp->state == JOBRUNNING)
4535                                         break;
4536                                 jp->waited = 1;
4537                                 jp = jp->prev_job;
4538                         }
4539         /* man bash:
4540          * "When bash is waiting for an asynchronous command via
4541          * the wait builtin, the reception of a signal for which a trap
4542          * has been set will cause the wait builtin to return immediately
4543          * with an exit status greater than 128, immediately after which
4544          * the trap is executed."
4545          */
4546                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4547         /* if child sends us a signal *and immediately exits*,
4548          * dowait() returns pid > 0. Check this case,
4549          * not "if (dowait() < 0)"!
4550          */
4551                         if (pending_sig)
4552                                 goto sigout;
4553                 }
4554         }
4555
4556         retval = 127;
4557         do {
4558                 if (**argv != '%') {
4559                         pid_t pid = number(*argv);
4560                         job = curjob;
4561                         while (1) {
4562                                 if (!job)
4563                                         goto repeat;
4564                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4565                                         break;
4566                                 job = job->prev_job;
4567                         }
4568                 } else {
4569                         job = getjob(*argv, 0);
4570                 }
4571                 /* loop until process terminated or stopped */
4572                 while (job->state == JOBRUNNING) {
4573                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4574                         if (pending_sig)
4575                                 goto sigout;
4576                 }
4577                 job->waited = 1;
4578                 retval = getstatus(job);
4579  repeat: ;
4580         } while (*++argv);
4581
4582  ret:
4583         return retval;
4584  sigout:
4585         retval = 128 + pending_sig;
4586         return retval;
4587 }
4588
4589 static struct job *
4590 growjobtab(void)
4591 {
4592         size_t len;
4593         ptrdiff_t offset;
4594         struct job *jp, *jq;
4595
4596         len = njobs * sizeof(*jp);
4597         jq = jobtab;
4598         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4599
4600         offset = (char *)jp - (char *)jq;
4601         if (offset) {
4602                 /* Relocate pointers */
4603                 size_t l = len;
4604
4605                 jq = (struct job *)((char *)jq + l);
4606                 while (l) {
4607                         l -= sizeof(*jp);
4608                         jq--;
4609 #define joff(p) ((struct job *)((char *)(p) + l))
4610 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4611                         if (joff(jp)->ps == &jq->ps0)
4612                                 jmove(joff(jp)->ps);
4613                         if (joff(jp)->prev_job)
4614                                 jmove(joff(jp)->prev_job);
4615                 }
4616                 if (curjob)
4617                         jmove(curjob);
4618 #undef joff
4619 #undef jmove
4620         }
4621
4622         njobs += 4;
4623         jobtab = jp;
4624         jp = (struct job *)((char *)jp + len);
4625         jq = jp + 3;
4626         do {
4627                 jq->used = 0;
4628         } while (--jq >= jp);
4629         return jp;
4630 }
4631
4632 /*
4633  * Return a new job structure.
4634  * Called with interrupts off.
4635  */
4636 static struct job *
4637 makejob(/*union node *node,*/ int nprocs)
4638 {
4639         int i;
4640         struct job *jp;
4641
4642         for (i = njobs, jp = jobtab; ; jp++) {
4643                 if (--i < 0) {
4644                         jp = growjobtab();
4645                         break;
4646                 }
4647                 if (jp->used == 0)
4648                         break;
4649                 if (jp->state != JOBDONE || !jp->waited)
4650                         continue;
4651 #if JOBS
4652                 if (doing_jobctl)
4653                         continue;
4654 #endif
4655                 freejob(jp);
4656                 break;
4657         }
4658         memset(jp, 0, sizeof(*jp));
4659 #if JOBS
4660         /* jp->jobctl is a bitfield.
4661          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4662         if (doing_jobctl)
4663                 jp->jobctl = 1;
4664 #endif
4665         jp->prev_job = curjob;
4666         curjob = jp;
4667         jp->used = 1;
4668         jp->ps = &jp->ps0;
4669         if (nprocs > 1) {
4670                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4671         }
4672         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4673                                 jobno(jp)));
4674         return jp;
4675 }
4676
4677 #if JOBS
4678 /*
4679  * Return a string identifying a command (to be printed by the
4680  * jobs command).
4681  */
4682 static char *cmdnextc;
4683
4684 static void
4685 cmdputs(const char *s)
4686 {
4687         static const char vstype[VSTYPE + 1][3] = {
4688                 "", "}", "-", "+", "?", "=",
4689                 "%", "%%", "#", "##"
4690                 IF_BASH_SUBSTR(, ":")
4691                 IF_BASH_PATTERN_SUBST(, "/", "//")
4692         };
4693
4694         const char *p, *str;
4695         char cc[2];
4696         char *nextc;
4697         unsigned char c;
4698         unsigned char subtype = 0;
4699         int quoted = 0;
4700
4701         cc[1] = '\0';
4702         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4703         p = s;
4704         while ((c = *p++) != '\0') {
4705                 str = NULL;
4706                 switch (c) {
4707                 case CTLESC:
4708                         c = *p++;
4709                         break;
4710                 case CTLVAR:
4711                         subtype = *p++;
4712                         if ((subtype & VSTYPE) == VSLENGTH)
4713                                 str = "${#";
4714                         else
4715                                 str = "${";
4716                         goto dostr;
4717                 case CTLENDVAR:
4718                         str = "\"}" + !(quoted & 1);
4719                         quoted >>= 1;
4720                         subtype = 0;
4721                         goto dostr;
4722                 case CTLBACKQ:
4723                         str = "$(...)";
4724                         goto dostr;
4725 #if ENABLE_FEATURE_SH_MATH
4726                 case CTLARI:
4727                         str = "$((";
4728                         goto dostr;
4729                 case CTLENDARI:
4730                         str = "))";
4731                         goto dostr;
4732 #endif
4733                 case CTLQUOTEMARK:
4734                         quoted ^= 1;
4735                         c = '"';
4736                         break;
4737                 case '=':
4738                         if (subtype == 0)
4739                                 break;
4740                         if ((subtype & VSTYPE) != VSNORMAL)
4741                                 quoted <<= 1;
4742                         str = vstype[subtype & VSTYPE];
4743                         if (subtype & VSNUL)
4744                                 c = ':';
4745                         else
4746                                 goto checkstr;
4747                         break;
4748                 case '\'':
4749                 case '\\':
4750                 case '"':
4751                 case '$':
4752                         /* These can only happen inside quotes */
4753                         cc[0] = c;
4754                         str = cc;
4755 //FIXME:
4756 // $ true $$ &
4757 // $ <cr>
4758 // [1]+  Done    true ${\$}   <<=== BUG: ${\$} is not a valid way to write $$ (${$} would be ok)
4759                         c = '\\';
4760                         break;
4761                 default:
4762                         break;
4763                 }
4764                 USTPUTC(c, nextc);
4765  checkstr:
4766                 if (!str)
4767                         continue;
4768  dostr:
4769                 while ((c = *str++) != '\0') {
4770                         USTPUTC(c, nextc);
4771                 }
4772         } /* while *p++ not NUL */
4773
4774         if (quoted & 1) {
4775                 USTPUTC('"', nextc);
4776         }
4777         *nextc = 0;
4778         cmdnextc = nextc;
4779 }
4780
4781 /* cmdtxt() and cmdlist() call each other */
4782 static void cmdtxt(union node *n);
4783
4784 static void
4785 cmdlist(union node *np, int sep)
4786 {
4787         for (; np; np = np->narg.next) {
4788                 if (!sep)
4789                         cmdputs(" ");
4790                 cmdtxt(np);
4791                 if (sep && np->narg.next)
4792                         cmdputs(" ");
4793         }
4794 }
4795
4796 static void
4797 cmdtxt(union node *n)
4798 {
4799         union node *np;
4800         struct nodelist *lp;
4801         const char *p;
4802
4803         if (!n)
4804                 return;
4805         switch (n->type) {
4806         default:
4807 #if DEBUG
4808                 abort();
4809 #endif
4810         case NPIPE:
4811                 lp = n->npipe.cmdlist;
4812                 for (;;) {
4813                         cmdtxt(lp->n);
4814                         lp = lp->next;
4815                         if (!lp)
4816                                 break;
4817                         cmdputs(" | ");
4818                 }
4819                 break;
4820         case NSEMI:
4821                 p = "; ";
4822                 goto binop;
4823         case NAND:
4824                 p = " && ";
4825                 goto binop;
4826         case NOR:
4827                 p = " || ";
4828  binop:
4829                 cmdtxt(n->nbinary.ch1);
4830                 cmdputs(p);
4831                 n = n->nbinary.ch2;
4832                 goto donode;
4833         case NREDIR:
4834         case NBACKGND:
4835                 n = n->nredir.n;
4836                 goto donode;
4837         case NNOT:
4838                 cmdputs("!");
4839                 n = n->nnot.com;
4840  donode:
4841                 cmdtxt(n);
4842                 break;
4843         case NIF:
4844                 cmdputs("if ");
4845                 cmdtxt(n->nif.test);
4846                 cmdputs("; then ");
4847                 if (n->nif.elsepart) {
4848                         cmdtxt(n->nif.ifpart);
4849                         cmdputs("; else ");
4850                         n = n->nif.elsepart;
4851                 } else {
4852                         n = n->nif.ifpart;
4853                 }
4854                 p = "; fi";
4855                 goto dotail;
4856         case NSUBSHELL:
4857                 cmdputs("(");
4858                 n = n->nredir.n;
4859                 p = ")";
4860                 goto dotail;
4861         case NWHILE:
4862                 p = "while ";
4863                 goto until;
4864         case NUNTIL:
4865                 p = "until ";
4866  until:
4867                 cmdputs(p);
4868                 cmdtxt(n->nbinary.ch1);
4869                 n = n->nbinary.ch2;
4870                 p = "; done";
4871  dodo:
4872                 cmdputs("; do ");
4873  dotail:
4874                 cmdtxt(n);
4875                 goto dotail2;
4876         case NFOR:
4877                 cmdputs("for ");
4878                 cmdputs(n->nfor.var);
4879                 cmdputs(" in ");
4880                 cmdlist(n->nfor.args, 1);
4881                 n = n->nfor.body;
4882                 p = "; done";
4883                 goto dodo;
4884         case NDEFUN:
4885                 cmdputs(n->ndefun.text);
4886                 p = "() { ... }";
4887                 goto dotail2;
4888         case NCMD:
4889                 cmdlist(n->ncmd.args, 1);
4890                 cmdlist(n->ncmd.redirect, 0);
4891                 break;
4892         case NARG:
4893                 p = n->narg.text;
4894  dotail2:
4895                 cmdputs(p);
4896                 break;
4897         case NHERE:
4898         case NXHERE:
4899                 p = "<<...";
4900                 goto dotail2;
4901         case NCASE:
4902                 cmdputs("case ");
4903                 cmdputs(n->ncase.expr->narg.text);
4904                 cmdputs(" in ");
4905                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4906                         cmdtxt(np->nclist.pattern);
4907                         cmdputs(") ");
4908                         cmdtxt(np->nclist.body);
4909                         cmdputs(";; ");
4910                 }
4911                 p = "esac";
4912                 goto dotail2;
4913         case NTO:
4914                 p = ">";
4915                 goto redir;
4916         case NCLOBBER:
4917                 p = ">|";
4918                 goto redir;
4919         case NAPPEND:
4920                 p = ">>";
4921                 goto redir;
4922 #if BASH_REDIR_OUTPUT
4923         case NTO2:
4924 #endif
4925         case NTOFD:
4926                 p = ">&";
4927                 goto redir;
4928         case NFROM:
4929                 p = "<";
4930                 goto redir;
4931         case NFROMFD:
4932                 p = "<&";
4933                 goto redir;
4934         case NFROMTO:
4935                 p = "<>";
4936  redir:
4937                 cmdputs(utoa(n->nfile.fd));
4938                 cmdputs(p);
4939                 if (n->type == NTOFD || n->type == NFROMFD) {
4940                         if (n->ndup.dupfd >= 0)
4941                                 cmdputs(utoa(n->ndup.dupfd));
4942                         else
4943                                 cmdputs("-");
4944                         break;
4945                 }
4946                 n = n->nfile.fname;
4947                 goto donode;
4948         }
4949 }
4950
4951 static char *
4952 commandtext(union node *n)
4953 {
4954         char *name;
4955
4956         STARTSTACKSTR(cmdnextc);
4957         cmdtxt(n);
4958         name = stackblock();
4959         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4960         return ckstrdup(name);
4961 }
4962 #endif /* JOBS */
4963
4964 /*
4965  * Fork off a subshell.  If we are doing job control, give the subshell its
4966  * own process group.  Jp is a job structure that the job is to be added to.
4967  * N is the command that will be evaluated by the child.  Both jp and n may
4968  * be NULL.  The mode parameter can be one of the following:
4969  *      FORK_FG - Fork off a foreground process.
4970  *      FORK_BG - Fork off a background process.
4971  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4972  *                   process group even if job control is on.
4973  *
4974  * When job control is turned off, background processes have their standard
4975  * input redirected to /dev/null (except for the second and later processes
4976  * in a pipeline).
4977  *
4978  * Called with interrupts off.
4979  */
4980 /*
4981  * Clear traps on a fork.
4982  */
4983 static void
4984 clear_traps(void)
4985 {
4986         char **tp;
4987
4988         INT_OFF;
4989         for (tp = trap; tp < &trap[NSIG]; tp++) {
4990                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4991                         if (trap_ptr == trap)
4992                                 free(*tp);
4993                         /* else: it "belongs" to trap_ptr vector, don't free */
4994                         *tp = NULL;
4995                         if ((tp - trap) != 0)
4996                                 setsignal(tp - trap);
4997                 }
4998         }
4999         may_have_traps = 0;
5000         INT_ON;
5001 }
5002
5003 /* Lives far away from here, needed for forkchild */
5004 static void closescript(void);
5005
5006 /* Called after fork(), in child */
5007 /* jp and n are NULL when called by openhere() for heredoc support */
5008 static NOINLINE void
5009 forkchild(struct job *jp, union node *n, int mode)
5010 {
5011         int oldlvl;
5012
5013         TRACE(("Child shell %d\n", getpid()));
5014         oldlvl = shlvl;
5015         shlvl++;
5016
5017         /* man bash: "Non-builtin commands run by bash have signal handlers
5018          * set to the values inherited by the shell from its parent".
5019          * Do we do it correctly? */
5020
5021         closescript();
5022
5023         if (mode == FORK_NOJOB          /* is it `xxx` ? */
5024          && n && n->type == NCMD        /* is it single cmd? */
5025         /* && n->ncmd.args->type == NARG - always true? */
5026          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
5027          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
5028         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
5029         ) {
5030                 TRACE(("Trap hack\n"));
5031                 /* Awful hack for `trap` or $(trap).
5032                  *
5033                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
5034                  * contains an example where "trap" is executed in a subshell:
5035                  *
5036                  * save_traps=$(trap)
5037                  * ...
5038                  * eval "$save_traps"
5039                  *
5040                  * Standard does not say that "trap" in subshell shall print
5041                  * parent shell's traps. It only says that its output
5042                  * must have suitable form, but then, in the above example
5043                  * (which is not supposed to be normative), it implies that.
5044                  *
5045                  * bash (and probably other shell) does implement it
5046                  * (traps are reset to defaults, but "trap" still shows them),
5047                  * but as a result, "trap" logic is hopelessly messed up:
5048                  *
5049                  * # trap
5050                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
5051                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
5052                  * # true | trap   <--- trap is in subshell - no output (ditto)
5053                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
5054                  * trap -- 'echo Ho' SIGWINCH
5055                  * # echo `(trap)`         <--- in subshell in subshell - output
5056                  * trap -- 'echo Ho' SIGWINCH
5057                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
5058                  * trap -- 'echo Ho' SIGWINCH
5059                  *
5060                  * The rules when to forget and when to not forget traps
5061                  * get really complex and nonsensical.
5062                  *
5063                  * Our solution: ONLY bare $(trap) or `trap` is special.
5064                  */
5065                 /* Save trap handler strings for trap builtin to print */
5066                 trap_ptr = xmemdup(trap, sizeof(trap));
5067                 /* Fall through into clearing traps */
5068         }
5069         clear_traps();
5070 #if JOBS
5071         /* do job control only in root shell */
5072         doing_jobctl = 0;
5073         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
5074                 pid_t pgrp;
5075
5076                 if (jp->nprocs == 0)
5077                         pgrp = getpid();
5078                 else
5079                         pgrp = jp->ps[0].ps_pid;
5080                 /* this can fail because we are doing it in the parent also */
5081                 setpgid(0, pgrp);
5082                 if (mode == FORK_FG)
5083                         xtcsetpgrp(ttyfd, pgrp);
5084                 setsignal(SIGTSTP);
5085                 setsignal(SIGTTOU);
5086         } else
5087 #endif
5088         if (mode == FORK_BG) {
5089                 /* man bash: "When job control is not in effect,
5090                  * asynchronous commands ignore SIGINT and SIGQUIT" */
5091                 ignoresig(SIGINT);
5092                 ignoresig(SIGQUIT);
5093                 if (jp->nprocs == 0) {
5094                         close(0);
5095                         if (open(bb_dev_null, O_RDONLY) != 0)
5096                                 ash_msg_and_raise_perror("can't open '%s'", bb_dev_null);
5097                 }
5098         }
5099         if (oldlvl == 0) {
5100                 if (iflag) { /* why if iflag only? */
5101                         setsignal(SIGINT);
5102                         setsignal(SIGTERM);
5103                 }
5104                 /* man bash:
5105                  * "In all cases, bash ignores SIGQUIT. Non-builtin
5106                  * commands run by bash have signal handlers
5107                  * set to the values inherited by the shell
5108                  * from its parent".
5109                  * Take care of the second rule: */
5110                 setsignal(SIGQUIT);
5111         }
5112 #if JOBS
5113         if (n && n->type == NCMD
5114          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
5115         ) {
5116                 TRACE(("Job hack\n"));
5117                 /* "jobs": we do not want to clear job list for it,
5118                  * instead we remove only _its_ own_ job from job list.
5119                  * This makes "jobs .... | cat" more useful.
5120                  */
5121                 freejob(curjob);
5122                 return;
5123         }
5124 #endif
5125         for (jp = curjob; jp; jp = jp->prev_job)
5126                 freejob(jp);
5127         jobless = 0;
5128 }
5129
5130 /* Called after fork(), in parent */
5131 #if !JOBS
5132 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5133 #endif
5134 static void
5135 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5136 {
5137         TRACE(("In parent shell: child = %d\n", pid));
5138         if (!jp) {
5139                 /* jp is NULL when called by openhere() for heredoc support */
5140                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5141                         continue;
5142                 jobless++;
5143                 return;
5144         }
5145 #if JOBS
5146         if (mode != FORK_NOJOB && jp->jobctl) {
5147                 int pgrp;
5148
5149                 if (jp->nprocs == 0)
5150                         pgrp = pid;
5151                 else
5152                         pgrp = jp->ps[0].ps_pid;
5153                 /* This can fail because we are doing it in the child also */
5154                 setpgid(pid, pgrp);
5155         }
5156 #endif
5157         if (mode == FORK_BG) {
5158                 backgndpid = pid;               /* set $! */
5159                 set_curjob(jp, CUR_RUNNING);
5160         }
5161         if (jp) {
5162                 struct procstat *ps = &jp->ps[jp->nprocs++];
5163                 ps->ps_pid = pid;
5164                 ps->ps_status = -1;
5165                 ps->ps_cmd = nullstr;
5166 #if JOBS
5167                 if (doing_jobctl && n)
5168                         ps->ps_cmd = commandtext(n);
5169 #endif
5170         }
5171 }
5172
5173 /* jp and n are NULL when called by openhere() for heredoc support */
5174 static int
5175 forkshell(struct job *jp, union node *n, int mode)
5176 {
5177         int pid;
5178
5179         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5180         pid = fork();
5181         if (pid < 0) {
5182                 TRACE(("Fork failed, errno=%d", errno));
5183                 if (jp)
5184                         freejob(jp);
5185                 ash_msg_and_raise_perror("can't fork");
5186         }
5187         if (pid == 0) {
5188                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5189                 forkchild(jp, n, mode);
5190         } else {
5191                 forkparent(jp, n, mode, pid);
5192         }
5193         return pid;
5194 }
5195
5196 /*
5197  * Wait for job to finish.
5198  *
5199  * Under job control we have the problem that while a child process
5200  * is running interrupts generated by the user are sent to the child
5201  * but not to the shell.  This means that an infinite loop started by
5202  * an interactive user may be hard to kill.  With job control turned off,
5203  * an interactive user may place an interactive program inside a loop.
5204  * If the interactive program catches interrupts, the user doesn't want
5205  * these interrupts to also abort the loop.  The approach we take here
5206  * is to have the shell ignore interrupt signals while waiting for a
5207  * foreground process to terminate, and then send itself an interrupt
5208  * signal if the child process was terminated by an interrupt signal.
5209  * Unfortunately, some programs want to do a bit of cleanup and then
5210  * exit on interrupt; unless these processes terminate themselves by
5211  * sending a signal to themselves (instead of calling exit) they will
5212  * confuse this approach.
5213  *
5214  * Called with interrupts off.
5215  */
5216 static int
5217 waitforjob(struct job *jp)
5218 {
5219         int st;
5220
5221         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5222
5223         INT_OFF;
5224         while (jp->state == JOBRUNNING) {
5225                 /* In non-interactive shells, we _can_ get
5226                  * a keyboard signal here and be EINTRed,
5227                  * but we just loop back, waiting for command to complete.
5228                  *
5229                  * man bash:
5230                  * "If bash is waiting for a command to complete and receives
5231                  * a signal for which a trap has been set, the trap
5232                  * will not be executed until the command completes."
5233                  *
5234                  * Reality is that even if trap is not set, bash
5235                  * will not act on the signal until command completes.
5236                  * Try this. sleep5intoff.c:
5237                  * #include <signal.h>
5238                  * #include <unistd.h>
5239                  * int main() {
5240                  *         sigset_t set;
5241                  *         sigemptyset(&set);
5242                  *         sigaddset(&set, SIGINT);
5243                  *         sigaddset(&set, SIGQUIT);
5244                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5245                  *         sleep(5);
5246                  *         return 0;
5247                  * }
5248                  * $ bash -c './sleep5intoff; echo hi'
5249                  * ^C^C^C^C <--- pressing ^C once a second
5250                  * $ _
5251                  * $ bash -c './sleep5intoff; echo hi'
5252                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5253                  * $ _
5254                  */
5255                 dowait(DOWAIT_BLOCK, jp);
5256         }
5257         INT_ON;
5258
5259         st = getstatus(jp);
5260 #if JOBS
5261         if (jp->jobctl) {
5262                 xtcsetpgrp(ttyfd, rootpid);
5263                 restore_tty_if_stopped_or_signaled(jp);
5264
5265                 /*
5266                  * This is truly gross.
5267                  * If we're doing job control, then we did a TIOCSPGRP which
5268                  * caused us (the shell) to no longer be in the controlling
5269                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5270                  * intuit from the subprocess exit status whether a SIGINT
5271                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5272                  */
5273                 if (jp->sigint) /* TODO: do the same with all signals */
5274                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5275         }
5276         if (jp->state == JOBDONE)
5277 #endif
5278                 freejob(jp);
5279         return st;
5280 }
5281
5282 /*
5283  * return 1 if there are stopped jobs, otherwise 0
5284  */
5285 static int
5286 stoppedjobs(void)
5287 {
5288         struct job *jp;
5289         int retval;
5290
5291         retval = 0;
5292         if (job_warning)
5293                 goto out;
5294         jp = curjob;
5295         if (jp && jp->state == JOBSTOPPED) {
5296                 out2str("You have stopped jobs.\n");
5297                 job_warning = 2;
5298                 retval++;
5299         }
5300  out:
5301         return retval;
5302 }
5303
5304
5305 /*
5306  * Code for dealing with input/output redirection.
5307  */
5308
5309 #undef EMPTY
5310 #undef CLOSED
5311 #define EMPTY -2                /* marks an unused slot in redirtab */
5312 #define CLOSED -1               /* marks a slot of previously-closed fd */
5313
5314 /*
5315  * Handle here documents.  Normally we fork off a process to write the
5316  * data to a pipe.  If the document is short, we can stuff the data in
5317  * the pipe without forking.
5318  */
5319 /* openhere needs this forward reference */
5320 static void expandhere(union node *arg, int fd);
5321 static int
5322 openhere(union node *redir)
5323 {
5324         int pip[2];
5325         size_t len = 0;
5326
5327         if (pipe(pip) < 0)
5328                 ash_msg_and_raise_perror("can't create pipe");
5329         if (redir->type == NHERE) {
5330                 len = strlen(redir->nhere.doc->narg.text);
5331                 if (len <= PIPE_BUF) {
5332                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5333                         goto out;
5334                 }
5335         }
5336         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5337                 /* child */
5338                 close(pip[0]);
5339                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5340                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5341                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5342                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5343                 signal(SIGPIPE, SIG_DFL);
5344                 if (redir->type == NHERE)
5345                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5346                 else /* NXHERE */
5347                         expandhere(redir->nhere.doc, pip[1]);
5348                 _exit(EXIT_SUCCESS);
5349         }
5350  out:
5351         close(pip[1]);
5352         return pip[0];
5353 }
5354
5355 static int
5356 openredirect(union node *redir)
5357 {
5358         struct stat sb;
5359         char *fname;
5360         int f;
5361
5362         switch (redir->nfile.type) {
5363 /* Can't happen, our single caller does this itself */
5364 //      case NTOFD:
5365 //      case NFROMFD:
5366 //              return -1;
5367         case NHERE:
5368         case NXHERE:
5369                 return openhere(redir);
5370         }
5371
5372         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5373          * allocated space. Do it only when we know it is safe.
5374          */
5375         fname = redir->nfile.expfname;
5376
5377         switch (redir->nfile.type) {
5378         default:
5379 #if DEBUG
5380                 abort();
5381 #endif
5382         case NFROM:
5383                 f = open(fname, O_RDONLY);
5384                 if (f < 0)
5385                         goto eopen;
5386                 break;
5387         case NFROMTO:
5388                 f = open(fname, O_RDWR|O_CREAT, 0666);
5389                 if (f < 0)
5390                         goto ecreate;
5391                 break;
5392         case NTO:
5393 #if BASH_REDIR_OUTPUT
5394         case NTO2:
5395 #endif
5396                 /* Take care of noclobber mode. */
5397                 if (Cflag) {
5398                         if (stat(fname, &sb) < 0) {
5399                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5400                                 if (f < 0)
5401                                         goto ecreate;
5402                         } else if (!S_ISREG(sb.st_mode)) {
5403                                 f = open(fname, O_WRONLY, 0666);
5404                                 if (f < 0)
5405                                         goto ecreate;
5406                                 if (!fstat(f, &sb) && S_ISREG(sb.st_mode)) {
5407                                         close(f);
5408                                         errno = EEXIST;
5409                                         goto ecreate;
5410                                 }
5411                         } else {
5412                                 errno = EEXIST;
5413                                 goto ecreate;
5414                         }
5415                         break;
5416                 }
5417                 /* FALLTHROUGH */
5418         case NCLOBBER:
5419                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5420                 if (f < 0)
5421                         goto ecreate;
5422                 break;
5423         case NAPPEND:
5424                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5425                 if (f < 0)
5426                         goto ecreate;
5427                 break;
5428         }
5429
5430         return f;
5431  ecreate:
5432         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5433  eopen:
5434         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5435 }
5436
5437 /*
5438  * Copy a file descriptor to be >= 10. Throws exception on error.
5439  */
5440 static int
5441 savefd(int from)
5442 {
5443         int newfd;
5444         int err;
5445
5446         newfd = fcntl(from, F_DUPFD_CLOEXEC, 10);
5447         err = newfd < 0 ? errno : 0;
5448         if (err != EBADF) {
5449                 if (err)
5450                         ash_msg_and_raise_perror("%d", from);
5451                 close(from);
5452                 if (F_DUPFD_CLOEXEC == F_DUPFD)
5453                         close_on_exec_on(newfd);
5454         }
5455
5456         return newfd;
5457 }
5458 static int
5459 dup2_or_raise(int from, int to)
5460 {
5461         int newfd;
5462
5463         newfd = (from != to) ? dup2(from, to) : to;
5464         if (newfd < 0) {
5465                 /* Happens when source fd is not open: try "echo >&99" */
5466                 ash_msg_and_raise_perror("%d", from);
5467         }
5468         return newfd;
5469 }
5470 static int
5471 dup_CLOEXEC(int fd, int avoid_fd)
5472 {
5473         int newfd;
5474  repeat:
5475         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5476         if (newfd >= 0) {
5477                 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
5478                         close_on_exec_on(newfd);
5479         } else { /* newfd < 0 */
5480                 if (errno == EBUSY)
5481                         goto repeat;
5482                 if (errno == EINTR)
5483                         goto repeat;
5484         }
5485         return newfd;
5486 }
5487 static int
5488 xdup_CLOEXEC_and_close(int fd, int avoid_fd)
5489 {
5490         int newfd;
5491  repeat:
5492         newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5493         if (newfd < 0) {
5494                 if (errno == EBUSY)
5495                         goto repeat;
5496                 if (errno == EINTR)
5497                         goto repeat;
5498                 /* fd was not open? */
5499                 if (errno == EBADF)
5500                         return fd;
5501                 ash_msg_and_raise_perror("%d", newfd);
5502         }
5503         if (F_DUPFD_CLOEXEC == F_DUPFD)
5504                 close_on_exec_on(newfd);
5505         close(fd);
5506         return newfd;
5507 }
5508
5509 /* Struct def and variable are moved down to the first usage site */
5510 struct squirrel {
5511         int orig_fd;
5512         int moved_to;
5513 };
5514 struct redirtab {
5515         struct redirtab *next;
5516         int pair_count;
5517         struct squirrel two_fd[];
5518 };
5519 #define redirlist (G_var.redirlist)
5520
5521 static void
5522 add_squirrel_closed(struct redirtab *sq, int fd)
5523 {
5524         int i;
5525
5526         if (!sq)
5527                 return;
5528
5529         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5530                 /* If we collide with an already moved fd... */
5531                 if (fd == sq->two_fd[i].orig_fd) {
5532                         /* Examples:
5533                          * "echo 3>FILE 3>&- 3>FILE"
5534                          * "echo 3>&- 3>FILE"
5535                          * No need for last redirect to insert
5536                          * another "need to close 3" indicator.
5537                          */
5538                         TRACE(("redirect_fd %d: already moved or closed\n", fd));
5539                         return;
5540                 }
5541         }
5542         TRACE(("redirect_fd %d: previous fd was closed\n", fd));
5543         sq->two_fd[i].orig_fd = fd;
5544         sq->two_fd[i].moved_to = CLOSED;
5545 }
5546
5547 static int
5548 save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5549 {
5550         int i, new_fd;
5551
5552         if (avoid_fd < 9) /* the important case here is that it can be -1 */
5553                 avoid_fd = 9;
5554
5555 #if JOBS
5556         if (fd == ttyfd) {
5557                 /* Testcase: "ls -l /proc/$$/fd 10>&-" should work */
5558                 ttyfd = xdup_CLOEXEC_and_close(ttyfd, avoid_fd);
5559                 TRACE(("redirect_fd %d: matches ttyfd, moving it to %d\n", fd, ttyfd));
5560                 return 1; /* "we closed fd" */
5561         }
5562 #endif
5563         /* Are we called from redirect(0)? E.g. redirect
5564          * in a forked child. No need to save fds,
5565          * we aren't going to use them anymore, ok to trash.
5566          */
5567         if (!sq)
5568                 return 0;
5569
5570         /* If this one of script's fds? */
5571         if (fd != 0) {
5572                 struct parsefile *pf = g_parsefile;
5573                 while (pf) {
5574                         /* We skip fd == 0 case because of the following:
5575                          * $ ash  # running ash interactively
5576                          * $ . ./script.sh
5577                          * and in script.sh: "exec 9>&0".
5578                          * Even though top-level pf_fd _is_ 0,
5579                          * it's still ok to use it: "read" builtin uses it,
5580                          * why should we cripple "exec" builtin?
5581                          */
5582                         if (fd == pf->pf_fd) {
5583                                 pf->pf_fd = xdup_CLOEXEC_and_close(fd, avoid_fd);
5584                                 return 1; /* "we closed fd" */
5585                         }
5586                         pf = pf->prev;
5587                 }
5588         }
5589
5590         /* Check whether it collides with any open fds (e.g. stdio), save fds as needed */
5591
5592         /* First: do we collide with some already moved fds? */
5593         for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5594                 /* If we collide with an already moved fd... */
5595                 if (fd == sq->two_fd[i].moved_to) {
5596                         new_fd = dup_CLOEXEC(fd, avoid_fd);
5597                         sq->two_fd[i].moved_to = new_fd;
5598                         TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5599                         if (new_fd < 0) /* what? */
5600                                 xfunc_die();
5601                         return 0; /* "we did not close fd" */
5602                 }
5603                 if (fd == sq->two_fd[i].orig_fd) {
5604                         /* Example: echo Hello >/dev/null 1>&2 */
5605                         TRACE(("redirect_fd %d: already moved\n", fd));
5606                         return 0; /* "we did not close fd" */
5607                 }
5608         }
5609
5610         /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5611         new_fd = dup_CLOEXEC(fd, avoid_fd);
5612         TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5613         if (new_fd < 0) {
5614                 if (errno != EBADF)
5615                         xfunc_die();
5616                 /* new_fd = CLOSED; - already is -1 */
5617         }
5618         sq->two_fd[i].moved_to = new_fd;
5619         sq->two_fd[i].orig_fd = fd;
5620
5621         /* if we move stderr, let "set -x" code know */
5622         if (fd == preverrout_fd)
5623                 preverrout_fd = new_fd;
5624
5625         return 0; /* "we did not close fd" */
5626 }
5627
5628 static int
5629 internally_opened_fd(int fd, struct redirtab *sq)
5630 {
5631         int i;
5632 #if JOBS
5633         if (fd == ttyfd)
5634                 return 1;
5635 #endif
5636         /* If this one of script's fds? */
5637         if (fd != 0) {
5638                 struct parsefile *pf = g_parsefile;
5639                 while (pf) {
5640                         if (fd == pf->pf_fd)
5641                                 return 1;
5642                         pf = pf->prev;
5643                 }
5644         }
5645
5646         if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
5647                 if (fd == sq->two_fd[i].moved_to)
5648                         return 1;
5649         }
5650         return 0;
5651 }
5652
5653 /*
5654  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5655  * old file descriptors are stashed away so that the redirection can be
5656  * undone by calling popredir.
5657  */
5658 /* flags passed to redirect */
5659 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5660 static void
5661 redirect(union node *redir, int flags)
5662 {
5663         struct redirtab *sv;
5664
5665         if (!redir)
5666                 return;
5667
5668         sv = NULL;
5669         INT_OFF;
5670         if (flags & REDIR_PUSH)
5671                 sv = redirlist;
5672         do {
5673                 int fd;
5674                 int newfd;
5675                 int close_fd;
5676                 int closed;
5677
5678                 fd = redir->nfile.fd;
5679                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5680                         //bb_error_msg("doing %d > %d", fd, newfd);
5681                         newfd = redir->ndup.dupfd;
5682                         close_fd = -1;
5683                 } else {
5684                         newfd = openredirect(redir); /* always >= 0 */
5685                         if (fd == newfd) {
5686                                 /* open() gave us precisely the fd we wanted.
5687                                  * This means that this fd was not busy
5688                                  * (not opened to anywhere).
5689                                  * Remember to close it on restore:
5690                                  */
5691                                 add_squirrel_closed(sv, fd);
5692                                 continue;
5693                         }
5694                         close_fd = newfd;
5695                 }
5696
5697                 if (fd == newfd)
5698                         continue;
5699
5700                 /* if "N>FILE": move newfd to fd */
5701                 /* if "N>&M": dup newfd to fd */
5702                 /* if "N>&-": close fd (newfd is -1) */
5703
5704  IF_BASH_REDIR_OUTPUT(redirect_more:)
5705
5706                 closed = save_fd_on_redirect(fd, /*avoid:*/ newfd, sv);
5707                 if (newfd == -1) {
5708                         /* "N>&-" means "close me" */
5709                         if (!closed) {
5710                                 /* ^^^ optimization: saving may already
5711                                  * have closed it. If not... */
5712                                 close(fd);
5713                         }
5714                 } else {
5715                         /* if newfd is a script fd or saved fd, simulate EBADF */
5716                         if (internally_opened_fd(newfd, sv)) {
5717                                 errno = EBADF;
5718                                 ash_msg_and_raise_perror("%d", newfd);
5719                         }
5720                         dup2_or_raise(newfd, fd);
5721                         if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
5722                                 close(close_fd);
5723 #if BASH_REDIR_OUTPUT
5724                         if (redir->nfile.type == NTO2 && fd == 1) {
5725                                 /* ">&FILE". we already redirected to 1, now copy 1 to 2 */
5726                                 fd = 2;
5727                                 newfd = 1;
5728                                 close_fd = -1;
5729                                 goto redirect_more;
5730                         }
5731 #endif
5732                 }
5733         } while ((redir = redir->nfile.next) != NULL);
5734         INT_ON;
5735
5736 //dash:#define REDIR_SAVEFD2 03        /* set preverrout */
5737 #define REDIR_SAVEFD2 0
5738         // dash has a bug: since REDIR_SAVEFD2=3 and REDIR_PUSH=1, this test
5739         // triggers for pure REDIR_PUSH too. Thus, this is done almost always,
5740         // not only for calls with flags containing REDIR_SAVEFD2.
5741         // We do this unconditionally (see save_fd_on_redirect()).
5742         //if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5743         //      preverrout_fd = copied_fd2;
5744 }
5745
5746 static int
5747 redirectsafe(union node *redir, int flags)
5748 {
5749         int err;
5750         volatile int saveint;
5751         struct jmploc *volatile savehandler = exception_handler;
5752         struct jmploc jmploc;
5753
5754         SAVE_INT(saveint);
5755         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5756         err = setjmp(jmploc.loc); /* was = setjmp(jmploc.loc) * 2; */
5757         if (!err) {
5758                 exception_handler = &jmploc;
5759                 redirect(redir, flags);
5760         }
5761         exception_handler = savehandler;
5762         if (err && exception_type != EXERROR)
5763                 longjmp(exception_handler->loc, 1);
5764         RESTORE_INT(saveint);
5765         return err;
5766 }
5767
5768 static struct redirtab*
5769 pushredir(union node *redir)
5770 {
5771         struct redirtab *sv;
5772         int i;
5773
5774         if (!redir)
5775                 return redirlist;
5776
5777         i = 0;
5778         do {
5779                 i++;
5780 #if BASH_REDIR_OUTPUT
5781                 if (redir->nfile.type == NTO2)
5782                         i++;
5783 #endif
5784                 redir = redir->nfile.next;
5785         } while (redir);
5786
5787         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5788         sv->pair_count = i;
5789         while (--i >= 0)
5790                 sv->two_fd[i].orig_fd = sv->two_fd[i].moved_to = EMPTY;
5791         sv->next = redirlist;
5792         redirlist = sv;
5793         return sv->next;
5794 }
5795
5796 /*
5797  * Undo the effects of the last redirection.
5798  */
5799 static void
5800 popredir(int drop)
5801 {
5802         struct redirtab *rp;
5803         int i;
5804
5805         if (redirlist == NULL)
5806                 return;
5807         INT_OFF;
5808         rp = redirlist;
5809         for (i = 0; i < rp->pair_count; i++) {
5810                 int fd = rp->two_fd[i].orig_fd;
5811                 int copy = rp->two_fd[i].moved_to;
5812                 if (copy == CLOSED) {
5813                         if (!drop)
5814                                 close(fd);
5815                         continue;
5816                 }
5817                 if (copy != EMPTY) {
5818                         if (!drop) {
5819                                 /*close(fd);*/
5820                                 dup2_or_raise(copy, fd);
5821                         }
5822                         close(copy);
5823                 }
5824         }
5825         redirlist = rp->next;
5826         free(rp);
5827         INT_ON;
5828 }
5829
5830 static void
5831 unwindredir(struct redirtab *stop)
5832 {
5833         while (redirlist != stop)
5834                 popredir(/*drop:*/ 0);
5835 }
5836
5837
5838 /* ============ Routines to expand arguments to commands
5839  *
5840  * We have to deal with backquotes, shell variables, and file metacharacters.
5841  */
5842
5843 #if ENABLE_FEATURE_SH_MATH
5844 static arith_t
5845 ash_arith(const char *s)
5846 {
5847         arith_state_t math_state;
5848         arith_t result;
5849
5850         math_state.lookupvar = lookupvar;
5851         math_state.setvar    = setvar0;
5852         //math_state.endofname = endofname;
5853
5854         INT_OFF;
5855         result = arith(&math_state, s);
5856         if (math_state.errmsg)
5857                 ash_msg_and_raise_error(math_state.errmsg);
5858         INT_ON;
5859
5860         return result;
5861 }
5862 #endif
5863 #if BASH_SUBSTR
5864 # if ENABLE_FEATURE_SH_MATH
5865 static int substr_atoi(const char *s)
5866 {
5867         arith_t t = ash_arith(s);
5868         if (sizeof(t) > sizeof(int)) {
5869                 /* clamp very large or very large negative nums for ${v:N:M}:
5870                  * else "${v:0:0x100000001}" would work as "${v:0:1}"
5871                  */
5872                 if (t > INT_MAX)
5873                         t = INT_MAX;
5874                 if (t < INT_MIN)
5875                         t = INT_MIN;
5876         }
5877         return t;
5878 }
5879 # else
5880 #  define substr_atoi(s) number(s)
5881 # endif
5882 #endif
5883
5884 /*
5885  * expandarg flags
5886  */
5887 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5888 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5889 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5890 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5891 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5892  * POSIX says for this case:
5893  *  Pathname expansion shall not be performed on the word by a
5894  *  non-interactive shell; an interactive shell may perform it, but shall
5895  *  do so only when the expansion would result in one word.
5896  * Currently, our code complies to the above rule by never globbing
5897  * redirection filenames.
5898  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5899  * (this means that on a typical Linux distro, bash almost always
5900  * performs globbing, and thus diverges from what we do).
5901  */
5902 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5903 #define EXP_VARTILDE2   0x20    /* expand tildes after colons only */
5904 #define EXP_WORD        0x40    /* expand word in parameter expansion */
5905 #define EXP_QUOTED      0x80    /* expand word in double quotes */
5906 /*
5907  * rmescape() flags
5908  */
5909 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5910 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5911 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5912 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5913
5914 /* Add CTLESC when necessary. */
5915 #define QUOTES_ESC     (EXP_FULL | EXP_CASE)
5916 /* Do not skip NUL characters. */
5917 #define QUOTES_KEEPNUL EXP_TILDE
5918
5919 /*
5920  * Structure specifying which parts of the string should be searched
5921  * for IFS characters.
5922  */
5923 struct ifsregion {
5924         struct ifsregion *next; /* next region in list */
5925         int begoff;             /* offset of start of region */
5926         int endoff;             /* offset of end of region */
5927         int nulonly;            /* search for nul bytes only */
5928 };
5929
5930 struct arglist {
5931         struct strlist *list;
5932         struct strlist **lastp;
5933 };
5934
5935 /* output of current string */
5936 static char *expdest;
5937 /* list of back quote expressions */
5938 static struct nodelist *argbackq;
5939 /* first struct in list of ifs regions */
5940 static struct ifsregion ifsfirst;
5941 /* last struct in list */
5942 static struct ifsregion *ifslastp;
5943 /* holds expanded arg list */
5944 static struct arglist exparg;
5945
5946 /*
5947  * Our own itoa().
5948  * cvtnum() is used even if math support is off (to prepare $? values and such).
5949  */
5950 static int
5951 cvtnum(arith_t num)
5952 {
5953         int len;
5954
5955         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5956         len = sizeof(arith_t) * 3;
5957         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5958         if (sizeof(arith_t) < 4) len += 2;
5959
5960         expdest = makestrspace(len, expdest);
5961         len = fmtstr(expdest, len, ARITH_FMT, num);
5962         STADJUST(len, expdest);
5963         return len;
5964 }
5965
5966 /*
5967  * Break the argument string into pieces based upon IFS and add the
5968  * strings to the argument list.  The regions of the string to be
5969  * searched for IFS characters have been stored by recordregion.
5970  */
5971 static void
5972 ifsbreakup(char *string, struct arglist *arglist)
5973 {
5974         struct ifsregion *ifsp;
5975         struct strlist *sp;
5976         char *start;
5977         char *p;
5978         char *q;
5979         const char *ifs, *realifs;
5980         int ifsspc;
5981         int nulonly;
5982
5983         start = string;
5984         if (ifslastp != NULL) {
5985                 ifsspc = 0;
5986                 nulonly = 0;
5987                 realifs = ifsset() ? ifsval() : defifs;
5988                 ifsp = &ifsfirst;
5989                 do {
5990                         int afternul;
5991
5992                         p = string + ifsp->begoff;
5993                         afternul = nulonly;
5994                         nulonly = ifsp->nulonly;
5995                         ifs = nulonly ? nullstr : realifs;
5996                         ifsspc = 0;
5997                         while (p < string + ifsp->endoff) {
5998                                 q = p;
5999                                 if ((unsigned char)*p == CTLESC)
6000                                         p++;
6001                                 if (!strchr(ifs, *p)) {
6002                                         p++;
6003                                         continue;
6004                                 }
6005                                 if (!(afternul || nulonly))
6006                                         ifsspc = (strchr(defifs, *p) != NULL);
6007                                 /* Ignore IFS whitespace at start */
6008                                 if (q == start && ifsspc) {
6009                                         p++;
6010                                         start = p;
6011                                         continue;
6012                                 }
6013                                 *q = '\0';
6014                                 sp = stzalloc(sizeof(*sp));
6015                                 sp->text = start;
6016                                 *arglist->lastp = sp;
6017                                 arglist->lastp = &sp->next;
6018                                 p++;
6019                                 if (!nulonly) {
6020                                         for (;;) {
6021                                                 if (p >= string + ifsp->endoff) {
6022                                                         break;
6023                                                 }
6024                                                 q = p;
6025                                                 if ((unsigned char)*p == CTLESC)
6026                                                         p++;
6027                                                 if (strchr(ifs, *p) == NULL) {
6028                                                         p = q;
6029                                                         break;
6030                                                 }
6031                                                 if (strchr(defifs, *p) == NULL) {
6032                                                         if (ifsspc) {
6033                                                                 p++;
6034                                                                 ifsspc = 0;
6035                                                         } else {
6036                                                                 p = q;
6037                                                                 break;
6038                                                         }
6039                                                 } else
6040                                                         p++;
6041                                         }
6042                                 }
6043                                 start = p;
6044                         } /* while */
6045                         ifsp = ifsp->next;
6046                 } while (ifsp != NULL);
6047                 if (nulonly)
6048                         goto add;
6049         }
6050
6051         if (!*start)
6052                 return;
6053
6054  add:
6055         sp = stzalloc(sizeof(*sp));
6056         sp->text = start;
6057         *arglist->lastp = sp;
6058         arglist->lastp = &sp->next;
6059 }
6060
6061 static void
6062 ifsfree(void)
6063 {
6064         struct ifsregion *p = ifsfirst.next;
6065
6066         if (!p)
6067                 goto out;
6068
6069         INT_OFF;
6070         do {
6071                 struct ifsregion *ifsp;
6072                 ifsp = p->next;
6073                 free(p);
6074                 p = ifsp;
6075         } while (p);
6076         ifsfirst.next = NULL;
6077         INT_ON;
6078  out:
6079         ifslastp = NULL;
6080 }
6081
6082 static size_t
6083 esclen(const char *start, const char *p)
6084 {
6085         size_t esc = 0;
6086
6087         while (p > start && (unsigned char)*--p == CTLESC) {
6088                 esc++;
6089         }
6090         return esc;
6091 }
6092
6093 /*
6094  * Remove any CTLESC characters from a string.
6095  */
6096 #if !BASH_PATTERN_SUBST
6097 #define rmescapes(str, flag, slash_position) \
6098         rmescapes(str, flag)
6099 #endif
6100 static char *
6101 rmescapes(char *str, int flag, int *slash_position)
6102 {
6103         static const char qchars[] ALIGN1 = {
6104                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
6105
6106         char *p, *q, *r;
6107         unsigned protect_against_glob;
6108         unsigned globbing;
6109
6110         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash_position));
6111         if (!p)
6112                 return str;
6113
6114         q = p;
6115         r = str;
6116         if (flag & RMESCAPE_ALLOC) {
6117                 size_t len = p - str;
6118                 size_t fulllen = len + strlen(p) + 1;
6119
6120                 if (flag & RMESCAPE_GROW) {
6121                         int strloc = str - (char *)stackblock();
6122                         r = makestrspace(fulllen, expdest);
6123                         /* p and str may be invalidated by makestrspace */
6124                         str = (char *)stackblock() + strloc;
6125                         p = str + len;
6126                 } else if (flag & RMESCAPE_HEAP) {
6127                         r = ckmalloc(fulllen);
6128                 } else {
6129                         r = stalloc(fulllen);
6130                 }
6131                 q = r;
6132                 if (len > 0) {
6133                         q = (char *)mempcpy(q, str, len);
6134                 }
6135         }
6136
6137         globbing = flag & RMESCAPE_GLOB;
6138         protect_against_glob = globbing;
6139         while (*p) {
6140                 if ((unsigned char)*p == CTLQUOTEMARK) {
6141 // Note: protect_against_glob only affect whether
6142 // CTLESC,<ch> gets converted to <ch> or to \<ch>
6143                         p++;
6144                         protect_against_glob = globbing;
6145                         continue;
6146                 }
6147                 if (*p == '\\') {
6148                         /* naked back slash */
6149                         protect_against_glob = 0;
6150                         goto copy;
6151                 }
6152                 if ((unsigned char)*p == CTLESC) {
6153                         p++;
6154 #if DEBUG
6155                         if (*p == '\0')
6156                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
6157 #endif
6158                         if (protect_against_glob) {
6159                                 /*
6160                                  * We used to trust glob() and fnmatch() to eat
6161                                  * superfluous escapes (\z where z has no
6162                                  * special meaning anyway). But this causes
6163                                  * bugs such as string of one greek letter rho
6164                                  * (unicode-encoded as two bytes "cf,81")
6165                                  * getting encoded as "cf,CTLESC,81"
6166                                  * and here, converted to "cf,\,81" -
6167                                  * which does not go well with some flavors
6168                                  * of fnmatch() in unicode locales
6169                                  * (for example, glibc <= 2.22).
6170                                  *
6171                                  * Lets add "\" only on the chars which need it.
6172                                  * Testcases for less obvious chars are shown.
6173                                  */
6174                                 if (*p == '*'
6175                                  || *p == '?'
6176                                  || *p == '['
6177                                  || *p == '\\' /* case '\' in \\    ) echo ok;; *) echo WRONG;; esac */
6178                                  || *p == ']'  /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
6179                                  || *p == '-'  /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
6180                                  || *p == '!'  /* case '!' in [\!]  ) echo ok;; *) echo WRONG;; esac */
6181                                 /* Some libc support [^negate], that's why "^" also needs love */
6182                                  || *p == '^'  /* case '^' in [\^]  ) echo ok;; *) echo WRONG;; esac */
6183                                 ) {
6184                                         *q++ = '\\';
6185                                 }
6186                         }
6187                 }
6188 #if BASH_PATTERN_SUBST
6189                 else if (slash_position && p == str + *slash_position) {
6190                         /* stop handling globbing */
6191                         globbing = 0;
6192                         *slash_position = q - r;
6193                         slash_position = NULL;
6194                 }
6195 #endif
6196                 protect_against_glob = globbing;
6197  copy:
6198                 *q++ = *p++;
6199         }
6200         *q = '\0';
6201         if (flag & RMESCAPE_GROW) {
6202                 expdest = r;
6203                 STADJUST(q - r + 1, expdest);
6204         }
6205         return r;
6206 }
6207 #define pmatch(a, b) !fnmatch((a), (b), 0)
6208
6209 /*
6210  * Prepare a pattern for a expmeta (internal glob(3)) call.
6211  *
6212  * Returns an stalloced string.
6213  */
6214 static char *
6215 preglob(const char *pattern, int flag)
6216 {
6217         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB, NULL);
6218 }
6219
6220 /*
6221  * Put a string on the stack.
6222  */
6223 static void
6224 memtodest(const char *p, size_t len, int syntax, int quotes)
6225 {
6226         char *q;
6227
6228         if (!len)
6229                 return;
6230
6231         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6232
6233         do {
6234                 unsigned char c = *p++;
6235                 if (c) {
6236                         if (quotes & QUOTES_ESC) {
6237                                 int n = SIT(c, syntax);
6238                                 if (n == CCTL
6239                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6240                                      && n == CBACK
6241                                     )
6242                                 ) {
6243                                         USTPUTC(CTLESC, q);
6244                                 }
6245                         }
6246                 } else if (!(quotes & QUOTES_KEEPNUL))
6247                         continue;
6248                 USTPUTC(c, q);
6249         } while (--len);
6250
6251         expdest = q;
6252 }
6253
6254 static size_t
6255 strtodest(const char *p, int syntax, int quotes)
6256 {
6257         size_t len = strlen(p);
6258         memtodest(p, len, syntax, quotes);
6259         return len;
6260 }
6261
6262 /*
6263  * Record the fact that we have to scan this region of the
6264  * string for IFS characters.
6265  */
6266 static void
6267 recordregion(int start, int end, int nulonly)
6268 {
6269         struct ifsregion *ifsp;
6270
6271         if (ifslastp == NULL) {
6272                 ifsp = &ifsfirst;
6273         } else {
6274                 INT_OFF;
6275                 ifsp = ckzalloc(sizeof(*ifsp));
6276                 /*ifsp->next = NULL; - ckzalloc did it */
6277                 ifslastp->next = ifsp;
6278                 INT_ON;
6279         }
6280         ifslastp = ifsp;
6281         ifslastp->begoff = start;
6282         ifslastp->endoff = end;
6283         ifslastp->nulonly = nulonly;
6284 }
6285
6286 static void
6287 removerecordregions(int endoff)
6288 {
6289         if (ifslastp == NULL)
6290                 return;
6291
6292         if (ifsfirst.endoff > endoff) {
6293                 while (ifsfirst.next) {
6294                         struct ifsregion *ifsp;
6295                         INT_OFF;
6296                         ifsp = ifsfirst.next->next;
6297                         free(ifsfirst.next);
6298                         ifsfirst.next = ifsp;
6299                         INT_ON;
6300                 }
6301                 if (ifsfirst.begoff > endoff) {
6302                         ifslastp = NULL;
6303                 } else {
6304                         ifslastp = &ifsfirst;
6305                         ifsfirst.endoff = endoff;
6306                 }
6307                 return;
6308         }
6309
6310         ifslastp = &ifsfirst;
6311         while (ifslastp->next && ifslastp->next->begoff < endoff)
6312                 ifslastp = ifslastp->next;
6313         while (ifslastp->next) {
6314                 struct ifsregion *ifsp;
6315                 INT_OFF;
6316                 ifsp = ifslastp->next->next;
6317                 free(ifslastp->next);
6318                 ifslastp->next = ifsp;
6319                 INT_ON;
6320         }
6321         if (ifslastp->endoff > endoff)
6322                 ifslastp->endoff = endoff;
6323 }
6324
6325 static char *
6326 exptilde(char *startp, char *p, int flags)
6327 {
6328         unsigned char c;
6329         char *name;
6330         struct passwd *pw;
6331         const char *home;
6332         int quotes = flags & QUOTES_ESC;
6333
6334         name = p + 1;
6335
6336         while ((c = *++p) != '\0') {
6337                 switch (c) {
6338                 case CTLESC:
6339                         return startp;
6340                 case CTLQUOTEMARK:
6341                         return startp;
6342                 case ':':
6343                         if (flags & EXP_VARTILDE)
6344                                 goto done;
6345                         break;
6346                 case '/':
6347                 case CTLENDVAR:
6348                         goto done;
6349                 }
6350         }
6351  done:
6352         *p = '\0';
6353         if (*name == '\0') {
6354                 home = lookupvar("HOME");
6355         } else {
6356                 pw = getpwnam(name);
6357                 if (pw == NULL)
6358                         goto lose;
6359                 home = pw->pw_dir;
6360         }
6361         if (!home || !*home)
6362                 goto lose;
6363         *p = c;
6364         strtodest(home, SQSYNTAX, quotes);
6365         return p;
6366  lose:
6367         *p = c;
6368         return startp;
6369 }
6370
6371 /*
6372  * Execute a command inside back quotes.  If it's a builtin command, we
6373  * want to save its output in a block obtained from malloc.  Otherwise
6374  * we fork off a subprocess and get the output of the command via a pipe.
6375  * Should be called with interrupts off.
6376  */
6377 struct backcmd {                /* result of evalbackcmd */
6378         int fd;                 /* file descriptor to read from */
6379         int nleft;              /* number of chars in buffer */
6380         char *buf;              /* buffer */
6381         struct job *jp;         /* job structure for command */
6382 };
6383
6384 /* These forward decls are needed to use "eval" code for backticks handling: */
6385 /* flags in argument to evaltree */
6386 #define EV_EXIT    01           /* exit after evaluating tree */
6387 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6388 static int evaltree(union node *, int);
6389
6390 /* An evaltree() which is known to never return.
6391  * Used to use an alias:
6392  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6393  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6394  */
6395 static ALWAYS_INLINE NORETURN void
6396 evaltreenr(union node *n, int flags)
6397 {
6398         evaltree(n, flags);
6399         bb_unreachable(abort());
6400         /* NOTREACHED */
6401 }
6402
6403 static void FAST_FUNC
6404 evalbackcmd(union node *n, struct backcmd *result)
6405 {
6406         int pip[2];
6407         struct job *jp;
6408
6409         result->fd = -1;
6410         result->buf = NULL;
6411         result->nleft = 0;
6412         result->jp = NULL;
6413         if (n == NULL) {
6414                 goto out;
6415         }
6416
6417         if (pipe(pip) < 0)
6418                 ash_msg_and_raise_perror("can't create pipe");
6419         jp = makejob(/*n,*/ 1);
6420         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6421                 /* child */
6422                 FORCE_INT_ON;
6423                 close(pip[0]);
6424                 if (pip[1] != 1) {
6425                         /*close(1);*/
6426                         dup2_or_raise(pip[1], 1);
6427                         close(pip[1]);
6428                 }
6429 /* TODO: eflag clearing makes the following not abort:
6430  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6431  * which is what bash does (unless it is in POSIX mode).
6432  * dash deleted "eflag = 0" line in the commit
6433  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6434  *  [EVAL] Don't clear eflag in evalbackcmd
6435  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6436  */
6437                 eflag = 0;
6438                 ifsfree();
6439                 evaltreenr(n, EV_EXIT);
6440                 /* NOTREACHED */
6441         }
6442         /* parent */
6443         close(pip[1]);
6444         result->fd = pip[0];
6445         result->jp = jp;
6446
6447  out:
6448         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6449                 result->fd, result->buf, result->nleft, result->jp));
6450 }
6451
6452 /*
6453  * Expand stuff in backwards quotes.
6454  */
6455 static void
6456 expbackq(union node *cmd, int flag)
6457 {
6458         struct backcmd in;
6459         int i;
6460         char buf[128];
6461         char *p;
6462         char *dest;
6463         int startloc;
6464         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6465         struct stackmark smark;
6466
6467         INT_OFF;
6468         startloc = expdest - (char *)stackblock();
6469         pushstackmark(&smark, startloc);
6470         evalbackcmd(cmd, &in);
6471         popstackmark(&smark);
6472
6473         p = in.buf;
6474         i = in.nleft;
6475         if (i == 0)
6476                 goto read;
6477         for (;;) {
6478                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6479  read:
6480                 if (in.fd < 0)
6481                         break;
6482                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6483                 TRACE(("expbackq: read returns %d\n", i));
6484                 if (i <= 0)
6485                         break;
6486                 p = buf;
6487         }
6488
6489         free(in.buf);
6490         if (in.fd >= 0) {
6491                 close(in.fd);
6492                 back_exitstatus = waitforjob(in.jp);
6493         }
6494         INT_ON;
6495
6496         /* Eat all trailing newlines */
6497         dest = expdest;
6498         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6499                 STUNPUTC(dest);
6500         expdest = dest;
6501
6502         if (!(flag & EXP_QUOTED))
6503                 recordregion(startloc, dest - (char *)stackblock(), 0);
6504         TRACE(("evalbackq: size:%d:'%.*s'\n",
6505                 (int)((dest - (char *)stackblock()) - startloc),
6506                 (int)((dest - (char *)stackblock()) - startloc),
6507                 stackblock() + startloc));
6508 }
6509
6510 #if ENABLE_FEATURE_SH_MATH
6511 /*
6512  * Expand arithmetic expression.  Backup to start of expression,
6513  * evaluate, place result in (backed up) result, adjust string position.
6514  */
6515 static void
6516 expari(int flag)
6517 {
6518         char *p, *start;
6519         int begoff;
6520         int len;
6521
6522         /* ifsfree(); */
6523
6524         /*
6525          * This routine is slightly over-complicated for
6526          * efficiency.  Next we scan backwards looking for the
6527          * start of arithmetic.
6528          */
6529         start = stackblock();
6530         p = expdest - 1;
6531         *p = '\0';
6532         p--;
6533         while (1) {
6534                 int esc;
6535
6536                 while ((unsigned char)*p != CTLARI) {
6537                         p--;
6538 #if DEBUG
6539                         if (p < start) {
6540                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6541                         }
6542 #endif
6543                 }
6544
6545                 esc = esclen(start, p);
6546                 if (!(esc % 2)) {
6547                         break;
6548                 }
6549
6550                 p -= esc + 1;
6551         }
6552
6553         begoff = p - start;
6554
6555         removerecordregions(begoff);
6556
6557         expdest = p;
6558
6559         if (flag & QUOTES_ESC)
6560                 rmescapes(p + 1, 0, NULL);
6561
6562         len = cvtnum(ash_arith(p + 1));
6563
6564         if (!(flag & EXP_QUOTED))
6565                 recordregion(begoff, begoff + len, 0);
6566 }
6567 #endif
6568
6569 /* argstr needs it */
6570 static char *evalvar(char *p, int flags);
6571
6572 /*
6573  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6574  * characters to allow for further processing.  Otherwise treat
6575  * $@ like $* since no splitting will be performed.
6576  */
6577 static void
6578 argstr(char *p, int flags)
6579 {
6580         static const char spclchars[] ALIGN1 = {
6581                 '=',
6582                 ':',
6583                 CTLQUOTEMARK,
6584                 CTLENDVAR,
6585                 CTLESC,
6586                 CTLVAR,
6587                 CTLBACKQ,
6588 #if ENABLE_FEATURE_SH_MATH
6589                 CTLENDARI,
6590 #endif
6591                 '\0'
6592         };
6593         const char *reject = spclchars;
6594         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6595         int inquotes;
6596         size_t length;
6597         int startloc;
6598
6599         if (!(flags & EXP_VARTILDE)) {
6600                 reject += 2;
6601         } else if (flags & EXP_VARTILDE2) {
6602                 reject++;
6603         }
6604         inquotes = 0;
6605         length = 0;
6606         if (flags & EXP_TILDE) {
6607                 char *q;
6608
6609                 flags &= ~EXP_TILDE;
6610  tilde:
6611                 q = p;
6612                 if (*q == '~')
6613                         p = exptilde(p, q, flags);
6614         }
6615  start:
6616         startloc = expdest - (char *)stackblock();
6617         for (;;) {
6618                 unsigned char c;
6619
6620                 length += strcspn(p + length, reject);
6621                 c = p[length];
6622                 if (c) {
6623                         if (!(c & 0x80)
6624                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6625                         ) {
6626                                 /* c == '=' || c == ':' || c == CTLENDARI */
6627                                 length++;
6628                         }
6629                 }
6630                 if (length > 0) {
6631                         int newloc;
6632                         expdest = stack_nputstr(p, length, expdest);
6633                         newloc = expdest - (char *)stackblock();
6634                         if (breakall && !inquotes && newloc > startloc) {
6635                                 recordregion(startloc, newloc, 0);
6636                         }
6637                         startloc = newloc;
6638                 }
6639                 p += length + 1;
6640                 length = 0;
6641
6642                 switch (c) {
6643                 case '\0':
6644                         goto breakloop;
6645                 case '=':
6646                         if (flags & EXP_VARTILDE2) {
6647                                 p--;
6648                                 continue;
6649                         }
6650                         flags |= EXP_VARTILDE2;
6651                         reject++;
6652                         /* fall through */
6653                 case ':':
6654                         /*
6655                          * sort of a hack - expand tildes in variable
6656                          * assignments (after the first '=' and after ':'s).
6657                          */
6658                         if (*--p == '~') {
6659                                 goto tilde;
6660                         }
6661                         continue;
6662                 }
6663
6664                 switch (c) {
6665                 case CTLENDVAR: /* ??? */
6666                         goto breakloop;
6667                 case CTLQUOTEMARK:
6668                         /* "$@" syntax adherence hack */
6669                         if (!inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6670                                 p = evalvar(p + 1, flags | EXP_QUOTED) + 1;
6671                                 goto start;
6672                         }
6673                         inquotes ^= EXP_QUOTED;
6674  addquote:
6675                         if (flags & QUOTES_ESC) {
6676                                 p--;
6677                                 length++;
6678                                 startloc++;
6679                         }
6680                         break;
6681                 case CTLESC:
6682                         startloc++;
6683                         length++;
6684                         goto addquote;
6685                 case CTLVAR:
6686                         TRACE(("argstr: evalvar('%s')\n", p));
6687                         p = evalvar(p, flags | inquotes);
6688                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6689                         goto start;
6690                 case CTLBACKQ:
6691                         expbackq(argbackq->n, flags | inquotes);
6692                         argbackq = argbackq->next;
6693                         goto start;
6694 #if ENABLE_FEATURE_SH_MATH
6695                 case CTLENDARI:
6696                         p--;
6697                         expari(flags | inquotes);
6698                         goto start;
6699 #endif
6700                 }
6701         }
6702  breakloop: ;
6703 }
6704
6705 static char *
6706 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6707                 char *pattern, int quotes, int zero)
6708 {
6709         char *loc, *loc2;
6710         char c;
6711
6712         loc = startp;
6713         loc2 = rmesc;
6714         do {
6715                 int match;
6716                 const char *s = loc2;
6717
6718                 c = *loc2;
6719                 if (zero) {
6720                         *loc2 = '\0';
6721                         s = rmesc;
6722                 }
6723                 match = pmatch(pattern, s);
6724
6725                 *loc2 = c;
6726                 if (match)
6727                         return loc;
6728                 if (quotes && (unsigned char)*loc == CTLESC)
6729                         loc++;
6730                 loc++;
6731                 loc2++;
6732         } while (c);
6733         return NULL;
6734 }
6735
6736 static char *
6737 scanright(char *startp, char *rmesc, char *rmescend,
6738                 char *pattern, int quotes, int match_at_start)
6739 {
6740 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6741         int try2optimize = match_at_start;
6742 #endif
6743         int esc = 0;
6744         char *loc;
6745         char *loc2;
6746
6747         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6748          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6749          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6750          * Logic:
6751          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6752          * and on each iteration they go back two/one char until they reach the beginning.
6753          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6754          */
6755         /* TODO: document in what other circumstances we are called. */
6756
6757         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6758                 int match;
6759                 char c = *loc2;
6760                 const char *s = loc2;
6761                 if (match_at_start) {
6762                         *loc2 = '\0';
6763                         s = rmesc;
6764                 }
6765                 match = pmatch(pattern, s);
6766                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6767                 *loc2 = c;
6768                 if (match)
6769                         return loc;
6770 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6771                 if (try2optimize) {
6772                         /* Maybe we can optimize this:
6773                          * if pattern ends with unescaped *, we can avoid checking
6774                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6775                          * it won't match truncated "raw_value_of_" strings too.
6776                          */
6777                         unsigned plen = strlen(pattern);
6778                         /* Does it end with "*"? */
6779                         if (plen != 0 && pattern[--plen] == '*') {
6780                                 /* "xxxx*" is not escaped */
6781                                 /* "xxx\*" is escaped */
6782                                 /* "xx\\*" is not escaped */
6783                                 /* "x\\\*" is escaped */
6784                                 int slashes = 0;
6785                                 while (plen != 0 && pattern[--plen] == '\\')
6786                                         slashes++;
6787                                 if (!(slashes & 1))
6788                                         break; /* ends with unescaped "*" */
6789                         }
6790                         try2optimize = 0;
6791                 }
6792 #endif
6793                 loc--;
6794                 if (quotes) {
6795                         if (--esc < 0) {
6796                                 esc = esclen(startp, loc);
6797                         }
6798                         if (esc % 2) {
6799                                 esc--;
6800                                 loc--;
6801                         }
6802                 }
6803         }
6804         return NULL;
6805 }
6806
6807 static void varunset(const char *, const char *, const char *, int) NORETURN;
6808 static void
6809 varunset(const char *end, const char *var, const char *umsg, int varflags)
6810 {
6811         const char *msg;
6812         const char *tail;
6813
6814         tail = nullstr;
6815         msg = "parameter not set";
6816         if (umsg) {
6817                 if ((unsigned char)*end == CTLENDVAR) {
6818                         if (varflags & VSNUL)
6819                                 tail = " or null";
6820                 } else {
6821                         msg = umsg;
6822                 }
6823         }
6824         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6825 }
6826
6827 static const char *
6828 subevalvar(char *p, char *varname, int strloc, int subtype,
6829                 int startloc, int varflags, int flag)
6830 {
6831         struct nodelist *saveargbackq = argbackq;
6832         int quotes = flag & QUOTES_ESC;
6833         char *startp;
6834         char *loc;
6835         char *rmesc, *rmescend;
6836         char *str;
6837         int amount, resetloc;
6838         int argstr_flags;
6839         IF_BASH_PATTERN_SUBST(int workloc;)
6840         IF_BASH_PATTERN_SUBST(int slash_pos;)
6841         IF_BASH_PATTERN_SUBST(char *repl;)
6842         int zero;
6843         char *(*scan)(char*, char*, char*, char*, int, int);
6844
6845         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6846         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6847
6848 #if BASH_PATTERN_SUBST
6849         /* For "${v/pattern/repl}", we must find the delimiter _before_
6850          * argstr() call expands possible variable references in pattern:
6851          * think about "v=a; a=a/; echo ${v/$a/r}" case.
6852          */
6853         repl = NULL;
6854         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6855                 /* Find '/' and replace with NUL */
6856                 repl = p;
6857                 for (;;) {
6858                         /* Handle escaped slashes, e.g. "${v/\//_}" (they are CTLESC'ed by this point) */
6859                         if (*repl == '\0') {
6860                                 repl = NULL;
6861                                 break;
6862                         }
6863                         if (*repl == '/') {
6864                                 *repl = '\0';
6865                                 break;
6866                         }
6867                         if ((unsigned char)*repl == CTLESC && repl[1])
6868                                 repl++;
6869                         repl++;
6870                 }
6871         }
6872 #endif
6873         argstr_flags = EXP_TILDE;
6874         if (subtype != VSASSIGN
6875          && subtype != VSQUESTION
6876 #if BASH_SUBSTR
6877          && subtype != VSSUBSTR
6878 #endif
6879         ) {
6880                 /* EXP_CASE keeps CTLESC's */
6881                 argstr_flags = EXP_TILDE | EXP_CASE;
6882         }
6883         argstr(p, argstr_flags);
6884         //bb_error_msg("str0:'%s'", (char *)stackblock() + strloc);
6885 #if BASH_PATTERN_SUBST
6886         slash_pos = -1;
6887         if (repl) {
6888                 slash_pos = expdest - ((char *)stackblock() + strloc);
6889                 STPUTC('/', expdest);
6890                 //bb_error_msg("repl+1:'%s'", repl + 1);
6891                 argstr(repl + 1, EXP_TILDE); /* EXP_TILDE: echo "${v/x/~}" expands ~ ! */
6892                 *repl = '/';
6893         }
6894 #endif
6895         STPUTC('\0', expdest);
6896         argbackq = saveargbackq;
6897         startp = (char *)stackblock() + startloc;
6898         //bb_error_msg("str1:'%s'", (char *)stackblock() + strloc);
6899
6900         switch (subtype) {
6901         case VSASSIGN:
6902                 setvar0(varname, startp);
6903                 amount = startp - expdest;
6904                 STADJUST(amount, expdest);
6905                 return startp;
6906
6907         case VSQUESTION:
6908                 varunset(p, varname, startp, varflags);
6909                 /* NOTREACHED */
6910
6911 #if BASH_SUBSTR
6912         case VSSUBSTR: {
6913                 int pos, len, orig_len;
6914                 char *colon;
6915
6916                 loc = str = stackblock() + strloc;
6917
6918                 /* Read POS in ${var:POS:LEN} */
6919                 colon = strchr(loc, ':');
6920                 if (colon) *colon = '\0';
6921                 pos = substr_atoi(loc);
6922                 if (colon) *colon = ':';
6923
6924                 /* Read LEN in ${var:POS:LEN} */
6925                 len = str - startp - 1;
6926                 /* *loc != '\0', guaranteed by parser */
6927                 if (quotes) {
6928                         char *ptr;
6929                         /* Adjust the length by the number of escapes */
6930                         for (ptr = startp; ptr < (str - 1); ptr++) {
6931                                 if ((unsigned char)*ptr == CTLESC) {
6932                                         len--;
6933                                         ptr++;
6934                                 }
6935                         }
6936                 }
6937                 orig_len = len;
6938                 if (*loc++ == ':') {
6939                         /* ${var::LEN} */
6940                         len = substr_atoi(loc);
6941                 } else {
6942                         /* Skip POS in ${var:POS:LEN} */
6943                         len = orig_len;
6944                         while (*loc && *loc != ':')
6945                                 loc++;
6946                         if (*loc++ == ':')
6947                                 len = substr_atoi(loc);
6948                 }
6949                 if (pos < 0) {
6950                         /* ${VAR:$((-n)):l} starts n chars from the end */
6951                         pos = orig_len + pos;
6952                 }
6953                 if ((unsigned)pos >= orig_len) {
6954                         /* apart from obvious ${VAR:999999:l},
6955                          * covers ${VAR:$((-9999999)):l} - result is ""
6956                          * (bash compat)
6957                          */
6958                         pos = 0;
6959                         len = 0;
6960                 }
6961                 if (len < 0) {
6962                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6963                         len = (orig_len - pos) + len;
6964                 }
6965                 if ((unsigned)len > (orig_len - pos))
6966                         len = orig_len - pos;
6967
6968                 for (str = startp; pos; str++, pos--) {
6969                         if (quotes && (unsigned char)*str == CTLESC)
6970                                 str++;
6971                 }
6972                 for (loc = startp; len; len--) {
6973                         if (quotes && (unsigned char)*str == CTLESC)
6974                                 *loc++ = *str++;
6975                         *loc++ = *str++;
6976                 }
6977                 *loc = '\0';
6978                 amount = loc - expdest;
6979                 STADJUST(amount, expdest);
6980                 return loc;
6981         }
6982 #endif /* BASH_SUBSTR */
6983         }
6984
6985         resetloc = expdest - (char *)stackblock();
6986
6987 #if BASH_PATTERN_SUBST
6988         repl = NULL;
6989
6990         /* We'll comeback here if we grow the stack while handling
6991          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6992          * stack will need rebasing, and we'll need to remove our work
6993          * areas each time
6994          */
6995  restart:
6996 #endif
6997
6998         amount = expdest - ((char *)stackblock() + resetloc);
6999         STADJUST(-amount, expdest);
7000         startp = (char *)stackblock() + startloc;
7001
7002         rmesc = startp;
7003         rmescend = (char *)stackblock() + strloc;
7004         //bb_error_msg("str7:'%s'", rmescend);
7005         if (quotes) {
7006 //TODO: how to handle slash_pos here if string changes (shortens?)
7007                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW, NULL);
7008                 if (rmesc != startp) {
7009                         rmescend = expdest;
7010                         startp = (char *)stackblock() + startloc;
7011                 }
7012         }
7013         rmescend--;
7014         str = (char *)stackblock() + strloc;
7015         /*
7016          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
7017          * The result is a_\_z_c (not a\_\_z_c)!
7018          *
7019          * The search pattern and replace string treat backslashes differently!
7020          * "&slash_pos" causes rmescapes() to work differently on the pattern
7021          * and string.  It's only used on the first call.
7022          */
7023         //bb_error_msg("str8:'%s' slash_pos:%d", str, slash_pos);
7024         rmescapes(str, RMESCAPE_GLOB,
7025                 repl ? NULL : (slash_pos < 0 ? NULL : &slash_pos)
7026         );
7027
7028 #if BASH_PATTERN_SUBST
7029         workloc = expdest - (char *)stackblock();
7030         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
7031                 int len;
7032                 char *idx, *end;
7033
7034                 if (!repl) {
7035                         //bb_error_msg("str9:'%s' slash_pos:%d", str, slash_pos);
7036                         repl = nullstr;
7037                         if (slash_pos >= 0) {
7038                                 repl = str + slash_pos;
7039                                 *repl++ = '\0';
7040                         }
7041                 }
7042                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
7043
7044                 /* If there's no pattern to match, return the expansion unmolested */
7045                 if (str[0] == '\0')
7046                         return NULL;
7047
7048                 len = 0;
7049                 idx = startp;
7050                 end = str - 1;
7051                 while (idx < end) {
7052  try_to_match:
7053                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
7054                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
7055                         if (!loc) {
7056                                 /* No match, advance */
7057                                 char *restart_detect = stackblock();
7058  skip_matching:
7059                                 STPUTC(*idx, expdest);
7060                                 if (quotes && (unsigned char)*idx == CTLESC) {
7061                                         idx++;
7062                                         len++;
7063                                         STPUTC(*idx, expdest);
7064                                 }
7065                                 if (stackblock() != restart_detect)
7066                                         goto restart;
7067                                 idx++;
7068                                 len++;
7069                                 rmesc++;
7070                                 /* continue; - prone to quadratic behavior, smarter code: */
7071                                 if (idx >= end)
7072                                         break;
7073                                 if (str[0] == '*') {
7074                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
7075                                          * it would never match "ong_string" etc, no point in trying.
7076                                          */
7077                                         goto skip_matching;
7078                                 }
7079                                 goto try_to_match;
7080                         }
7081
7082                         if (subtype == VSREPLACEALL) {
7083                                 while (idx < loc) {
7084                                         if (quotes && (unsigned char)*idx == CTLESC)
7085                                                 idx++;
7086                                         idx++;
7087                                         rmesc++;
7088                                 }
7089                         } else {
7090                                 idx = loc;
7091                         }
7092
7093                         //bb_error_msg("repl:'%s'", repl);
7094                         for (loc = (char*)repl; *loc; loc++) {
7095                                 char *restart_detect = stackblock();
7096                                 if (quotes && *loc == '\\') {
7097                                         STPUTC(CTLESC, expdest);
7098                                         len++;
7099                                 }
7100                                 STPUTC(*loc, expdest);
7101                                 if (stackblock() != restart_detect)
7102                                         goto restart;
7103                                 len++;
7104                         }
7105
7106                         if (subtype == VSREPLACE) {
7107                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
7108                                 while (*idx) {
7109                                         char *restart_detect = stackblock();
7110                                         STPUTC(*idx, expdest);
7111                                         if (stackblock() != restart_detect)
7112                                                 goto restart;
7113                                         len++;
7114                                         idx++;
7115                                 }
7116                                 break;
7117                         }
7118                 }
7119
7120                 /* We've put the replaced text into a buffer at workloc, now
7121                  * move it to the right place and adjust the stack.
7122                  */
7123                 STPUTC('\0', expdest);
7124                 startp = (char *)stackblock() + startloc;
7125                 memmove(startp, (char *)stackblock() + workloc, len + 1);
7126                 //bb_error_msg("startp:'%s'", startp);
7127                 amount = expdest - (startp + len);
7128                 STADJUST(-amount, expdest);
7129                 return startp;
7130         }
7131 #endif /* BASH_PATTERN_SUBST */
7132
7133         subtype -= VSTRIMRIGHT;
7134 #if DEBUG
7135         if (subtype < 0 || subtype > 7)
7136                 abort();
7137 #endif
7138         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
7139         zero = subtype >> 1;
7140         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
7141         scan = (subtype & 1) ^ zero ? scanleft : scanright;
7142
7143         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
7144         if (loc) {
7145                 if (zero) {
7146                         memmove(startp, loc, str - loc);
7147                         loc = startp + (str - loc) - 1;
7148                 }
7149                 *loc = '\0';
7150                 amount = loc - expdest;
7151                 STADJUST(amount, expdest);
7152         }
7153         return loc;
7154 }
7155
7156 /*
7157  * Add the value of a specialized variable to the stack string.
7158  * name parameter (examples):
7159  * ash -c 'echo $1'      name:'1='
7160  * ash -c 'echo $qwe'    name:'qwe='
7161  * ash -c 'echo $$'      name:'$='
7162  * ash -c 'echo ${$}'    name:'$='
7163  * ash -c 'echo ${$##q}' name:'$=q'
7164  * ash -c 'echo ${#$}'   name:'$='
7165  * note: examples with bad shell syntax:
7166  * ash -c 'echo ${#$1}'  name:'$=1'
7167  * ash -c 'echo ${#1#}'  name:'1=#'
7168  */
7169 static NOINLINE ssize_t
7170 varvalue(char *name, int varflags, int flags, int *quotedp)
7171 {
7172         const char *p;
7173         int num;
7174         int i;
7175         ssize_t len = 0;
7176         int sep;
7177         int quoted = *quotedp;
7178         int subtype = varflags & VSTYPE;
7179         int discard = subtype == VSPLUS || subtype == VSLENGTH;
7180         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
7181         int syntax;
7182
7183         sep = (flags & EXP_FULL) << CHAR_BIT;
7184         syntax = quoted ? DQSYNTAX : BASESYNTAX;
7185
7186         switch (*name) {
7187         case '$':
7188                 num = rootpid;
7189                 goto numvar;
7190         case '?':
7191                 num = exitstatus;
7192                 goto numvar;
7193         case '#':
7194                 num = shellparam.nparam;
7195                 goto numvar;
7196         case '!':
7197                 num = backgndpid;
7198                 if (num == 0)
7199                         return -1;
7200  numvar:
7201                 len = cvtnum(num);
7202                 goto check_1char_name;
7203         case '-':
7204                 expdest = makestrspace(NOPTS, expdest);
7205                 for (i = NOPTS - 1; i >= 0; i--) {
7206                         if (optlist[i] && optletters(i)) {
7207                                 USTPUTC(optletters(i), expdest);
7208                                 len++;
7209                         }
7210                 }
7211  check_1char_name:
7212 #if 0
7213                 /* handles cases similar to ${#$1} */
7214                 if (name[2] != '\0')
7215                         raise_error_syntax("bad substitution");
7216 #endif
7217                 break;
7218         case '@':
7219                 if (quoted && sep)
7220                         goto param;
7221                 /* fall through */
7222         case '*': {
7223                 char **ap;
7224                 char sepc;
7225
7226                 if (quoted)
7227                         sep = 0;
7228                 sep |= ifsset() ? ifsval()[0] : ' ';
7229  param:
7230                 sepc = sep;
7231                 *quotedp = !sepc;
7232                 ap = shellparam.p;
7233                 if (!ap)
7234                         return -1;
7235                 while ((p = *ap++) != NULL) {
7236                         len += strtodest(p, syntax, quotes);
7237
7238                         if (*ap && sep) {
7239                                 len++;
7240                                 memtodest(&sepc, 1, syntax, quotes);
7241                         }
7242                 }
7243                 break;
7244         } /* case '*' */
7245         case '0':
7246         case '1':
7247         case '2':
7248         case '3':
7249         case '4':
7250         case '5':
7251         case '6':
7252         case '7':
7253         case '8':
7254         case '9':
7255                 num = atoi(name); /* number(name) fails on ${N#str} etc */
7256                 if (num < 0 || num > shellparam.nparam)
7257                         return -1;
7258                 p = num ? shellparam.p[num - 1] : arg0;
7259                 goto value;
7260         default:
7261                 /* NB: name has form "VAR=..." */
7262                 p = lookupvar(name);
7263  value:
7264                 if (!p)
7265                         return -1;
7266
7267                 len = strtodest(p, syntax, quotes);
7268 #if ENABLE_UNICODE_SUPPORT
7269                 if (subtype == VSLENGTH && len > 0) {
7270                         reinit_unicode_for_ash();
7271                         if (unicode_status == UNICODE_ON) {
7272                                 STADJUST(-len, expdest);
7273                                 discard = 0;
7274                                 len = unicode_strlen(p);
7275                         }
7276                 }
7277 #endif
7278                 break;
7279         }
7280
7281         if (discard)
7282                 STADJUST(-len, expdest);
7283         return len;
7284 }
7285
7286 /*
7287  * Expand a variable, and return a pointer to the next character in the
7288  * input string.
7289  */
7290 static char *
7291 evalvar(char *p, int flag)
7292 {
7293         char varflags;
7294         char subtype;
7295         int quoted;
7296         char easy;
7297         char *var;
7298         int patloc;
7299         int startloc;
7300         ssize_t varlen;
7301
7302         varflags = (unsigned char) *p++;
7303         subtype = varflags & VSTYPE;
7304
7305         if (!subtype)
7306                 raise_error_syntax("bad substitution");
7307
7308         quoted = flag & EXP_QUOTED;
7309         var = p;
7310         easy = (!quoted || (*var == '@' && shellparam.nparam));
7311         startloc = expdest - (char *)stackblock();
7312         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7313
7314  again:
7315         varlen = varvalue(var, varflags, flag, &quoted);
7316         if (varflags & VSNUL)
7317                 varlen--;
7318
7319         if (subtype == VSPLUS) {
7320                 varlen = -1 - varlen;
7321                 goto vsplus;
7322         }
7323
7324         if (subtype == VSMINUS) {
7325  vsplus:
7326                 if (varlen < 0) {
7327                         argstr(
7328                                 p,
7329                                 flag | EXP_TILDE | EXP_WORD
7330                         );
7331                         goto end;
7332                 }
7333                 goto record;
7334         }
7335
7336         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7337                 if (varlen >= 0)
7338                         goto record;
7339
7340                 subevalvar(p, var, 0, subtype, startloc, varflags,
7341                            flag & ~QUOTES_ESC);
7342                 varflags &= ~VSNUL;
7343                 /*
7344                  * Remove any recorded regions beyond
7345                  * start of variable
7346                  */
7347                 removerecordregions(startloc);
7348                 goto again;
7349         }
7350
7351         if (varlen < 0 && uflag)
7352                 varunset(p, var, 0, 0);
7353
7354         if (subtype == VSLENGTH) {
7355                 cvtnum(varlen > 0 ? varlen : 0);
7356                 goto record;
7357         }
7358
7359         if (subtype == VSNORMAL) {
7360  record:
7361                 if (!easy)
7362                         goto end;
7363                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7364                 goto end;
7365         }
7366
7367 #if DEBUG
7368         switch (subtype) {
7369         case VSTRIMLEFT:
7370         case VSTRIMLEFTMAX:
7371         case VSTRIMRIGHT:
7372         case VSTRIMRIGHTMAX:
7373 #if BASH_SUBSTR
7374         case VSSUBSTR:
7375 #endif
7376 #if BASH_PATTERN_SUBST
7377         case VSREPLACE:
7378         case VSREPLACEALL:
7379 #endif
7380                 break;
7381         default:
7382                 abort();
7383         }
7384 #endif
7385
7386         if (varlen >= 0) {
7387                 /*
7388                  * Terminate the string and start recording the pattern
7389                  * right after it
7390                  */
7391                 STPUTC('\0', expdest);
7392                 patloc = expdest - (char *)stackblock();
7393                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7394                                 startloc, varflags, flag)) {
7395                         int amount = expdest - (
7396                                 (char *)stackblock() + patloc - 1
7397                         );
7398                         STADJUST(-amount, expdest);
7399                 }
7400                 /* Remove any recorded regions beyond start of variable */
7401                 removerecordregions(startloc);
7402                 goto record;
7403         }
7404
7405  end:
7406         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7407                 int nesting = 1;
7408                 for (;;) {
7409                         unsigned char c = *p++;
7410                         if (c == CTLESC)
7411                                 p++;
7412                         else if (c == CTLBACKQ) {
7413                                 if (varlen >= 0)
7414                                         argbackq = argbackq->next;
7415                         } else if (c == CTLVAR) {
7416                                 if ((*p++ & VSTYPE) != VSNORMAL)
7417                                         nesting++;
7418                         } else if (c == CTLENDVAR) {
7419                                 if (--nesting == 0)
7420                                         break;
7421                         }
7422                 }
7423         }
7424         return p;
7425 }
7426
7427 /*
7428  * Add a file name to the list.
7429  */
7430 static void
7431 addfname(const char *name)
7432 {
7433         struct strlist *sp;
7434
7435         sp = stzalloc(sizeof(*sp));
7436         sp->text = sstrdup(name);
7437         *exparg.lastp = sp;
7438         exparg.lastp = &sp->next;
7439 }
7440
7441 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7442 static int
7443 hasmeta(const char *p)
7444 {
7445         static const char chars[] ALIGN1 = {
7446                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7447         };
7448
7449         for (;;) {
7450                 p = strpbrk(p, chars);
7451                 if (!p)
7452                         break;
7453                 switch ((unsigned char)*p) {
7454                 case CTLQUOTEMARK:
7455                         for (;;) {
7456                                 p++;
7457                                 if ((unsigned char)*p == CTLQUOTEMARK)
7458                                         break;
7459                                 if ((unsigned char)*p == CTLESC)
7460                                         p++;
7461                                 if (*p == '\0') /* huh? */
7462                                         return 0;
7463                         }
7464                         break;
7465                 case '\\':
7466                 case CTLESC:
7467                         p++;
7468                         if (*p == '\0')
7469                                 return 0;
7470                         break;
7471                 case '[':
7472                         if (!strchr(p + 1, ']')) {
7473                                 /* It's not a properly closed [] pattern,
7474                                  * but other metas may follow. Continue checking.
7475                                  * my[file* _is_ globbed by bash
7476                                  * and matches filenames like "my[file1".
7477                                  */
7478                                 break;
7479                         }
7480                         /* fallthrough */
7481                 default:
7482                 /* case '*': */
7483                 /* case '?': */
7484                         return 1;
7485                 }
7486                 p++;
7487         }
7488
7489         return 0;
7490 }
7491
7492 /* If we want to use glob() from libc... */
7493 #if !ENABLE_ASH_INTERNAL_GLOB
7494
7495 /* Add the result of glob() to the list */
7496 static void
7497 addglob(const glob_t *pglob)
7498 {
7499         char **p = pglob->gl_pathv;
7500
7501         do {
7502                 addfname(*p);
7503         } while (*++p);
7504 }
7505 static void
7506 expandmeta(struct strlist *str /*, int flag*/)
7507 {
7508         /* TODO - EXP_REDIR */
7509
7510         while (str) {
7511                 char *p;
7512                 glob_t pglob;
7513                 int i;
7514
7515                 if (fflag)
7516                         goto nometa;
7517
7518                 if (!hasmeta(str->text))
7519                         goto nometa;
7520
7521                 INT_OFF;
7522                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7523 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7524 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7525 //
7526 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7527 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7528 // Which means you need to unescape the string, right? Not so fast:
7529 // if there _is_ a file named "file\?" (with backslash), it is returned
7530 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7531 // You DON'T KNOW by looking at the result whether you need to unescape it.
7532 //
7533 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7534 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7535 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7536 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7537 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7538 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7539                 i = glob(p, 0, NULL, &pglob);
7540                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7541                 if (p != str->text)
7542                         free(p);
7543                 switch (i) {
7544                 case 0:
7545 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7546                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7547                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7548                                 goto nometa2;
7549 #endif
7550                         addglob(&pglob);
7551                         globfree(&pglob);
7552                         INT_ON;
7553                         break;
7554                 case GLOB_NOMATCH:
7555  //nometa2:
7556                         globfree(&pglob);
7557                         INT_ON;
7558  nometa:
7559                         *exparg.lastp = str;
7560                         rmescapes(str->text, 0, NULL);
7561                         exparg.lastp = &str->next;
7562                         break;
7563                 default:        /* GLOB_NOSPACE */
7564                         globfree(&pglob);
7565                         INT_ON;
7566                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7567                 }
7568                 str = str->next;
7569         }
7570 }
7571
7572 #else
7573 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7574
7575 /*
7576  * Do metacharacter (i.e. *, ?, [...]) expansion.
7577  */
7578 static void
7579 expmeta(char *expdir, char *enddir, char *name)
7580 {
7581         char *p;
7582         const char *cp;
7583         char *start;
7584         char *endname;
7585         int metaflag;
7586         struct stat statb;
7587         DIR *dirp;
7588         struct dirent *dp;
7589         int atend;
7590         int matchdot;
7591         int esc;
7592
7593         metaflag = 0;
7594         start = name;
7595         for (p = name; esc = 0, *p; p += esc + 1) {
7596                 if (*p == '*' || *p == '?')
7597                         metaflag = 1;
7598                 else if (*p == '[') {
7599                         char *q = p + 1;
7600                         if (*q == '!')
7601                                 q++;
7602                         for (;;) {
7603                                 if (*q == '\\')
7604                                         q++;
7605                                 if (*q == '/' || *q == '\0')
7606                                         break;
7607                                 if (*++q == ']') {
7608                                         metaflag = 1;
7609                                         break;
7610                                 }
7611                         }
7612                 } else {
7613                         if (*p == '\\')
7614                                 esc++;
7615                         if (p[esc] == '/') {
7616                                 if (metaflag)
7617                                         break;
7618                                 start = p + esc + 1;
7619                         }
7620                 }
7621         }
7622         if (metaflag == 0) {    /* we've reached the end of the file name */
7623                 if (enddir != expdir)
7624                         metaflag++;
7625                 p = name;
7626                 do {
7627                         if (*p == '\\')
7628                                 p++;
7629                         *enddir++ = *p;
7630                 } while (*p++);
7631                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7632                         addfname(expdir);
7633                 return;
7634         }
7635         endname = p;
7636         if (name < start) {
7637                 p = name;
7638                 do {
7639                         if (*p == '\\')
7640                                 p++;
7641                         *enddir++ = *p++;
7642                 } while (p < start);
7643         }
7644         if (enddir == expdir) {
7645                 cp = ".";
7646         } else if (enddir == expdir + 1 && *expdir == '/') {
7647                 cp = "/";
7648         } else {
7649                 cp = expdir;
7650                 enddir[-1] = '\0';
7651         }
7652         dirp = opendir(cp);
7653         if (dirp == NULL)
7654                 return;
7655         if (enddir != expdir)
7656                 enddir[-1] = '/';
7657         if (*endname == 0) {
7658                 atend = 1;
7659         } else {
7660                 atend = 0;
7661                 *endname = '\0';
7662                 endname += esc + 1;
7663         }
7664         matchdot = 0;
7665         p = start;
7666         if (*p == '\\')
7667                 p++;
7668         if (*p == '.')
7669                 matchdot++;
7670         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7671                 if (dp->d_name[0] == '.' && !matchdot)
7672                         continue;
7673                 if (pmatch(start, dp->d_name)) {
7674                         if (atend) {
7675                                 strcpy(enddir, dp->d_name);
7676                                 addfname(expdir);
7677                         } else {
7678                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7679                                         continue;
7680                                 p[-1] = '/';
7681                                 expmeta(expdir, p, endname);
7682                         }
7683                 }
7684         }
7685         closedir(dirp);
7686         if (!atend)
7687                 endname[-esc - 1] = esc ? '\\' : '/';
7688 }
7689
7690 static struct strlist *
7691 msort(struct strlist *list, int len)
7692 {
7693         struct strlist *p, *q = NULL;
7694         struct strlist **lpp;
7695         int half;
7696         int n;
7697
7698         if (len <= 1)
7699                 return list;
7700         half = len >> 1;
7701         p = list;
7702         for (n = half; --n >= 0;) {
7703                 q = p;
7704                 p = p->next;
7705         }
7706         q->next = NULL;                 /* terminate first half of list */
7707         q = msort(list, half);          /* sort first half of list */
7708         p = msort(p, len - half);               /* sort second half */
7709         lpp = &list;
7710         for (;;) {
7711 #if ENABLE_LOCALE_SUPPORT
7712                 if (strcoll(p->text, q->text) < 0)
7713 #else
7714                 if (strcmp(p->text, q->text) < 0)
7715 #endif
7716                                                 {
7717                         *lpp = p;
7718                         lpp = &p->next;
7719                         p = *lpp;
7720                         if (p == NULL) {
7721                                 *lpp = q;
7722                                 break;
7723                         }
7724                 } else {
7725                         *lpp = q;
7726                         lpp = &q->next;
7727                         q = *lpp;
7728                         if (q == NULL) {
7729                                 *lpp = p;
7730                                 break;
7731                         }
7732                 }
7733         }
7734         return list;
7735 }
7736
7737 /*
7738  * Sort the results of file name expansion.  It calculates the number of
7739  * strings to sort and then calls msort (short for merge sort) to do the
7740  * work.
7741  */
7742 static struct strlist *
7743 expsort(struct strlist *str)
7744 {
7745         int len;
7746         struct strlist *sp;
7747
7748         len = 0;
7749         for (sp = str; sp; sp = sp->next)
7750                 len++;
7751         return msort(str, len);
7752 }
7753
7754 static void
7755 expandmeta(struct strlist *str /*, int flag*/)
7756 {
7757         /* TODO - EXP_REDIR */
7758
7759         while (str) {
7760                 char *expdir;
7761                 struct strlist **savelastp;
7762                 struct strlist *sp;
7763                 char *p;
7764
7765                 if (fflag)
7766                         goto nometa;
7767                 if (!hasmeta(str->text))
7768                         goto nometa;
7769                 savelastp = exparg.lastp;
7770
7771                 INT_OFF;
7772                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7773                 {
7774                         int i = strlen(str->text);
7775 //BUGGY estimation of how long expanded name can be
7776                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7777                 }
7778                 expmeta(expdir, expdir, p);
7779                 free(expdir);
7780                 if (p != str->text)
7781                         free(p);
7782                 INT_ON;
7783                 if (exparg.lastp == savelastp) {
7784                         /*
7785                          * no matches
7786                          */
7787  nometa:
7788                         *exparg.lastp = str;
7789                         rmescapes(str->text, 0, NULL);
7790                         exparg.lastp = &str->next;
7791                 } else {
7792                         *exparg.lastp = NULL;
7793                         *savelastp = sp = expsort(*savelastp);
7794                         while (sp->next != NULL)
7795                                 sp = sp->next;
7796                         exparg.lastp = &sp->next;
7797                 }
7798                 str = str->next;
7799         }
7800 }
7801 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7802
7803 /*
7804  * Perform variable substitution and command substitution on an argument,
7805  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7806  * perform splitting and file name expansion.  When arglist is NULL, perform
7807  * here document expansion.
7808  */
7809 static void
7810 expandarg(union node *arg, struct arglist *arglist, int flag)
7811 {
7812         struct strlist *sp;
7813         char *p;
7814
7815         argbackq = arg->narg.backquote;
7816         STARTSTACKSTR(expdest);
7817         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7818         argstr(arg->narg.text, flag);
7819         p = _STPUTC('\0', expdest);
7820         expdest = p - 1;
7821         if (arglist == NULL) {
7822                 /* here document expanded */
7823                 goto out;
7824         }
7825         p = grabstackstr(p);
7826         TRACE(("expandarg: p:'%s'\n", p));
7827         exparg.lastp = &exparg.list;
7828         /*
7829          * TODO - EXP_REDIR
7830          */
7831         if (flag & EXP_FULL) {
7832                 ifsbreakup(p, &exparg);
7833                 *exparg.lastp = NULL;
7834                 exparg.lastp = &exparg.list;
7835                 expandmeta(exparg.list /*, flag*/);
7836         } else {
7837                 sp = stzalloc(sizeof(*sp));
7838                 sp->text = p;
7839                 *exparg.lastp = sp;
7840                 exparg.lastp = &sp->next;
7841         }
7842         *exparg.lastp = NULL;
7843         if (exparg.list) {
7844                 *arglist->lastp = exparg.list;
7845                 arglist->lastp = exparg.lastp;
7846         }
7847
7848  out:
7849         ifsfree();
7850 }
7851
7852 /*
7853  * Expand shell variables and backquotes inside a here document.
7854  */
7855 static void
7856 expandhere(union node *arg, int fd)
7857 {
7858         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7859         full_write(fd, stackblock(), expdest - (char *)stackblock());
7860 }
7861
7862 /*
7863  * Returns true if the pattern matches the string.
7864  */
7865 static int
7866 patmatch(char *pattern, const char *string)
7867 {
7868         char *p = preglob(pattern, 0);
7869         int r = pmatch(p, string);
7870         //bb_error_msg("!fnmatch(pattern:'%s',str:'%s',0):%d", p, string, r);
7871         return r;
7872 }
7873
7874 /*
7875  * See if a pattern matches in a case statement.
7876  */
7877 static int
7878 casematch(union node *pattern, char *val)
7879 {
7880         struct stackmark smark;
7881         int result;
7882
7883         setstackmark(&smark);
7884         argbackq = pattern->narg.backquote;
7885         STARTSTACKSTR(expdest);
7886         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7887         STACKSTRNUL(expdest);
7888         ifsfree();
7889         result = patmatch(stackblock(), val);
7890         popstackmark(&smark);
7891         return result;
7892 }
7893
7894
7895 /* ============ find_command */
7896
7897 struct builtincmd {
7898         const char *name;
7899         int (*builtin)(int, char **) FAST_FUNC;
7900         /* unsigned flags; */
7901 };
7902 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7903 /* "regular" builtins always take precedence over commands,
7904  * regardless of PATH=....%builtin... position */
7905 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7906 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7907
7908 struct cmdentry {
7909         smallint cmdtype;       /* CMDxxx */
7910         union param {
7911                 int index;
7912                 /* index >= 0 for commands without path (slashes) */
7913                 /* (TODO: what exactly does the value mean? PATH position?) */
7914                 /* index == -1 for commands with slashes */
7915                 /* index == (-2 - applet_no) for NOFORK applets */
7916                 const struct builtincmd *cmd;
7917                 struct funcnode *func;
7918         } u;
7919 };
7920 /* values of cmdtype */
7921 #define CMDUNKNOWN      -1      /* no entry in table for command */
7922 #define CMDNORMAL       0       /* command is an executable program */
7923 #define CMDFUNCTION     1       /* command is a shell function */
7924 #define CMDBUILTIN      2       /* command is a shell builtin */
7925
7926 /* action to find_command() */
7927 #define DO_ERR          0x01    /* prints errors */
7928 #define DO_ABS          0x02    /* checks absolute paths */
7929 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7930 #define DO_ALTPATH      0x08    /* using alternate path */
7931 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7932
7933 static void find_command(char *, struct cmdentry *, int, const char *);
7934
7935
7936 /* ============ Hashing commands */
7937
7938 /*
7939  * When commands are first encountered, they are entered in a hash table.
7940  * This ensures that a full path search will not have to be done for them
7941  * on each invocation.
7942  *
7943  * We should investigate converting to a linear search, even though that
7944  * would make the command name "hash" a misnomer.
7945  */
7946
7947 struct tblentry {
7948         struct tblentry *next;  /* next entry in hash chain */
7949         union param param;      /* definition of builtin function */
7950         smallint cmdtype;       /* CMDxxx */
7951         char rehash;            /* if set, cd done since entry created */
7952         char cmdname[1];        /* name of command */
7953 };
7954
7955 static struct tblentry **cmdtable;
7956 #define INIT_G_cmdtable() do { \
7957         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7958 } while (0)
7959
7960 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7961
7962
7963 static void
7964 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7965 {
7966 #if ENABLE_FEATURE_SH_STANDALONE
7967         if (applet_no >= 0) {
7968                 if (APPLET_IS_NOEXEC(applet_no)) {
7969                         clearenv();
7970                         while (*envp)
7971                                 putenv(*envp++);
7972                         popredir(/*drop:*/ 1);
7973                         run_noexec_applet_and_exit(applet_no, cmd, argv);
7974                 }
7975                 /* re-exec ourselves with the new arguments */
7976                 execve(bb_busybox_exec_path, argv, envp);
7977                 /* If they called chroot or otherwise made the binary no longer
7978                  * executable, fall through */
7979         }
7980 #endif
7981
7982  repeat:
7983 #ifdef SYSV
7984         do {
7985                 execve(cmd, argv, envp);
7986         } while (errno == EINTR);
7987 #else
7988         execve(cmd, argv, envp);
7989 #endif
7990         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
7991                 /* Run "cmd" as a shell script:
7992                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7993                  * "If the execve() function fails with ENOEXEC, the shell
7994                  * shall execute a command equivalent to having a shell invoked
7995                  * with the command name as its first operand,
7996                  * with any remaining arguments passed to the new shell"
7997                  *
7998                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7999                  * just call ourselves.
8000                  *
8001                  * Note that bash reads ~80 chars of the file, and if it sees
8002                  * a zero byte before it sees newline, it doesn't try to
8003                  * interpret it, but fails with "cannot execute binary file"
8004                  * message and exit code 126. For one, this prevents attempts
8005                  * to interpret foreign ELF binaries as shell scripts.
8006                  */
8007                 argv[0] = (char*) cmd;
8008                 cmd = bb_busybox_exec_path;
8009                 /* NB: this is only possible because all callers of shellexec()
8010                  * ensure that the argv[-1] slot exists!
8011                  */
8012                 argv--;
8013                 argv[0] = (char*) "ash";
8014                 goto repeat;
8015         }
8016 }
8017
8018 /*
8019  * Exec a program.  Never returns.  If you change this routine, you may
8020  * have to change the find_command routine as well.
8021  * argv[-1] must exist and be writable! See tryexec() for why.
8022  */
8023 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
8024 static void shellexec(char *prog, char **argv, const char *path, int idx)
8025 {
8026         char *cmdname;
8027         int e;
8028         char **envp;
8029         int exerrno;
8030         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
8031
8032         envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
8033         if (strchr(prog, '/') != NULL
8034 #if ENABLE_FEATURE_SH_STANDALONE
8035          || (applet_no = find_applet_by_name(prog)) >= 0
8036 #endif
8037         ) {
8038                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
8039                 if (applet_no >= 0) {
8040                         /* We tried execing ourself, but it didn't work.
8041                          * Maybe /proc/self/exe doesn't exist?
8042                          * Try $PATH search.
8043                          */
8044                         goto try_PATH;
8045                 }
8046                 e = errno;
8047         } else {
8048  try_PATH:
8049                 e = ENOENT;
8050                 while ((cmdname = path_advance(&path, prog)) != NULL) {
8051                         if (--idx < 0 && pathopt == NULL) {
8052                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
8053                                 if (errno != ENOENT && errno != ENOTDIR)
8054                                         e = errno;
8055                         }
8056                         stunalloc(cmdname);
8057                 }
8058         }
8059
8060         /* Map to POSIX errors */
8061         switch (e) {
8062         case EACCES:
8063                 exerrno = 126;
8064                 break;
8065         case ENOENT:
8066                 exerrno = 127;
8067                 break;
8068         default:
8069                 exerrno = 2;
8070                 break;
8071         }
8072         exitstatus = exerrno;
8073         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
8074                 prog, e, suppress_int));
8075         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
8076         /* NOTREACHED */
8077 }
8078
8079 static void
8080 printentry(struct tblentry *cmdp)
8081 {
8082         int idx;
8083         const char *path;
8084         char *name;
8085
8086         idx = cmdp->param.index;
8087         path = pathval();
8088         do {
8089                 name = path_advance(&path, cmdp->cmdname);
8090                 stunalloc(name);
8091         } while (--idx >= 0);
8092         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
8093 }
8094
8095 /*
8096  * Clear out command entries.  The argument specifies the first entry in
8097  * PATH which has changed.
8098  */
8099 static void
8100 clearcmdentry(int firstchange)
8101 {
8102         struct tblentry **tblp;
8103         struct tblentry **pp;
8104         struct tblentry *cmdp;
8105
8106         INT_OFF;
8107         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
8108                 pp = tblp;
8109                 while ((cmdp = *pp) != NULL) {
8110                         if ((cmdp->cmdtype == CMDNORMAL &&
8111                              cmdp->param.index >= firstchange)
8112                          || (cmdp->cmdtype == CMDBUILTIN &&
8113                              builtinloc >= firstchange)
8114                         ) {
8115                                 *pp = cmdp->next;
8116                                 free(cmdp);
8117                         } else {
8118                                 pp = &cmdp->next;
8119                         }
8120                 }
8121         }
8122         INT_ON;
8123 }
8124
8125 /*
8126  * Locate a command in the command hash table.  If "add" is nonzero,
8127  * add the command to the table if it is not already present.  The
8128  * variable "lastcmdentry" is set to point to the address of the link
8129  * pointing to the entry, so that delete_cmd_entry can delete the
8130  * entry.
8131  *
8132  * Interrupts must be off if called with add != 0.
8133  */
8134 static struct tblentry **lastcmdentry;
8135
8136 static struct tblentry *
8137 cmdlookup(const char *name, int add)
8138 {
8139         unsigned int hashval;
8140         const char *p;
8141         struct tblentry *cmdp;
8142         struct tblentry **pp;
8143
8144         p = name;
8145         hashval = (unsigned char)*p << 4;
8146         while (*p)
8147                 hashval += (unsigned char)*p++;
8148         hashval &= 0x7FFF;
8149         pp = &cmdtable[hashval % CMDTABLESIZE];
8150         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8151                 if (strcmp(cmdp->cmdname, name) == 0)
8152                         break;
8153                 pp = &cmdp->next;
8154         }
8155         if (add && cmdp == NULL) {
8156                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
8157                                 + strlen(name)
8158                                 /* + 1 - already done because
8159                                  * tblentry::cmdname is char[1] */);
8160                 /*cmdp->next = NULL; - ckzalloc did it */
8161                 cmdp->cmdtype = CMDUNKNOWN;
8162                 strcpy(cmdp->cmdname, name);
8163         }
8164         lastcmdentry = pp;
8165         return cmdp;
8166 }
8167
8168 /*
8169  * Delete the command entry returned on the last lookup.
8170  */
8171 static void
8172 delete_cmd_entry(void)
8173 {
8174         struct tblentry *cmdp;
8175
8176         INT_OFF;
8177         cmdp = *lastcmdentry;
8178         *lastcmdentry = cmdp->next;
8179         if (cmdp->cmdtype == CMDFUNCTION)
8180                 freefunc(cmdp->param.func);
8181         free(cmdp);
8182         INT_ON;
8183 }
8184
8185 /*
8186  * Add a new command entry, replacing any existing command entry for
8187  * the same name - except special builtins.
8188  */
8189 static void
8190 addcmdentry(char *name, struct cmdentry *entry)
8191 {
8192         struct tblentry *cmdp;
8193
8194         cmdp = cmdlookup(name, 1);
8195         if (cmdp->cmdtype == CMDFUNCTION) {
8196                 freefunc(cmdp->param.func);
8197         }
8198         cmdp->cmdtype = entry->cmdtype;
8199         cmdp->param = entry->u;
8200         cmdp->rehash = 0;
8201 }
8202
8203 static int FAST_FUNC
8204 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8205 {
8206         struct tblentry **pp;
8207         struct tblentry *cmdp;
8208         int c;
8209         struct cmdentry entry;
8210         char *name;
8211
8212         if (nextopt("r") != '\0') {
8213                 clearcmdentry(0);
8214                 return 0;
8215         }
8216
8217         if (*argptr == NULL) {
8218                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8219                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8220                                 if (cmdp->cmdtype == CMDNORMAL)
8221                                         printentry(cmdp);
8222                         }
8223                 }
8224                 return 0;
8225         }
8226
8227         c = 0;
8228         while ((name = *argptr) != NULL) {
8229                 cmdp = cmdlookup(name, 0);
8230                 if (cmdp != NULL
8231                  && (cmdp->cmdtype == CMDNORMAL
8232                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8233                 ) {
8234                         delete_cmd_entry();
8235                 }
8236                 find_command(name, &entry, DO_ERR, pathval());
8237                 if (entry.cmdtype == CMDUNKNOWN)
8238                         c = 1;
8239                 argptr++;
8240         }
8241         return c;
8242 }
8243
8244 /*
8245  * Called when a cd is done.  Marks all commands so the next time they
8246  * are executed they will be rehashed.
8247  */
8248 static void
8249 hashcd(void)
8250 {
8251         struct tblentry **pp;
8252         struct tblentry *cmdp;
8253
8254         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8255                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8256                         if (cmdp->cmdtype == CMDNORMAL
8257                          || (cmdp->cmdtype == CMDBUILTIN
8258                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8259                              && builtinloc > 0)
8260                         ) {
8261                                 cmdp->rehash = 1;
8262                         }
8263                 }
8264         }
8265 }
8266
8267 /*
8268  * Fix command hash table when PATH changed.
8269  * Called before PATH is changed.  The argument is the new value of PATH;
8270  * pathval() still returns the old value at this point.
8271  * Called with interrupts off.
8272  */
8273 static void FAST_FUNC
8274 changepath(const char *new)
8275 {
8276         const char *old;
8277         int firstchange;
8278         int idx;
8279         int idx_bltin;
8280
8281         old = pathval();
8282         firstchange = 9999;     /* assume no change */
8283         idx = 0;
8284         idx_bltin = -1;
8285         for (;;) {
8286                 if (*old != *new) {
8287                         firstchange = idx;
8288                         if ((*old == '\0' && *new == ':')
8289                          || (*old == ':' && *new == '\0')
8290                         ) {
8291                                 firstchange++;
8292                         }
8293                         old = new;      /* ignore subsequent differences */
8294                 }
8295                 if (*new == '\0')
8296                         break;
8297                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8298                         idx_bltin = idx;
8299                 if (*new == ':')
8300                         idx++;
8301                 new++;
8302                 old++;
8303         }
8304         if (builtinloc < 0 && idx_bltin >= 0)
8305                 builtinloc = idx_bltin;             /* zap builtins */
8306         if (builtinloc >= 0 && idx_bltin < 0)
8307                 firstchange = 0;
8308         clearcmdentry(firstchange);
8309         builtinloc = idx_bltin;
8310 }
8311 enum {
8312         TEOF,
8313         TNL,
8314         TREDIR,
8315         TWORD,
8316         TSEMI,
8317         TBACKGND,
8318         TAND,
8319         TOR,
8320         TPIPE,
8321         TLP,
8322         TRP,
8323         TENDCASE,
8324         TENDBQUOTE,
8325         TNOT,
8326         TCASE,
8327         TDO,
8328         TDONE,
8329         TELIF,
8330         TELSE,
8331         TESAC,
8332         TFI,
8333         TFOR,
8334 #if BASH_FUNCTION
8335         TFUNCTION,
8336 #endif
8337         TIF,
8338         TIN,
8339         TTHEN,
8340         TUNTIL,
8341         TWHILE,
8342         TBEGIN,
8343         TEND
8344 };
8345 typedef smallint token_id_t;
8346
8347 /* Nth bit indicates if token marks the end of a list */
8348 enum {
8349         tokendlist = 0
8350         /*  0 */ | (1u << TEOF)
8351         /*  1 */ | (0u << TNL)
8352         /*  2 */ | (0u << TREDIR)
8353         /*  3 */ | (0u << TWORD)
8354         /*  4 */ | (0u << TSEMI)
8355         /*  5 */ | (0u << TBACKGND)
8356         /*  6 */ | (0u << TAND)
8357         /*  7 */ | (0u << TOR)
8358         /*  8 */ | (0u << TPIPE)
8359         /*  9 */ | (0u << TLP)
8360         /* 10 */ | (1u << TRP)
8361         /* 11 */ | (1u << TENDCASE)
8362         /* 12 */ | (1u << TENDBQUOTE)
8363         /* 13 */ | (0u << TNOT)
8364         /* 14 */ | (0u << TCASE)
8365         /* 15 */ | (1u << TDO)
8366         /* 16 */ | (1u << TDONE)
8367         /* 17 */ | (1u << TELIF)
8368         /* 18 */ | (1u << TELSE)
8369         /* 19 */ | (1u << TESAC)
8370         /* 20 */ | (1u << TFI)
8371         /* 21 */ | (0u << TFOR)
8372 #if BASH_FUNCTION
8373         /* 22 */ | (0u << TFUNCTION)
8374 #endif
8375         /* 23 */ | (0u << TIF)
8376         /* 24 */ | (0u << TIN)
8377         /* 25 */ | (1u << TTHEN)
8378         /* 26 */ | (0u << TUNTIL)
8379         /* 27 */ | (0u << TWHILE)
8380         /* 28 */ | (0u << TBEGIN)
8381         /* 29 */ | (1u << TEND)
8382         , /* thus far 29 bits used */
8383 };
8384
8385 static const char *const tokname_array[] = {
8386         "end of file",
8387         "newline",
8388         "redirection",
8389         "word",
8390         ";",
8391         "&",
8392         "&&",
8393         "||",
8394         "|",
8395         "(",
8396         ")",
8397         ";;",
8398         "`",
8399 #define KWDOFFSET 13
8400         /* the following are keywords */
8401         "!",
8402         "case",
8403         "do",
8404         "done",
8405         "elif",
8406         "else",
8407         "esac",
8408         "fi",
8409         "for",
8410 #if BASH_FUNCTION
8411         "function",
8412 #endif
8413         "if",
8414         "in",
8415         "then",
8416         "until",
8417         "while",
8418         "{",
8419         "}",
8420 };
8421
8422 /* Wrapper around strcmp for qsort/bsearch/... */
8423 static int
8424 pstrcmp(const void *a, const void *b)
8425 {
8426         return strcmp((char*)a, *(char**)b);
8427 }
8428
8429 static const char *const *
8430 findkwd(const char *s)
8431 {
8432         return bsearch(s, tokname_array + KWDOFFSET,
8433                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8434                         sizeof(tokname_array[0]), pstrcmp);
8435 }
8436
8437 /*
8438  * Locate and print what a word is...
8439  */
8440 static int
8441 describe_command(char *command, const char *path, int describe_command_verbose)
8442 {
8443         struct cmdentry entry;
8444 #if ENABLE_ASH_ALIAS
8445         const struct alias *ap;
8446 #endif
8447
8448         path = path ? path : pathval();
8449
8450         if (describe_command_verbose) {
8451                 out1str(command);
8452         }
8453
8454         /* First look at the keywords */
8455         if (findkwd(command)) {
8456                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8457                 goto out;
8458         }
8459
8460 #if ENABLE_ASH_ALIAS
8461         /* Then look at the aliases */
8462         ap = lookupalias(command, 0);
8463         if (ap != NULL) {
8464                 if (!describe_command_verbose) {
8465                         out1str("alias ");
8466                         printalias(ap);
8467                         return 0;
8468                 }
8469                 out1fmt(" is an alias for %s", ap->val);
8470                 goto out;
8471         }
8472 #endif
8473         /* Brute force */
8474         find_command(command, &entry, DO_ABS, path);
8475
8476         switch (entry.cmdtype) {
8477         case CMDNORMAL: {
8478                 int j = entry.u.index;
8479                 char *p;
8480                 if (j < 0) {
8481                         p = command;
8482                 } else {
8483                         do {
8484                                 p = path_advance(&path, command);
8485                                 stunalloc(p);
8486                         } while (--j >= 0);
8487                 }
8488                 if (describe_command_verbose) {
8489                         out1fmt(" is %s", p);
8490                 } else {
8491                         out1str(p);
8492                 }
8493                 break;
8494         }
8495
8496         case CMDFUNCTION:
8497                 if (describe_command_verbose) {
8498                         out1str(" is a shell function");
8499                 } else {
8500                         out1str(command);
8501                 }
8502                 break;
8503
8504         case CMDBUILTIN:
8505                 if (describe_command_verbose) {
8506                         out1fmt(" is a %sshell builtin",
8507                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8508                                         "special " : nullstr
8509                         );
8510                 } else {
8511                         out1str(command);
8512                 }
8513                 break;
8514
8515         default:
8516                 if (describe_command_verbose) {
8517                         out1str(": not found\n");
8518                 }
8519                 return 127;
8520         }
8521  out:
8522         out1str("\n");
8523         return 0;
8524 }
8525
8526 static int FAST_FUNC
8527 typecmd(int argc UNUSED_PARAM, char **argv)
8528 {
8529         int i = 1;
8530         int err = 0;
8531         int verbose = 1;
8532
8533         /* type -p ... ? (we don't bother checking for 'p') */
8534         if (argv[1] && argv[1][0] == '-') {
8535                 i++;
8536                 verbose = 0;
8537         }
8538         while (argv[i]) {
8539                 err |= describe_command(argv[i++], NULL, verbose);
8540         }
8541         return err;
8542 }
8543
8544 #if ENABLE_ASH_CMDCMD
8545 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8546 static char **
8547 parse_command_args(char **argv, const char **path)
8548 {
8549         char *cp, c;
8550
8551         for (;;) {
8552                 cp = *++argv;
8553                 if (!cp)
8554                         return NULL;
8555                 if (*cp++ != '-')
8556                         break;
8557                 c = *cp++;
8558                 if (!c)
8559                         break;
8560                 if (c == '-' && !*cp) {
8561                         if (!*++argv)
8562                                 return NULL;
8563                         break;
8564                 }
8565                 do {
8566                         switch (c) {
8567                         case 'p':
8568                                 *path = bb_default_path;
8569                                 break;
8570                         default:
8571                                 /* run 'typecmd' for other options */
8572                                 return NULL;
8573                         }
8574                         c = *cp++;
8575                 } while (c);
8576         }
8577         return argv;
8578 }
8579
8580 static int FAST_FUNC
8581 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8582 {
8583         char *cmd;
8584         int c;
8585         enum {
8586                 VERIFY_BRIEF = 1,
8587                 VERIFY_VERBOSE = 2,
8588         } verify = 0;
8589         const char *path = NULL;
8590
8591         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8592          * never reaches this function.
8593          */
8594
8595         while ((c = nextopt("pvV")) != '\0')
8596                 if (c == 'V')
8597                         verify |= VERIFY_VERBOSE;
8598                 else if (c == 'v')
8599                         /*verify |= VERIFY_BRIEF*/;
8600 #if DEBUG
8601                 else if (c != 'p')
8602                         abort();
8603 #endif
8604                 else
8605                         path = bb_default_path;
8606
8607         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8608         cmd = *argptr;
8609         if (/*verify && */ cmd)
8610                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8611
8612         return 0;
8613 }
8614 #endif
8615
8616
8617 /*static int funcblocksize;     // size of structures in function */
8618 /*static int funcstringsize;    // size of strings in node */
8619 static void *funcblock;         /* block to allocate function from */
8620 static char *funcstring_end;    /* end of block to allocate strings from */
8621
8622 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8623         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8624         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8625         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8626         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8627         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8628         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8629         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8630         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8631         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8632         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8633         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8634         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8635         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8636         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8637         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8638         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8639         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8640 #if BASH_REDIR_OUTPUT
8641         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8642 #endif
8643         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8644         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8645         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8646         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8647         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8648         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8649         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8650         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8651         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8652 };
8653
8654 static int calcsize(int funcblocksize, union node *n);
8655
8656 static int
8657 sizenodelist(int funcblocksize, struct nodelist *lp)
8658 {
8659         while (lp) {
8660                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8661                 funcblocksize = calcsize(funcblocksize, lp->n);
8662                 lp = lp->next;
8663         }
8664         return funcblocksize;
8665 }
8666
8667 static int
8668 calcsize(int funcblocksize, union node *n)
8669 {
8670         if (n == NULL)
8671                 return funcblocksize;
8672         funcblocksize += nodesize[n->type];
8673         switch (n->type) {
8674         case NCMD:
8675                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8676                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8677                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8678                 break;
8679         case NPIPE:
8680                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8681                 break;
8682         case NREDIR:
8683         case NBACKGND:
8684         case NSUBSHELL:
8685                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8686                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8687                 break;
8688         case NAND:
8689         case NOR:
8690         case NSEMI:
8691         case NWHILE:
8692         case NUNTIL:
8693                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8694                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8695                 break;
8696         case NIF:
8697                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8698                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8699                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8700                 break;
8701         case NFOR:
8702                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8703                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8704                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8705                 break;
8706         case NCASE:
8707                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8708                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8709                 break;
8710         case NCLIST:
8711                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8712                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8713                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8714                 break;
8715         case NDEFUN:
8716                 funcblocksize = calcsize(funcblocksize, n->ndefun.body);
8717                 funcblocksize += SHELL_ALIGN(strlen(n->ndefun.text) + 1);
8718                 break;
8719         case NARG:
8720                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8721                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8722                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8723                 break;
8724         case NTO:
8725 #if BASH_REDIR_OUTPUT
8726         case NTO2:
8727 #endif
8728         case NCLOBBER:
8729         case NFROM:
8730         case NFROMTO:
8731         case NAPPEND:
8732                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8733                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8734                 break;
8735         case NTOFD:
8736         case NFROMFD:
8737                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8738                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8739         break;
8740         case NHERE:
8741         case NXHERE:
8742                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8743                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8744                 break;
8745         case NNOT:
8746                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8747                 break;
8748         };
8749         return funcblocksize;
8750 }
8751
8752 static char *
8753 nodeckstrdup(char *s)
8754 {
8755         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8756         return strcpy(funcstring_end, s);
8757 }
8758
8759 static union node *copynode(union node *);
8760
8761 static struct nodelist *
8762 copynodelist(struct nodelist *lp)
8763 {
8764         struct nodelist *start;
8765         struct nodelist **lpp;
8766
8767         lpp = &start;
8768         while (lp) {
8769                 *lpp = funcblock;
8770                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8771                 (*lpp)->n = copynode(lp->n);
8772                 lp = lp->next;
8773                 lpp = &(*lpp)->next;
8774         }
8775         *lpp = NULL;
8776         return start;
8777 }
8778
8779 static union node *
8780 copynode(union node *n)
8781 {
8782         union node *new;
8783
8784         if (n == NULL)
8785                 return NULL;
8786         new = funcblock;
8787         funcblock = (char *) funcblock + nodesize[n->type];
8788
8789         switch (n->type) {
8790         case NCMD:
8791                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8792                 new->ncmd.args = copynode(n->ncmd.args);
8793                 new->ncmd.assign = copynode(n->ncmd.assign);
8794                 new->ncmd.linno = n->ncmd.linno;
8795                 break;
8796         case NPIPE:
8797                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8798                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8799                 break;
8800         case NREDIR:
8801         case NBACKGND:
8802         case NSUBSHELL:
8803                 new->nredir.redirect = copynode(n->nredir.redirect);
8804                 new->nredir.n = copynode(n->nredir.n);
8805                 new->nredir.linno = n->nredir.linno;
8806                 break;
8807         case NAND:
8808         case NOR:
8809         case NSEMI:
8810         case NWHILE:
8811         case NUNTIL:
8812                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8813                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8814                 break;
8815         case NIF:
8816                 new->nif.elsepart = copynode(n->nif.elsepart);
8817                 new->nif.ifpart = copynode(n->nif.ifpart);
8818                 new->nif.test = copynode(n->nif.test);
8819                 break;
8820         case NFOR:
8821                 new->nfor.var = nodeckstrdup(n->nfor.var);
8822                 new->nfor.body = copynode(n->nfor.body);
8823                 new->nfor.args = copynode(n->nfor.args);
8824                 new->nfor.linno = n->nfor.linno;
8825                 break;
8826         case NCASE:
8827                 new->ncase.cases = copynode(n->ncase.cases);
8828                 new->ncase.expr = copynode(n->ncase.expr);
8829                 new->ncase.linno = n->ncase.linno;
8830                 break;
8831         case NCLIST:
8832                 new->nclist.body = copynode(n->nclist.body);
8833                 new->nclist.pattern = copynode(n->nclist.pattern);
8834                 new->nclist.next = copynode(n->nclist.next);
8835                 break;
8836         case NDEFUN:
8837                 new->ndefun.body = copynode(n->ndefun.body);
8838                 new->ndefun.text = nodeckstrdup(n->ndefun.text);
8839                 new->ndefun.linno = n->ndefun.linno;
8840                 break;
8841         case NARG:
8842                 new->narg.backquote = copynodelist(n->narg.backquote);
8843                 new->narg.text = nodeckstrdup(n->narg.text);
8844                 new->narg.next = copynode(n->narg.next);
8845                 break;
8846         case NTO:
8847 #if BASH_REDIR_OUTPUT
8848         case NTO2:
8849 #endif
8850         case NCLOBBER:
8851         case NFROM:
8852         case NFROMTO:
8853         case NAPPEND:
8854                 new->nfile.fname = copynode(n->nfile.fname);
8855                 new->nfile.fd = n->nfile.fd;
8856                 new->nfile.next = copynode(n->nfile.next);
8857                 break;
8858         case NTOFD:
8859         case NFROMFD:
8860                 new->ndup.vname = copynode(n->ndup.vname);
8861                 new->ndup.dupfd = n->ndup.dupfd;
8862                 new->ndup.fd = n->ndup.fd;
8863                 new->ndup.next = copynode(n->ndup.next);
8864                 break;
8865         case NHERE:
8866         case NXHERE:
8867                 new->nhere.doc = copynode(n->nhere.doc);
8868                 new->nhere.fd = n->nhere.fd;
8869                 new->nhere.next = copynode(n->nhere.next);
8870                 break;
8871         case NNOT:
8872                 new->nnot.com = copynode(n->nnot.com);
8873                 break;
8874         };
8875         new->type = n->type;
8876         return new;
8877 }
8878
8879 /*
8880  * Make a copy of a parse tree.
8881  */
8882 static struct funcnode *
8883 copyfunc(union node *n)
8884 {
8885         struct funcnode *f;
8886         size_t blocksize;
8887
8888         /*funcstringsize = 0;*/
8889         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8890         f = ckzalloc(blocksize /* + funcstringsize */);
8891         funcblock = (char *) f + offsetof(struct funcnode, n);
8892         funcstring_end = (char *) f + blocksize;
8893         copynode(n);
8894         /* f->count = 0; - ckzalloc did it */
8895         return f;
8896 }
8897
8898 /*
8899  * Define a shell function.
8900  */
8901 static void
8902 defun(union node *func)
8903 {
8904         struct cmdentry entry;
8905
8906         INT_OFF;
8907         entry.cmdtype = CMDFUNCTION;
8908         entry.u.func = copyfunc(func);
8909         addcmdentry(func->ndefun.text, &entry);
8910         INT_ON;
8911 }
8912
8913 /* Reasons for skipping commands (see comment on breakcmd routine) */
8914 #define SKIPBREAK      (1 << 0)
8915 #define SKIPCONT       (1 << 1)
8916 #define SKIPFUNC       (1 << 2)
8917 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8918 static int skipcount;           /* number of levels to skip */
8919 static int loopnest;            /* current loop nesting level */
8920 static int funcline;            /* starting line number of current function, or 0 if not in a function */
8921
8922 /* Forward decl way out to parsing code - dotrap needs it */
8923 static int evalstring(char *s, int flags);
8924
8925 /* Called to execute a trap.
8926  * Single callsite - at the end of evaltree().
8927  * If we return non-zero, evaltree raises EXEXIT exception.
8928  *
8929  * Perhaps we should avoid entering new trap handlers
8930  * while we are executing a trap handler. [is it a TODO?]
8931  */
8932 static void
8933 dotrap(void)
8934 {
8935         uint8_t *g;
8936         int sig;
8937         uint8_t last_status;
8938
8939         if (!pending_sig)
8940                 return;
8941
8942         last_status = exitstatus;
8943         pending_sig = 0;
8944         barrier();
8945
8946         TRACE(("dotrap entered\n"));
8947         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8948                 char *p;
8949
8950                 if (!*g)
8951                         continue;
8952
8953                 if (evalskip) {
8954                         pending_sig = sig;
8955                         break;
8956                 }
8957
8958                 p = trap[sig];
8959                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8960                  * don't upset it by resetting gotsig[SIGINT-1] */
8961                 if (sig == SIGINT && !p)
8962                         continue;
8963
8964                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8965                 *g = 0;
8966                 if (!p)
8967                         continue;
8968                 evalstring(p, 0);
8969         }
8970         exitstatus = last_status;
8971         TRACE(("dotrap returns\n"));
8972 }
8973
8974 /* forward declarations - evaluation is fairly recursive business... */
8975 static int evalloop(union node *, int);
8976 static int evalfor(union node *, int);
8977 static int evalcase(union node *, int);
8978 static int evalsubshell(union node *, int);
8979 static void expredir(union node *);
8980 static int evalpipe(union node *, int);
8981 static int evalcommand(union node *, int);
8982 static int evalbltin(const struct builtincmd *, int, char **, int);
8983 static void prehash(union node *);
8984
8985 /*
8986  * Evaluate a parse tree.  The value is left in the global variable
8987  * exitstatus.
8988  */
8989 static int
8990 evaltree(union node *n, int flags)
8991 {
8992         int checkexit = 0;
8993         int (*evalfn)(union node *, int);
8994         int status = 0;
8995
8996         if (n == NULL) {
8997                 TRACE(("evaltree(NULL) called\n"));
8998                 goto out;
8999         }
9000         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
9001
9002         dotrap();
9003
9004         switch (n->type) {
9005         default:
9006 #if DEBUG
9007                 out1fmt("Node type = %d\n", n->type);
9008                 fflush_all();
9009                 break;
9010 #endif
9011         case NNOT:
9012                 status = !evaltree(n->nnot.com, EV_TESTED);
9013                 goto setstatus;
9014         case NREDIR:
9015                 errlinno = lineno = n->nredir.linno;
9016                 if (funcline)
9017                         lineno -= funcline - 1;
9018                 expredir(n->nredir.redirect);
9019                 pushredir(n->nredir.redirect);
9020                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
9021                 if (!status) {
9022                         status = evaltree(n->nredir.n, flags & EV_TESTED);
9023                 }
9024                 if (n->nredir.redirect)
9025                         popredir(/*drop:*/ 0);
9026                 goto setstatus;
9027         case NCMD:
9028                 evalfn = evalcommand;
9029  checkexit:
9030                 if (eflag && !(flags & EV_TESTED))
9031                         checkexit = ~0;
9032                 goto calleval;
9033         case NFOR:
9034                 evalfn = evalfor;
9035                 goto calleval;
9036         case NWHILE:
9037         case NUNTIL:
9038                 evalfn = evalloop;
9039                 goto calleval;
9040         case NSUBSHELL:
9041         case NBACKGND:
9042                 evalfn = evalsubshell;
9043                 goto checkexit;
9044         case NPIPE:
9045                 evalfn = evalpipe;
9046                 goto checkexit;
9047         case NCASE:
9048                 evalfn = evalcase;
9049                 goto calleval;
9050         case NAND:
9051         case NOR:
9052         case NSEMI: {
9053
9054 #if NAND + 1 != NOR
9055 #error NAND + 1 != NOR
9056 #endif
9057 #if NOR + 1 != NSEMI
9058 #error NOR + 1 != NSEMI
9059 #endif
9060                 unsigned is_or = n->type - NAND;
9061                 status = evaltree(
9062                         n->nbinary.ch1,
9063                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
9064                 );
9065                 if ((!status) == is_or || evalskip)
9066                         break;
9067                 n = n->nbinary.ch2;
9068  evaln:
9069                 evalfn = evaltree;
9070  calleval:
9071                 status = evalfn(n, flags);
9072                 goto setstatus;
9073         }
9074         case NIF:
9075                 status = evaltree(n->nif.test, EV_TESTED);
9076                 if (evalskip)
9077                         break;
9078                 if (!status) {
9079                         n = n->nif.ifpart;
9080                         goto evaln;
9081                 }
9082                 if (n->nif.elsepart) {
9083                         n = n->nif.elsepart;
9084                         goto evaln;
9085                 }
9086                 status = 0;
9087                 goto setstatus;
9088         case NDEFUN:
9089                 defun(n);
9090                 /* Not necessary. To test it:
9091                  * "false; f() { qwerty; }; echo $?" should print 0.
9092                  */
9093                 /* status = 0; */
9094  setstatus:
9095                 exitstatus = status;
9096                 break;
9097         }
9098  out:
9099         /* Order of checks below is important:
9100          * signal handlers trigger before exit caused by "set -e".
9101          */
9102         dotrap();
9103
9104         if (checkexit & status)
9105                 raise_exception(EXEXIT);
9106         if (flags & EV_EXIT)
9107                 raise_exception(EXEXIT);
9108
9109         TRACE(("leaving evaltree (no interrupts)\n"));
9110         return exitstatus;
9111 }
9112
9113 static int
9114 skiploop(void)
9115 {
9116         int skip = evalskip;
9117
9118         switch (skip) {
9119         case 0:
9120                 break;
9121         case SKIPBREAK:
9122         case SKIPCONT:
9123                 if (--skipcount <= 0) {
9124                         evalskip = 0;
9125                         break;
9126                 }
9127                 skip = SKIPBREAK;
9128                 break;
9129         }
9130         return skip;
9131 }
9132
9133 static int
9134 evalloop(union node *n, int flags)
9135 {
9136         int skip;
9137         int status;
9138
9139         loopnest++;
9140         status = 0;
9141         flags &= EV_TESTED;
9142         do {
9143                 int i;
9144
9145                 i = evaltree(n->nbinary.ch1, EV_TESTED);
9146                 skip = skiploop();
9147                 if (skip == SKIPFUNC)
9148                         status = i;
9149                 if (skip)
9150                         continue;
9151                 if (n->type != NWHILE)
9152                         i = !i;
9153                 if (i != 0)
9154                         break;
9155                 status = evaltree(n->nbinary.ch2, flags);
9156                 skip = skiploop();
9157         } while (!(skip & ~SKIPCONT));
9158         loopnest--;
9159
9160         return status;
9161 }
9162
9163 static int
9164 evalfor(union node *n, int flags)
9165 {
9166         struct arglist arglist;
9167         union node *argp;
9168         struct strlist *sp;
9169         struct stackmark smark;
9170         int status = 0;
9171
9172         errlinno = lineno = n->ncase.linno;
9173         if (funcline)
9174                 lineno -= funcline - 1;
9175
9176         setstackmark(&smark);
9177         arglist.list = NULL;
9178         arglist.lastp = &arglist.list;
9179         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
9180                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9181         }
9182         *arglist.lastp = NULL;
9183
9184         loopnest++;
9185         flags &= EV_TESTED;
9186         for (sp = arglist.list; sp; sp = sp->next) {
9187                 setvar0(n->nfor.var, sp->text);
9188                 status = evaltree(n->nfor.body, flags);
9189                 if (skiploop() & ~SKIPCONT)
9190                         break;
9191         }
9192         loopnest--;
9193         popstackmark(&smark);
9194
9195         return status;
9196 }
9197
9198 static int
9199 evalcase(union node *n, int flags)
9200 {
9201         union node *cp;
9202         union node *patp;
9203         struct arglist arglist;
9204         struct stackmark smark;
9205         int status = 0;
9206
9207         errlinno = lineno = n->ncase.linno;
9208         if (funcline)
9209                 lineno -= funcline - 1;
9210
9211         setstackmark(&smark);
9212         arglist.list = NULL;
9213         arglist.lastp = &arglist.list;
9214         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9215         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9216                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9217                         if (casematch(patp, arglist.list->text)) {
9218                                 /* Ensure body is non-empty as otherwise
9219                                  * EV_EXIT may prevent us from setting the
9220                                  * exit status.
9221                                  */
9222                                 if (evalskip == 0 && cp->nclist.body) {
9223                                         status = evaltree(cp->nclist.body, flags);
9224                                 }
9225                                 goto out;
9226                         }
9227                 }
9228         }
9229  out:
9230         popstackmark(&smark);
9231
9232         return status;
9233 }
9234
9235 /*
9236  * Kick off a subshell to evaluate a tree.
9237  */
9238 static int
9239 evalsubshell(union node *n, int flags)
9240 {
9241         struct job *jp;
9242         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9243         int status;
9244
9245         errlinno = lineno = n->nredir.linno;
9246         if (funcline)
9247                 lineno -= funcline - 1;
9248
9249         expredir(n->nredir.redirect);
9250         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9251                 goto nofork;
9252         INT_OFF;
9253         if (backgnd == FORK_FG)
9254                 get_tty_state();
9255         jp = makejob(/*n,*/ 1);
9256         if (forkshell(jp, n, backgnd) == 0) {
9257                 /* child */
9258                 INT_ON;
9259                 flags |= EV_EXIT;
9260                 if (backgnd)
9261                         flags &= ~EV_TESTED;
9262  nofork:
9263                 redirect(n->nredir.redirect, 0);
9264                 evaltreenr(n->nredir.n, flags);
9265                 /* never returns */
9266         }
9267         /* parent */
9268         status = 0;
9269         if (backgnd == FORK_FG)
9270                 status = waitforjob(jp);
9271         INT_ON;
9272         return status;
9273 }
9274
9275 /*
9276  * Compute the names of the files in a redirection list.
9277  */
9278 static void fixredir(union node *, const char *, int);
9279 static void
9280 expredir(union node *n)
9281 {
9282         union node *redir;
9283
9284         for (redir = n; redir; redir = redir->nfile.next) {
9285                 struct arglist fn;
9286
9287                 fn.list = NULL;
9288                 fn.lastp = &fn.list;
9289                 switch (redir->type) {
9290                 case NFROMTO:
9291                 case NFROM:
9292                 case NTO:
9293 #if BASH_REDIR_OUTPUT
9294                 case NTO2:
9295 #endif
9296                 case NCLOBBER:
9297                 case NAPPEND:
9298                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9299                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9300 #if BASH_REDIR_OUTPUT
9301  store_expfname:
9302 #endif
9303 #if 0
9304 // By the design of stack allocator, the loop of this kind:
9305 //      while true; do while true; do break; done </dev/null; done
9306 // will look like a memory leak: ash plans to free expfname's
9307 // of "/dev/null" as soon as it finishes running the loop
9308 // (in this case, never).
9309 // This "fix" is wrong:
9310                         if (redir->nfile.expfname)
9311                                 stunalloc(redir->nfile.expfname);
9312 // It results in corrupted state of stacked allocations.
9313 #endif
9314                         redir->nfile.expfname = fn.list->text;
9315                         break;
9316                 case NFROMFD:
9317                 case NTOFD: /* >& */
9318                         if (redir->ndup.vname) {
9319                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9320                                 if (fn.list == NULL)
9321                                         ash_msg_and_raise_error("redir error");
9322 #if BASH_REDIR_OUTPUT
9323 //FIXME: we used expandarg with different args!
9324                                 if (!isdigit_str9(fn.list->text)) {
9325                                         /* >&file, not >&fd */
9326                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9327                                                 ash_msg_and_raise_error("redir error");
9328                                         redir->type = NTO2;
9329                                         goto store_expfname;
9330                                 }
9331 #endif
9332                                 fixredir(redir, fn.list->text, 1);
9333                         }
9334                         break;
9335                 }
9336         }
9337 }
9338
9339 /*
9340  * Evaluate a pipeline.  All the processes in the pipeline are children
9341  * of the process creating the pipeline.  (This differs from some versions
9342  * of the shell, which make the last process in a pipeline the parent
9343  * of all the rest.)
9344  */
9345 static int
9346 evalpipe(union node *n, int flags)
9347 {
9348         struct job *jp;
9349         struct nodelist *lp;
9350         int pipelen;
9351         int prevfd;
9352         int pip[2];
9353         int status = 0;
9354
9355         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9356         pipelen = 0;
9357         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9358                 pipelen++;
9359         flags |= EV_EXIT;
9360         INT_OFF;
9361         if (n->npipe.pipe_backgnd == 0)
9362                 get_tty_state();
9363         jp = makejob(/*n,*/ pipelen);
9364         prevfd = -1;
9365         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9366                 prehash(lp->n);
9367                 pip[1] = -1;
9368                 if (lp->next) {
9369                         if (pipe(pip) < 0) {
9370                                 close(prevfd);
9371                                 ash_msg_and_raise_perror("can't create pipe");
9372                         }
9373                 }
9374                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9375                         /* child */
9376                         INT_ON;
9377                         if (pip[1] >= 0) {
9378                                 close(pip[0]);
9379                         }
9380                         if (prevfd > 0) {
9381                                 dup2(prevfd, 0);
9382                                 close(prevfd);
9383                         }
9384                         if (pip[1] > 1) {
9385                                 dup2(pip[1], 1);
9386                                 close(pip[1]);
9387                         }
9388                         evaltreenr(lp->n, flags);
9389                         /* never returns */
9390                 }
9391                 /* parent */
9392                 if (prevfd >= 0)
9393                         close(prevfd);
9394                 prevfd = pip[0];
9395                 /* Don't want to trigger debugging */
9396                 if (pip[1] != -1)
9397                         close(pip[1]);
9398         }
9399         if (n->npipe.pipe_backgnd == 0) {
9400                 status = waitforjob(jp);
9401                 TRACE(("evalpipe:  job done exit status %d\n", status));
9402         }
9403         INT_ON;
9404
9405         return status;
9406 }
9407
9408 /*
9409  * Controls whether the shell is interactive or not.
9410  */
9411 static void
9412 setinteractive(int on)
9413 {
9414         static smallint is_interactive;
9415
9416         if (++on == is_interactive)
9417                 return;
9418         is_interactive = on;
9419         setsignal(SIGINT);
9420         setsignal(SIGQUIT);
9421         setsignal(SIGTERM);
9422 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9423         if (is_interactive > 1) {
9424                 /* Looks like they want an interactive shell */
9425                 static smallint did_banner;
9426
9427                 if (!did_banner) {
9428                         /* note: ash and hush share this string */
9429                         out1fmt("\n\n%s %s\n"
9430                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9431                                 "\n",
9432                                 bb_banner,
9433                                 "built-in shell (ash)"
9434                         );
9435                         did_banner = 1;
9436                 }
9437         }
9438 #endif
9439 }
9440
9441 static void
9442 optschanged(void)
9443 {
9444 #if DEBUG
9445         opentrace();
9446 #endif
9447         setinteractive(iflag);
9448         setjobctl(mflag);
9449 #if ENABLE_FEATURE_EDITING_VI
9450         if (viflag)
9451                 line_input_state->flags |= VI_MODE;
9452         else
9453                 line_input_state->flags &= ~VI_MODE;
9454 #else
9455         viflag = 0; /* forcibly keep the option off */
9456 #endif
9457 }
9458
9459 struct localvar_list {
9460         struct localvar_list *next;
9461         struct localvar *lv;
9462 };
9463
9464 static struct localvar_list *localvar_stack;
9465
9466 /*
9467  * Called after a function returns.
9468  * Interrupts must be off.
9469  */
9470 static void
9471 poplocalvars(int keep)
9472 {
9473         struct localvar_list *ll;
9474         struct localvar *lvp, *next;
9475         struct var *vp;
9476
9477         INT_OFF;
9478         ll = localvar_stack;
9479         localvar_stack = ll->next;
9480
9481         next = ll->lv;
9482         free(ll);
9483
9484         while ((lvp = next) != NULL) {
9485                 next = lvp->next;
9486                 vp = lvp->vp;
9487                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9488                 if (keep) {
9489                         int bits = VSTRFIXED;
9490
9491                         if (lvp->flags != VUNSET) {
9492                                 if (vp->var_text == lvp->text)
9493                                         bits |= VTEXTFIXED;
9494                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9495                                         free((char*)lvp->text);
9496                         }
9497
9498                         vp->flags &= ~bits;
9499                         vp->flags |= (lvp->flags & bits);
9500
9501                         if ((vp->flags &
9502                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9503                                 unsetvar(vp->var_text);
9504                 } else if (vp == NULL) {        /* $- saved */
9505                         memcpy(optlist, lvp->text, sizeof(optlist));
9506                         free((char*)lvp->text);
9507                         optschanged();
9508                 } else if (lvp->flags == VUNSET) {
9509                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9510                         unsetvar(vp->var_text);
9511                 } else {
9512                         if (vp->var_func)
9513                                 vp->var_func(var_end(lvp->text));
9514                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9515                                 free((char*)vp->var_text);
9516                         vp->flags = lvp->flags;
9517                         vp->var_text = lvp->text;
9518                 }
9519                 free(lvp);
9520         }
9521         INT_ON;
9522 }
9523
9524 /*
9525  * Create a new localvar environment.
9526  */
9527 static struct localvar_list *
9528 pushlocalvars(void)
9529 {
9530         struct localvar_list *ll;
9531
9532         INT_OFF;
9533         ll = ckzalloc(sizeof(*ll));
9534         /*ll->lv = NULL; - zalloc did it */
9535         ll->next = localvar_stack;
9536         localvar_stack = ll;
9537         INT_ON;
9538
9539         return ll->next;
9540 }
9541
9542 static void
9543 unwindlocalvars(struct localvar_list *stop)
9544 {
9545         while (localvar_stack != stop)
9546                 poplocalvars(0);
9547 }
9548
9549 static int
9550 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9551 {
9552         volatile struct shparam saveparam;
9553         struct jmploc *volatile savehandler;
9554         struct jmploc jmploc;
9555         int e;
9556         int savefuncline;
9557
9558         saveparam = shellparam;
9559         savefuncline = funcline;
9560         savehandler = exception_handler;
9561         e = setjmp(jmploc.loc);
9562         if (e) {
9563                 goto funcdone;
9564         }
9565         INT_OFF;
9566         exception_handler = &jmploc;
9567         shellparam.malloced = 0;
9568         func->count++;
9569         funcline = func->n.ndefun.linno;
9570         INT_ON;
9571         shellparam.nparam = argc - 1;
9572         shellparam.p = argv + 1;
9573 #if ENABLE_ASH_GETOPTS
9574         shellparam.optind = 1;
9575         shellparam.optoff = -1;
9576 #endif
9577         pushlocalvars();
9578         evaltree(func->n.ndefun.body, flags & EV_TESTED);
9579         poplocalvars(0);
9580  funcdone:
9581         INT_OFF;
9582         funcline = savefuncline;
9583         freefunc(func);
9584         freeparam(&shellparam);
9585         shellparam = saveparam;
9586         exception_handler = savehandler;
9587         INT_ON;
9588         evalskip &= ~SKIPFUNC;
9589         return e;
9590 }
9591
9592 /*
9593  * Make a variable a local variable.  When a variable is made local, it's
9594  * value and flags are saved in a localvar structure.  The saved values
9595  * will be restored when the shell function returns.  We handle the name
9596  * "-" as a special case: it makes changes to "set +-options" local
9597  * (options will be restored on return from the function).
9598  */
9599 static void
9600 mklocal(char *name)
9601 {
9602         struct localvar *lvp;
9603         struct var **vpp;
9604         struct var *vp;
9605         char *eq = strchr(name, '=');
9606
9607         INT_OFF;
9608         /* Cater for duplicate "local". Examples:
9609          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9610          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9611          */
9612         lvp = localvar_stack->lv;
9613         while (lvp) {
9614                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9615                         if (eq)
9616                                 setvareq(name, 0);
9617                         /* else:
9618                          * it's a duplicate "local VAR" declaration, do nothing
9619                          */
9620                         goto ret;
9621                 }
9622                 lvp = lvp->next;
9623         }
9624
9625         lvp = ckzalloc(sizeof(*lvp));
9626         if (LONE_DASH(name)) {
9627                 char *p;
9628                 p = ckmalloc(sizeof(optlist));
9629                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9630                 vp = NULL;
9631         } else {
9632                 vpp = hashvar(name);
9633                 vp = *findvar(vpp, name);
9634                 if (vp == NULL) {
9635                         /* variable did not exist yet */
9636                         if (eq)
9637                                 vp = setvareq(name, VSTRFIXED);
9638                         else
9639                                 vp = setvar(name, NULL, VSTRFIXED);
9640                         lvp->flags = VUNSET;
9641                 } else {
9642                         lvp->text = vp->var_text;
9643                         lvp->flags = vp->flags;
9644                         /* make sure neither "struct var" nor string gets freed
9645                          * during (un)setting:
9646                          */
9647                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9648                         if (eq)
9649                                 setvareq(name, 0);
9650                         else
9651                                 /* "local VAR" unsets VAR: */
9652                                 setvar0(name, NULL);
9653                 }
9654         }
9655         lvp->vp = vp;
9656         lvp->next = localvar_stack->lv;
9657         localvar_stack->lv = lvp;
9658  ret:
9659         INT_ON;
9660 }
9661
9662 /*
9663  * The "local" command.
9664  */
9665 static int FAST_FUNC
9666 localcmd(int argc UNUSED_PARAM, char **argv)
9667 {
9668         char *name;
9669
9670         if (!localvar_stack)
9671                 ash_msg_and_raise_error("not in a function");
9672
9673         argv = argptr;
9674         while ((name = *argv++) != NULL) {
9675                 mklocal(name);
9676         }
9677         return 0;
9678 }
9679
9680 static int FAST_FUNC
9681 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9682 {
9683         return 1;
9684 }
9685
9686 static int FAST_FUNC
9687 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9688 {
9689         return 0;
9690 }
9691
9692 static int FAST_FUNC
9693 execcmd(int argc UNUSED_PARAM, char **argv)
9694 {
9695         optionarg = NULL;
9696         while (nextopt("a:") != '\0')
9697                 /* nextopt() sets optionarg to "-a ARGV0" */;
9698
9699         argv = argptr;
9700         if (argv[0]) {
9701                 char *prog;
9702
9703                 iflag = 0;              /* exit on error */
9704                 mflag = 0;
9705                 optschanged();
9706                 /* We should set up signals for "exec CMD"
9707                  * the same way as for "CMD" without "exec".
9708                  * But optschanged->setinteractive->setsignal
9709                  * still thought we are a root shell. Therefore, for example,
9710                  * SIGQUIT is still set to IGN. Fix it:
9711                  */
9712                 shlvl++;
9713                 setsignal(SIGQUIT);
9714                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9715                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9716                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9717
9718                 prog = argv[0];
9719                 if (optionarg)
9720                         argv[0] = optionarg;
9721                 shellexec(prog, argv, pathval(), 0);
9722                 /* NOTREACHED */
9723         }
9724         return 0;
9725 }
9726
9727 /*
9728  * The return command.
9729  */
9730 static int FAST_FUNC
9731 returncmd(int argc UNUSED_PARAM, char **argv)
9732 {
9733         /*
9734          * If called outside a function, do what ksh does;
9735          * skip the rest of the file.
9736          */
9737         evalskip = SKIPFUNC;
9738         return argv[1] ? number(argv[1]) : exitstatus;
9739 }
9740
9741 /* Forward declarations for builtintab[] */
9742 static int breakcmd(int, char **) FAST_FUNC;
9743 static int dotcmd(int, char **) FAST_FUNC;
9744 static int evalcmd(int, char **, int) FAST_FUNC;
9745 static int exitcmd(int, char **) FAST_FUNC;
9746 static int exportcmd(int, char **) FAST_FUNC;
9747 #if ENABLE_ASH_GETOPTS
9748 static int getoptscmd(int, char **) FAST_FUNC;
9749 #endif
9750 #if ENABLE_ASH_HELP
9751 static int helpcmd(int, char **) FAST_FUNC;
9752 #endif
9753 #if MAX_HISTORY
9754 static int historycmd(int, char **) FAST_FUNC;
9755 #endif
9756 #if ENABLE_FEATURE_SH_MATH
9757 static int letcmd(int, char **) FAST_FUNC;
9758 #endif
9759 static int readcmd(int, char **) FAST_FUNC;
9760 static int setcmd(int, char **) FAST_FUNC;
9761 static int shiftcmd(int, char **) FAST_FUNC;
9762 static int timescmd(int, char **) FAST_FUNC;
9763 static int trapcmd(int, char **) FAST_FUNC;
9764 static int umaskcmd(int, char **) FAST_FUNC;
9765 static int unsetcmd(int, char **) FAST_FUNC;
9766 static int ulimitcmd(int, char **) FAST_FUNC;
9767
9768 #define BUILTIN_NOSPEC          "0"
9769 #define BUILTIN_SPECIAL         "1"
9770 #define BUILTIN_REGULAR         "2"
9771 #define BUILTIN_SPEC_REG        "3"
9772 #define BUILTIN_ASSIGN          "4"
9773 #define BUILTIN_SPEC_ASSG       "5"
9774 #define BUILTIN_REG_ASSG        "6"
9775 #define BUILTIN_SPEC_REG_ASSG   "7"
9776
9777 /* Stubs for calling non-FAST_FUNC's */
9778 #if ENABLE_ASH_ECHO
9779 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9780 #endif
9781 #if ENABLE_ASH_PRINTF
9782 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9783 #endif
9784 #if ENABLE_ASH_TEST || BASH_TEST2
9785 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9786 #endif
9787
9788 /* Keep these in proper order since it is searched via bsearch() */
9789 static const struct builtincmd builtintab[] = {
9790         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9791         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9792 #if ENABLE_ASH_TEST
9793         { BUILTIN_REGULAR       "["       , testcmd    },
9794 #endif
9795 #if BASH_TEST2
9796         { BUILTIN_REGULAR       "[["      , testcmd    },
9797 #endif
9798 #if ENABLE_ASH_ALIAS
9799         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9800 #endif
9801 #if JOBS
9802         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9803 #endif
9804         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9805         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9806         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9807 #if ENABLE_ASH_CMDCMD
9808         { BUILTIN_REGULAR       "command" , commandcmd },
9809 #endif
9810         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9811 #if ENABLE_ASH_ECHO
9812         { BUILTIN_REGULAR       "echo"    , echocmd    },
9813 #endif
9814         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9815         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9816         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9817         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9818         { BUILTIN_REGULAR       "false"   , falsecmd   },
9819 #if JOBS
9820         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9821 #endif
9822 #if ENABLE_ASH_GETOPTS
9823         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9824 #endif
9825         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9826 #if ENABLE_ASH_HELP
9827         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9828 #endif
9829 #if MAX_HISTORY
9830         { BUILTIN_NOSPEC        "history" , historycmd },
9831 #endif
9832 #if JOBS
9833         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9834         { BUILTIN_REGULAR       "kill"    , killcmd    },
9835 #endif
9836 #if ENABLE_FEATURE_SH_MATH
9837         { BUILTIN_NOSPEC        "let"     , letcmd     },
9838 #endif
9839         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9840 #if ENABLE_ASH_PRINTF
9841         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9842 #endif
9843         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9844         { BUILTIN_REGULAR       "read"    , readcmd    },
9845         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9846         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9847         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9848         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9849 #if BASH_SOURCE
9850         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9851 #endif
9852 #if ENABLE_ASH_TEST
9853         { BUILTIN_REGULAR       "test"    , testcmd    },
9854 #endif
9855         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9856         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9857         { BUILTIN_REGULAR       "true"    , truecmd    },
9858         { BUILTIN_NOSPEC        "type"    , typecmd    },
9859         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9860         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9861 #if ENABLE_ASH_ALIAS
9862         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9863 #endif
9864         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9865         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9866 };
9867
9868 /* Should match the above table! */
9869 #define COMMANDCMD (builtintab + \
9870         /* . : */       2 + \
9871         /* [ */         1 * ENABLE_ASH_TEST + \
9872         /* [[ */        1 * BASH_TEST2 + \
9873         /* alias */     1 * ENABLE_ASH_ALIAS + \
9874         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9875         /* break cd cddir  */   3)
9876 #define EVALCMD (COMMANDCMD + \
9877         /* command */   1 * ENABLE_ASH_CMDCMD + \
9878         /* continue */  1 + \
9879         /* echo */      1 * ENABLE_ASH_ECHO + \
9880         0)
9881 #define EXECCMD (EVALCMD + \
9882         /* eval */      1)
9883
9884 /*
9885  * Search the table of builtin commands.
9886  */
9887 static int
9888 pstrcmp1(const void *a, const void *b)
9889 {
9890         return strcmp((char*)a, *(char**)b + 1);
9891 }
9892 static struct builtincmd *
9893 find_builtin(const char *name)
9894 {
9895         struct builtincmd *bp;
9896
9897         bp = bsearch(
9898                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9899                 pstrcmp1
9900         );
9901         return bp;
9902 }
9903
9904 /*
9905  * Execute a simple command.
9906  */
9907 static int
9908 isassignment(const char *p)
9909 {
9910         const char *q = endofname(p);
9911         if (p == q)
9912                 return 0;
9913         return *q == '=';
9914 }
9915 static int FAST_FUNC
9916 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9917 {
9918         /* Preserve exitstatus of a previous possible redirection
9919          * as POSIX mandates */
9920         return back_exitstatus;
9921 }
9922 static int
9923 evalcommand(union node *cmd, int flags)
9924 {
9925         static const struct builtincmd null_bltin = {
9926                 "\0\0", bltincmd /* why three NULs? */
9927         };
9928         struct localvar_list *localvar_stop;
9929         struct redirtab *redir_stop;
9930         struct stackmark smark;
9931         union node *argp;
9932         struct arglist arglist;
9933         struct arglist varlist;
9934         char **argv;
9935         int argc;
9936         const struct strlist *sp;
9937         struct cmdentry cmdentry;
9938         struct job *jp;
9939         char *lastarg;
9940         const char *path;
9941         int spclbltin;
9942         int status;
9943         char **nargv;
9944         smallint cmd_is_exec;
9945
9946         errlinno = lineno = cmd->ncmd.linno;
9947         if (funcline)
9948                 lineno -= funcline - 1;
9949
9950         /* First expand the arguments. */
9951         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9952         setstackmark(&smark);
9953         localvar_stop = pushlocalvars();
9954         back_exitstatus = 0;
9955
9956         cmdentry.cmdtype = CMDBUILTIN;
9957         cmdentry.u.cmd = &null_bltin;
9958         varlist.lastp = &varlist.list;
9959         *varlist.lastp = NULL;
9960         arglist.lastp = &arglist.list;
9961         *arglist.lastp = NULL;
9962
9963         argc = 0;
9964         if (cmd->ncmd.args) {
9965                 struct builtincmd *bcmd;
9966                 smallint pseudovarflag;
9967
9968                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9969                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9970
9971                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9972                         struct strlist **spp;
9973
9974                         spp = arglist.lastp;
9975                         if (pseudovarflag && isassignment(argp->narg.text))
9976                                 expandarg(argp, &arglist, EXP_VARTILDE);
9977                         else
9978                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9979
9980                         for (sp = *spp; sp; sp = sp->next)
9981                                 argc++;
9982                 }
9983         }
9984
9985         /* Reserve one extra spot at the front for shellexec. */
9986         nargv = stalloc(sizeof(char *) * (argc + 2));
9987         argv = ++nargv;
9988         for (sp = arglist.list; sp; sp = sp->next) {
9989                 TRACE(("evalcommand arg: %s\n", sp->text));
9990                 *nargv++ = sp->text;
9991         }
9992         *nargv = NULL;
9993
9994         lastarg = NULL;
9995         if (iflag && funcline == 0 && argc > 0)
9996                 lastarg = nargv[-1];
9997
9998         expredir(cmd->ncmd.redirect);
9999         redir_stop = pushredir(cmd->ncmd.redirect);
10000         preverrout_fd = 2;
10001         if (BASH_XTRACEFD && xflag) {
10002                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
10003                  * we do not emulate this. We only use its value.
10004                  */
10005                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
10006                 if (xtracefd && is_number(xtracefd))
10007                         preverrout_fd = atoi(xtracefd);
10008
10009         }
10010         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
10011
10012         path = vpath.var_text;
10013         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
10014                 struct strlist **spp;
10015                 char *p;
10016
10017                 spp = varlist.lastp;
10018                 expandarg(argp, &varlist, EXP_VARTILDE);
10019
10020                 mklocal((*spp)->text);
10021
10022                 /*
10023                  * Modify the command lookup path, if a PATH= assignment
10024                  * is present
10025                  */
10026                 p = (*spp)->text;
10027                 if (varcmp(p, path) == 0)
10028                         path = p;
10029         }
10030
10031         /* Print the command if xflag is set. */
10032         if (xflag) {
10033                 const char *pfx = "";
10034
10035                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
10036
10037                 sp = varlist.list;
10038                 while (sp) {
10039                         char *varval = sp->text;
10040                         char *eq = strchrnul(varval, '=');
10041                         if (*eq)
10042                                 eq++;
10043                         fdprintf(preverrout_fd, "%s%.*s%s",
10044                                 pfx,
10045                                 (int)(eq - varval), varval,
10046                                 maybe_single_quote(eq)
10047                         );
10048                         sp = sp->next;
10049                         pfx = " ";
10050                 }
10051
10052                 sp = arglist.list;
10053                 while (sp) {
10054                         fdprintf(preverrout_fd, "%s%s",
10055                                 pfx,
10056                                 /* always quote if matches reserved word: */
10057                                 findkwd(sp->text)
10058                                 ? single_quote(sp->text)
10059                                 : maybe_single_quote(sp->text)
10060                         );
10061                         sp = sp->next;
10062                         pfx = " ";
10063                 }
10064                 safe_write(preverrout_fd, "\n", 1);
10065         }
10066
10067         cmd_is_exec = 0;
10068         spclbltin = -1;
10069
10070         /* Now locate the command. */
10071         if (argc) {
10072                 int cmd_flag = DO_ERR;
10073 #if ENABLE_ASH_CMDCMD
10074                 const char *oldpath = path + 5;
10075 #endif
10076                 path += 5;
10077                 for (;;) {
10078                         find_command(argv[0], &cmdentry, cmd_flag, path);
10079                         if (cmdentry.cmdtype == CMDUNKNOWN) {
10080                                 flush_stdout_stderr();
10081                                 status = 127;
10082                                 goto bail;
10083                         }
10084
10085                         /* implement bltin and command here */
10086                         if (cmdentry.cmdtype != CMDBUILTIN)
10087                                 break;
10088                         if (spclbltin < 0)
10089                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
10090                         if (cmdentry.u.cmd == EXECCMD)
10091                                 cmd_is_exec = 1;
10092 #if ENABLE_ASH_CMDCMD
10093                         if (cmdentry.u.cmd == COMMANDCMD) {
10094                                 path = oldpath;
10095                                 nargv = parse_command_args(argv, &path);
10096                                 if (!nargv)
10097                                         break;
10098                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
10099                                  * nargv => "PROG". path is updated if -p.
10100                                  */
10101                                 argc -= nargv - argv;
10102                                 argv = nargv;
10103                                 cmd_flag |= DO_NOFUNC;
10104                         } else
10105 #endif
10106                                 break;
10107                 }
10108         }
10109
10110         if (status) {
10111  bail:
10112                 exitstatus = status;
10113
10114                 /* We have a redirection error. */
10115                 if (spclbltin > 0)
10116                         raise_exception(EXERROR);
10117
10118                 goto out;
10119         }
10120
10121         /* Execute the command. */
10122         switch (cmdentry.cmdtype) {
10123         default: {
10124
10125 #if ENABLE_FEATURE_SH_STANDALONE \
10126  && ENABLE_FEATURE_SH_NOFORK \
10127  && NUM_APPLETS > 1
10128 /* (1) BUG: if variables are set, we need to fork, or save/restore them
10129  *     around run_nofork_applet() call.
10130  * (2) Should this check also be done in forkshell()?
10131  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
10132  */
10133                 /* find_command() encodes applet_no as (-2 - applet_no) */
10134                 int applet_no = (- cmdentry.u.index - 2);
10135                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
10136                         char **sv_environ;
10137
10138                         INT_OFF;
10139                         sv_environ = environ;
10140                         environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
10141                         /*
10142                          * Run <applet>_main().
10143                          * Signals (^C) can't interrupt here.
10144                          * Otherwise we can mangle stdio or malloc internal state.
10145                          * This makes applets which can run for a long time
10146                          * and/or wait for user input ineligible for NOFORK:
10147                          * for example, "yes" or "rm" (rm -i waits for input).
10148                          */
10149                         status = run_nofork_applet(applet_no, argv);
10150                         environ = sv_environ;
10151                         /*
10152                          * Try enabling NOFORK for "yes" applet.
10153                          * ^C _will_ stop it (write returns EINTR),
10154                          * but this causes stdout FILE to be stuck
10155                          * and needing clearerr(). What if other applets
10156                          * also can get EINTRs? Do we need to switch
10157                          * our signals to SA_RESTART?
10158                          */
10159                         /*clearerr(stdout);*/
10160                         INT_ON;
10161                         break;
10162                 }
10163 #endif
10164                 /* Can we avoid forking? For example, very last command
10165                  * in a script or a subshell does not need forking,
10166                  * we can just exec it.
10167                  */
10168                 if (!(flags & EV_EXIT) || may_have_traps) {
10169                         /* No, forking off a child is necessary */
10170                         INT_OFF;
10171                         get_tty_state();
10172                         jp = makejob(/*cmd,*/ 1);
10173                         if (forkshell(jp, cmd, FORK_FG) != 0) {
10174                                 /* parent */
10175                                 status = waitforjob(jp);
10176                                 INT_ON;
10177                                 TRACE(("forked child exited with %d\n", status));
10178                                 break;
10179                         }
10180                         /* child */
10181                         FORCE_INT_ON;
10182                         /* fall through to exec'ing external program */
10183                 }
10184                 listsetvar(varlist.list, VEXPORT|VSTACK);
10185                 shellexec(argv[0], argv, path, cmdentry.u.index);
10186                 /* NOTREACHED */
10187         } /* default */
10188         case CMDBUILTIN:
10189                 if (spclbltin > 0 || argc == 0) {
10190                         poplocalvars(1);
10191                         if (cmd_is_exec && argc > 1)
10192                                 listsetvar(varlist.list, VEXPORT);
10193                 }
10194
10195                 /* Tight loop with builtins only:
10196                  * "while kill -0 $child; do true; done"
10197                  * will never exit even if $child died, unless we do this
10198                  * to reap the zombie and make kill detect that it's gone: */
10199                 dowait(DOWAIT_NONBLOCK, NULL);
10200
10201                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10202                         if (exception_type == EXERROR && spclbltin <= 0) {
10203                                 FORCE_INT_ON;
10204                                 goto readstatus;
10205                         }
10206  raise:
10207                         longjmp(exception_handler->loc, 1);
10208                 }
10209                 goto readstatus;
10210
10211         case CMDFUNCTION:
10212                 poplocalvars(1);
10213                 /* See above for the rationale */
10214                 dowait(DOWAIT_NONBLOCK, NULL);
10215                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10216                         goto raise;
10217  readstatus:
10218                 status = exitstatus;
10219                 break;
10220         } /* switch */
10221
10222  out:
10223         if (cmd->ncmd.redirect)
10224                 popredir(/*drop:*/ cmd_is_exec);
10225         unwindredir(redir_stop);
10226         unwindlocalvars(localvar_stop);
10227         if (lastarg) {
10228                 /* dsl: I think this is intended to be used to support
10229                  * '_' in 'vi' command mode during line editing...
10230                  * However I implemented that within libedit itself.
10231                  */
10232                 setvar0("_", lastarg);
10233         }
10234         popstackmark(&smark);
10235
10236         return status;
10237 }
10238
10239 static int
10240 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10241 {
10242         char *volatile savecmdname;
10243         struct jmploc *volatile savehandler;
10244         struct jmploc jmploc;
10245         int status;
10246         int i;
10247
10248         savecmdname = commandname;
10249         savehandler = exception_handler;
10250         i = setjmp(jmploc.loc);
10251         if (i)
10252                 goto cmddone;
10253         exception_handler = &jmploc;
10254         commandname = argv[0];
10255         argptr = argv + 1;
10256         optptr = NULL;                  /* initialize nextopt */
10257         if (cmd == EVALCMD)
10258                 status = evalcmd(argc, argv, flags);
10259         else
10260                 status = (*cmd->builtin)(argc, argv);
10261         flush_stdout_stderr();
10262         status |= ferror(stdout);
10263         exitstatus = status;
10264  cmddone:
10265         clearerr(stdout);
10266         commandname = savecmdname;
10267         exception_handler = savehandler;
10268
10269         return i;
10270 }
10271
10272 static int
10273 goodname(const char *p)
10274 {
10275         return endofname(p)[0] == '\0';
10276 }
10277
10278
10279 /*
10280  * Search for a command.  This is called before we fork so that the
10281  * location of the command will be available in the parent as well as
10282  * the child.  The check for "goodname" is an overly conservative
10283  * check that the name will not be subject to expansion.
10284  */
10285 static void
10286 prehash(union node *n)
10287 {
10288         struct cmdentry entry;
10289
10290         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10291                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10292 }
10293
10294
10295 /* ============ Builtin commands
10296  *
10297  * Builtin commands whose functions are closely tied to evaluation
10298  * are implemented here.
10299  */
10300
10301 /*
10302  * Handle break and continue commands.  Break, continue, and return are
10303  * all handled by setting the evalskip flag.  The evaluation routines
10304  * above all check this flag, and if it is set they start skipping
10305  * commands rather than executing them.  The variable skipcount is
10306  * the number of loops to break/continue, or the number of function
10307  * levels to return.  (The latter is always 1.)  It should probably
10308  * be an error to break out of more loops than exist, but it isn't
10309  * in the standard shell so we don't make it one here.
10310  */
10311 static int FAST_FUNC
10312 breakcmd(int argc UNUSED_PARAM, char **argv)
10313 {
10314         int n = argv[1] ? number(argv[1]) : 1;
10315
10316         if (n <= 0)
10317                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10318         if (n > loopnest)
10319                 n = loopnest;
10320         if (n > 0) {
10321                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10322                 skipcount = n;
10323         }
10324         return 0;
10325 }
10326
10327
10328 /*
10329  * This implements the input routines used by the parser.
10330  */
10331
10332 enum {
10333         INPUT_PUSH_FILE = 1,
10334         INPUT_NOFILE_OK = 2,
10335 };
10336
10337 static smallint checkkwd;
10338 /* values of checkkwd variable */
10339 #define CHKALIAS        0x1
10340 #define CHKKWD          0x2
10341 #define CHKNL           0x4
10342 #define CHKEOFMARK      0x8
10343
10344 /*
10345  * Push a string back onto the input at this current parsefile level.
10346  * We handle aliases this way.
10347  */
10348 #if !ENABLE_ASH_ALIAS
10349 #define pushstring(s, ap) pushstring(s)
10350 #endif
10351 static void
10352 pushstring(char *s, struct alias *ap)
10353 {
10354         struct strpush *sp;
10355         int len;
10356
10357         len = strlen(s);
10358         INT_OFF;
10359         if (g_parsefile->strpush) {
10360                 sp = ckzalloc(sizeof(*sp));
10361                 sp->prev = g_parsefile->strpush;
10362         } else {
10363                 sp = &(g_parsefile->basestrpush);
10364         }
10365         g_parsefile->strpush = sp;
10366         sp->prev_string = g_parsefile->next_to_pgetc;
10367         sp->prev_left_in_line = g_parsefile->left_in_line;
10368         sp->unget = g_parsefile->unget;
10369         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10370 #if ENABLE_ASH_ALIAS
10371         sp->ap = ap;
10372         if (ap) {
10373                 ap->flag |= ALIASINUSE;
10374                 sp->string = s;
10375         }
10376 #endif
10377         g_parsefile->next_to_pgetc = s;
10378         g_parsefile->left_in_line = len;
10379         g_parsefile->unget = 0;
10380         INT_ON;
10381 }
10382
10383 static void
10384 popstring(void)
10385 {
10386         struct strpush *sp = g_parsefile->strpush;
10387
10388         INT_OFF;
10389 #if ENABLE_ASH_ALIAS
10390         if (sp->ap) {
10391                 if (g_parsefile->next_to_pgetc[-1] == ' '
10392                  || g_parsefile->next_to_pgetc[-1] == '\t'
10393                 ) {
10394                         checkkwd |= CHKALIAS;
10395                 }
10396                 if (sp->string != sp->ap->val) {
10397                         free(sp->string);
10398                 }
10399                 sp->ap->flag &= ~ALIASINUSE;
10400                 if (sp->ap->flag & ALIASDEAD) {
10401                         unalias(sp->ap->name);
10402                 }
10403         }
10404 #endif
10405         g_parsefile->next_to_pgetc = sp->prev_string;
10406         g_parsefile->left_in_line = sp->prev_left_in_line;
10407         g_parsefile->unget = sp->unget;
10408         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10409         g_parsefile->strpush = sp->prev;
10410         if (sp != &(g_parsefile->basestrpush))
10411                 free(sp);
10412         INT_ON;
10413 }
10414
10415 static int
10416 preadfd(void)
10417 {
10418         int nr;
10419         char *buf = g_parsefile->buf;
10420
10421         g_parsefile->next_to_pgetc = buf;
10422 #if ENABLE_FEATURE_EDITING
10423  retry:
10424         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10425                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10426         else {
10427 # if ENABLE_ASH_IDLE_TIMEOUT
10428                 int timeout = -1;
10429                 if (iflag) {
10430                         const char *tmout_var = lookupvar("TMOUT");
10431                         if (tmout_var) {
10432                                 timeout = atoi(tmout_var) * 1000;
10433                                 if (timeout <= 0)
10434                                         timeout = -1;
10435                         }
10436                 }
10437                 line_input_state->timeout = timeout;
10438 # endif
10439 # if ENABLE_FEATURE_TAB_COMPLETION
10440                 line_input_state->path_lookup = pathval();
10441 # endif
10442                 reinit_unicode_for_ash();
10443                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10444                 if (nr == 0) {
10445                         /* ^C pressed, "convert" to SIGINT */
10446                         write(STDOUT_FILENO, "^C", 2);
10447                         if (trap[SIGINT]) {
10448                                 buf[0] = '\n';
10449                                 buf[1] = '\0';
10450                                 raise(SIGINT);
10451                                 return 1;
10452                         }
10453                         exitstatus = 128 + SIGINT;
10454                         bb_putchar('\n');
10455                         goto retry;
10456                 }
10457                 if (nr < 0) {
10458                         if (errno == 0) {
10459                                 /* Ctrl+D pressed */
10460                                 nr = 0;
10461                         }
10462 # if ENABLE_ASH_IDLE_TIMEOUT
10463                         else if (errno == EAGAIN && timeout > 0) {
10464                                 puts("\007timed out waiting for input: auto-logout");
10465                                 exitshell();
10466                         }
10467 # endif
10468                 }
10469         }
10470 #else
10471         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10472 #endif
10473
10474 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10475         if (nr < 0) {
10476                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10477                         int flags = fcntl(0, F_GETFL);
10478                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10479                                 flags &= ~O_NONBLOCK;
10480                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10481                                         out2str("sh: turning off NDELAY mode\n");
10482                                         goto retry;
10483                                 }
10484                         }
10485                 }
10486         }
10487 #endif
10488         return nr;
10489 }
10490
10491 /*
10492  * Refill the input buffer and return the next input character:
10493  *
10494  * 1) If a string was pushed back on the input, pop it;
10495  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10496  *    or we are reading from a string so we can't refill the buffer,
10497  *    return EOF.
10498  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10499  * 4) Process input up to the next newline, deleting nul characters.
10500  */
10501 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10502 #define pgetc_debug(...) ((void)0)
10503 static int pgetc(void);
10504 static int
10505 preadbuffer(void)
10506 {
10507         char *q;
10508         int more;
10509
10510         if (g_parsefile->strpush) {
10511 #if ENABLE_ASH_ALIAS
10512                 if (g_parsefile->left_in_line == -1
10513                  && g_parsefile->strpush->ap
10514                  && g_parsefile->next_to_pgetc[-1] != ' '
10515                  && g_parsefile->next_to_pgetc[-1] != '\t'
10516                 ) {
10517                         pgetc_debug("preadbuffer PEOA");
10518                         return PEOA;
10519                 }
10520 #endif
10521                 popstring();
10522                 return pgetc();
10523         }
10524         /* on both branches above g_parsefile->left_in_line < 0.
10525          * "pgetc" needs refilling.
10526          */
10527
10528         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10529          * pungetc() may increment it a few times.
10530          * Assuming it won't increment it to less than -90.
10531          */
10532         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10533                 pgetc_debug("preadbuffer PEOF1");
10534                 /* even in failure keep left_in_line and next_to_pgetc
10535                  * in lock step, for correct multi-layer pungetc.
10536                  * left_in_line was decremented before preadbuffer(),
10537                  * must inc next_to_pgetc: */
10538                 g_parsefile->next_to_pgetc++;
10539                 return PEOF;
10540         }
10541
10542         more = g_parsefile->left_in_buffer;
10543         if (more <= 0) {
10544                 flush_stdout_stderr();
10545  again:
10546                 more = preadfd();
10547                 if (more <= 0) {
10548                         /* don't try reading again */
10549                         g_parsefile->left_in_line = -99;
10550                         pgetc_debug("preadbuffer PEOF2");
10551                         g_parsefile->next_to_pgetc++;
10552                         return PEOF;
10553                 }
10554         }
10555
10556         /* Find out where's the end of line.
10557          * Set g_parsefile->left_in_line
10558          * and g_parsefile->left_in_buffer acordingly.
10559          * NUL chars are deleted.
10560          */
10561         q = g_parsefile->next_to_pgetc;
10562         for (;;) {
10563                 char c;
10564
10565                 more--;
10566
10567                 c = *q;
10568                 if (c == '\0') {
10569                         memmove(q, q + 1, more);
10570                 } else {
10571                         q++;
10572                         if (c == '\n') {
10573                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10574                                 break;
10575                         }
10576                 }
10577
10578                 if (more <= 0) {
10579                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10580                         if (g_parsefile->left_in_line < 0)
10581                                 goto again;
10582                         break;
10583                 }
10584         }
10585         g_parsefile->left_in_buffer = more;
10586
10587         if (vflag) {
10588                 char save = *q;
10589                 *q = '\0';
10590                 out2str(g_parsefile->next_to_pgetc);
10591                 *q = save;
10592         }
10593
10594         pgetc_debug("preadbuffer at %d:%p'%s'",
10595                         g_parsefile->left_in_line,
10596                         g_parsefile->next_to_pgetc,
10597                         g_parsefile->next_to_pgetc);
10598         return (unsigned char)*g_parsefile->next_to_pgetc++;
10599 }
10600
10601 static void
10602 nlprompt(void)
10603 {
10604         g_parsefile->linno++;
10605         setprompt_if(doprompt, 2);
10606 }
10607 static void
10608 nlnoprompt(void)
10609 {
10610         g_parsefile->linno++;
10611         needprompt = doprompt;
10612 }
10613
10614 static int
10615 pgetc(void)
10616 {
10617         int c;
10618
10619         pgetc_debug("pgetc at %d:%p'%s'",
10620                         g_parsefile->left_in_line,
10621                         g_parsefile->next_to_pgetc,
10622                         g_parsefile->next_to_pgetc);
10623         if (g_parsefile->unget)
10624                 return g_parsefile->lastc[--g_parsefile->unget];
10625
10626         if (--g_parsefile->left_in_line >= 0)
10627                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10628         else
10629                 c = preadbuffer();
10630
10631         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10632         g_parsefile->lastc[0] = c;
10633
10634         return c;
10635 }
10636
10637 #if ENABLE_ASH_ALIAS
10638 static int
10639 pgetc_without_PEOA(void)
10640 {
10641         int c;
10642         do {
10643                 pgetc_debug("pgetc at %d:%p'%s'",
10644                                 g_parsefile->left_in_line,
10645                                 g_parsefile->next_to_pgetc,
10646                                 g_parsefile->next_to_pgetc);
10647                 c = pgetc();
10648         } while (c == PEOA);
10649         return c;
10650 }
10651 #else
10652 # define pgetc_without_PEOA() pgetc()
10653 #endif
10654
10655 /*
10656  * Undo a call to pgetc.  Only two characters may be pushed back.
10657  * PEOF may be pushed back.
10658  */
10659 static void
10660 pungetc(void)
10661 {
10662         g_parsefile->unget++;
10663 }
10664
10665 /* This one eats backslash+newline */
10666 static int
10667 pgetc_eatbnl(void)
10668 {
10669         int c;
10670
10671         while ((c = pgetc()) == '\\') {
10672                 if (pgetc() != '\n') {
10673                         pungetc();
10674                         break;
10675                 }
10676
10677                 nlprompt();
10678         }
10679
10680         return c;
10681 }
10682
10683 struct synstack {
10684         smalluint syntax;
10685         uint8_t innerdq   :1;
10686         uint8_t varpushed :1;
10687         uint8_t dblquote  :1;
10688         int varnest;            /* levels of variables expansion */
10689         int dqvarnest;          /* levels of variables expansion within double quotes */
10690         int parenlevel;         /* levels of parens in arithmetic */
10691         struct synstack *prev;
10692         struct synstack *next;
10693 };
10694
10695 static void
10696 synstack_push(struct synstack **stack, struct synstack *next, int syntax)
10697 {
10698         memset(next, 0, sizeof(*next));
10699         next->syntax = syntax;
10700         next->next = *stack;
10701         (*stack)->prev = next;
10702         *stack = next;
10703 }
10704
10705 static ALWAYS_INLINE void
10706 synstack_pop(struct synstack **stack)
10707 {
10708         *stack = (*stack)->next;
10709 }
10710
10711 /*
10712  * To handle the "." command, a stack of input files is used.  Pushfile
10713  * adds a new entry to the stack and popfile restores the previous level.
10714  */
10715 static void
10716 pushfile(void)
10717 {
10718         struct parsefile *pf;
10719
10720         pf = ckzalloc(sizeof(*pf));
10721         pf->prev = g_parsefile;
10722         pf->pf_fd = -1;
10723         /*pf->strpush = NULL; - ckzalloc did it */
10724         /*pf->basestrpush.prev = NULL;*/
10725         /*pf->unget = 0;*/
10726         g_parsefile = pf;
10727 }
10728
10729 static void
10730 popfile(void)
10731 {
10732         struct parsefile *pf = g_parsefile;
10733
10734         if (pf == &basepf)
10735                 return;
10736
10737         INT_OFF;
10738         if (pf->pf_fd >= 0)
10739                 close(pf->pf_fd);
10740         free(pf->buf);
10741         while (pf->strpush)
10742                 popstring();
10743         g_parsefile = pf->prev;
10744         free(pf);
10745         INT_ON;
10746 }
10747
10748 /*
10749  * Return to top level.
10750  */
10751 static void
10752 popallfiles(void)
10753 {
10754         while (g_parsefile != &basepf)
10755                 popfile();
10756 }
10757
10758 /*
10759  * Close the file(s) that the shell is reading commands from.  Called
10760  * after a fork is done.
10761  */
10762 static void
10763 closescript(void)
10764 {
10765         popallfiles();
10766         if (g_parsefile->pf_fd > 0) {
10767                 close(g_parsefile->pf_fd);
10768                 g_parsefile->pf_fd = 0;
10769         }
10770 }
10771
10772 /*
10773  * Like setinputfile, but takes an open file descriptor.  Call this with
10774  * interrupts off.
10775  */
10776 static void
10777 setinputfd(int fd, int push)
10778 {
10779         if (push) {
10780                 pushfile();
10781                 g_parsefile->buf = NULL;
10782         }
10783         g_parsefile->pf_fd = fd;
10784         if (g_parsefile->buf == NULL)
10785                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10786         g_parsefile->left_in_buffer = 0;
10787         g_parsefile->left_in_line = 0;
10788         g_parsefile->linno = 1;
10789 }
10790
10791 /*
10792  * Set the input to take input from a file.  If push is set, push the
10793  * old input onto the stack first.
10794  */
10795 static int
10796 setinputfile(const char *fname, int flags)
10797 {
10798         int fd;
10799
10800         INT_OFF;
10801         fd = open(fname, O_RDONLY | O_CLOEXEC);
10802         if (fd < 0) {
10803                 if (flags & INPUT_NOFILE_OK)
10804                         goto out;
10805                 exitstatus = 127;
10806                 ash_msg_and_raise_perror("can't open '%s'", fname);
10807         }
10808         if (fd < 10)
10809                 fd = savefd(fd);
10810         else if (O_CLOEXEC == 0) /* old libc */
10811                 close_on_exec_on(fd);
10812
10813         setinputfd(fd, flags & INPUT_PUSH_FILE);
10814  out:
10815         INT_ON;
10816         return fd;
10817 }
10818
10819 /*
10820  * Like setinputfile, but takes input from a string.
10821  */
10822 static void
10823 setinputstring(char *string)
10824 {
10825         INT_OFF;
10826         pushfile();
10827         g_parsefile->next_to_pgetc = string;
10828         g_parsefile->left_in_line = strlen(string);
10829         g_parsefile->buf = NULL;
10830         g_parsefile->linno = 1;
10831         INT_ON;
10832 }
10833
10834
10835 /*
10836  * Routines to check for mail.
10837  */
10838
10839 #if ENABLE_ASH_MAIL
10840
10841 /* Hash of mtimes of mailboxes */
10842 static unsigned mailtime_hash;
10843 /* Set if MAIL or MAILPATH is changed. */
10844 static smallint mail_var_path_changed;
10845
10846 /*
10847  * Print appropriate message(s) if mail has arrived.
10848  * If mail_var_path_changed is set,
10849  * then the value of MAIL has mail_var_path_changed,
10850  * so we just update the values.
10851  */
10852 static void
10853 chkmail(void)
10854 {
10855         const char *mpath;
10856         char *p;
10857         char *q;
10858         unsigned new_hash;
10859         struct stackmark smark;
10860         struct stat statb;
10861
10862         setstackmark(&smark);
10863         mpath = mpathset() ? mpathval() : mailval();
10864         new_hash = 0;
10865         for (;;) {
10866                 p = path_advance(&mpath, nullstr);
10867                 if (p == NULL)
10868                         break;
10869                 if (*p == '\0')
10870                         continue;
10871                 for (q = p; *q; q++)
10872                         continue;
10873 #if DEBUG
10874                 if (q[-1] != '/')
10875                         abort();
10876 #endif
10877                 q[-1] = '\0';                   /* delete trailing '/' */
10878                 if (stat(p, &statb) < 0) {
10879                         continue;
10880                 }
10881                 /* Very simplistic "hash": just a sum of all mtimes */
10882                 new_hash += (unsigned)statb.st_mtime;
10883         }
10884         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10885                 if (mailtime_hash != 0)
10886                         out2str("you have mail\n");
10887                 mailtime_hash = new_hash;
10888         }
10889         mail_var_path_changed = 0;
10890         popstackmark(&smark);
10891 }
10892
10893 static void FAST_FUNC
10894 changemail(const char *val UNUSED_PARAM)
10895 {
10896         mail_var_path_changed = 1;
10897 }
10898
10899 #endif /* ASH_MAIL */
10900
10901
10902 /* ============ ??? */
10903
10904 /*
10905  * Set the shell parameters.
10906  */
10907 static void
10908 setparam(char **argv)
10909 {
10910         char **newparam;
10911         char **ap;
10912         int nparam;
10913
10914         for (nparam = 0; argv[nparam]; nparam++)
10915                 continue;
10916         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10917         while (*argv) {
10918                 *ap++ = ckstrdup(*argv++);
10919         }
10920         *ap = NULL;
10921         freeparam(&shellparam);
10922         shellparam.malloced = 1;
10923         shellparam.nparam = nparam;
10924         shellparam.p = newparam;
10925 #if ENABLE_ASH_GETOPTS
10926         shellparam.optind = 1;
10927         shellparam.optoff = -1;
10928 #endif
10929 }
10930
10931 /*
10932  * Process shell options.  The global variable argptr contains a pointer
10933  * to the argument list; we advance it past the options.
10934  *
10935  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10936  * For a non-interactive shell, an error condition encountered
10937  * by a special built-in ... shall cause the shell to write a diagnostic message
10938  * to standard error and exit as shown in the following table:
10939  * Error                                           Special Built-In
10940  * ...
10941  * Utility syntax error (option or operand error)  Shall exit
10942  * ...
10943  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10944  * we see that bash does not do that (set "finishes" with error code 1 instead,
10945  * and shell continues), and people rely on this behavior!
10946  * Testcase:
10947  * set -o barfoo 2>/dev/null
10948  * echo $?
10949  *
10950  * Oh well. Let's mimic that.
10951  */
10952 static int
10953 plus_minus_o(char *name, int val)
10954 {
10955         int i;
10956
10957         if (name) {
10958                 for (i = 0; i < NOPTS; i++) {
10959                         if (strcmp(name, optnames(i)) == 0) {
10960                                 optlist[i] = val;
10961                                 return 0;
10962                         }
10963                 }
10964                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10965                 return 1;
10966         }
10967         for (i = 0; i < NOPTS; i++) {
10968                 if (val) {
10969                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10970                 } else {
10971                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10972                 }
10973         }
10974         return 0;
10975 }
10976 static void
10977 setoption(int flag, int val)
10978 {
10979         int i;
10980
10981         for (i = 0; i < NOPTS; i++) {
10982                 if (optletters(i) == flag) {
10983                         optlist[i] = val;
10984                         return;
10985                 }
10986         }
10987         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10988         /* NOTREACHED */
10989 }
10990 static int
10991 options(int cmdline, int *login_sh)
10992 {
10993         char *p;
10994         int val;
10995         int c;
10996
10997         if (cmdline)
10998                 minusc = NULL;
10999         while ((p = *argptr) != NULL) {
11000                 c = *p++;
11001                 if (c != '-' && c != '+')
11002                         break;
11003                 argptr++;
11004                 val = 0; /* val = 0 if c == '+' */
11005                 if (c == '-') {
11006                         val = 1;
11007                         if (p[0] == '\0' || LONE_DASH(p)) {
11008                                 if (!cmdline) {
11009                                         /* "-" means turn off -x and -v */
11010                                         if (p[0] == '\0')
11011                                                 xflag = vflag = 0;
11012                                         /* "--" means reset params */
11013                                         else if (*argptr == NULL)
11014                                                 setparam(argptr);
11015                                 }
11016                                 break;    /* "-" or "--" terminates options */
11017                         }
11018                 }
11019                 /* first char was + or - */
11020                 while ((c = *p++) != '\0') {
11021                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
11022                         if (c == 'c' && cmdline) {
11023                                 minusc = p;     /* command is after shell args */
11024                         } else if (c == 'o') {
11025                                 if (plus_minus_o(*argptr, val)) {
11026                                         /* it already printed err message */
11027                                         return 1; /* error */
11028                                 }
11029                                 if (*argptr)
11030                                         argptr++;
11031                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
11032                                 if (login_sh)
11033                                         *login_sh = 1;
11034                         /* bash does not accept +-login, we also won't */
11035                         } else if (cmdline && val && (c == '-')) { /* long options */
11036                                 if (strcmp(p, "login") == 0) {
11037                                         if (login_sh)
11038                                                 *login_sh = 1;
11039                                 }
11040                                 break;
11041                         } else {
11042                                 setoption(c, val);
11043                         }
11044                 }
11045         }
11046         return 0;
11047 }
11048
11049 /*
11050  * The shift builtin command.
11051  */
11052 static int FAST_FUNC
11053 shiftcmd(int argc UNUSED_PARAM, char **argv)
11054 {
11055         int n;
11056         char **ap1, **ap2;
11057
11058         n = 1;
11059         if (argv[1])
11060                 n = number(argv[1]);
11061         if (n > shellparam.nparam)
11062                 return 1;
11063         INT_OFF;
11064         shellparam.nparam -= n;
11065         for (ap1 = shellparam.p; --n >= 0; ap1++) {
11066                 if (shellparam.malloced)
11067                         free(*ap1);
11068         }
11069         ap2 = shellparam.p;
11070         while ((*ap2++ = *ap1++) != NULL)
11071                 continue;
11072 #if ENABLE_ASH_GETOPTS
11073         shellparam.optind = 1;
11074         shellparam.optoff = -1;
11075 #endif
11076         INT_ON;
11077         return 0;
11078 }
11079
11080 /*
11081  * POSIX requires that 'set' (but not export or readonly) output the
11082  * variables in lexicographic order - by the locale's collating order (sigh).
11083  * Maybe we could keep them in an ordered balanced binary tree
11084  * instead of hashed lists.
11085  * For now just roll 'em through qsort for printing...
11086  */
11087 static int
11088 showvars(const char *sep_prefix, int on, int off)
11089 {
11090         const char *sep;
11091         char **ep, **epend;
11092
11093         ep = listvars(on, off, /*strlist:*/ NULL, &epend);
11094         qsort(ep, epend - ep, sizeof(char *), vpcmp);
11095
11096         sep = *sep_prefix ? " " : sep_prefix;
11097
11098         for (; ep < epend; ep++) {
11099                 const char *p;
11100                 const char *q;
11101
11102                 p = endofname(*ep);
11103 /* Used to have simple "p = strchrnul(*ep, '=')" here instead, but this
11104  * makes "export -p" to have output not suitable for "eval":
11105  * import os
11106  * os.environ["test-test"]="test"
11107  * if os.fork() == 0:
11108  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
11109  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])
11110  */
11111                 q = nullstr;
11112                 if (*p == '=')
11113                         q = single_quote(++p);
11114                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
11115         }
11116         return 0;
11117 }
11118
11119 /*
11120  * The set command builtin.
11121  */
11122 static int FAST_FUNC
11123 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11124 {
11125         int retval;
11126
11127         if (!argv[1])
11128                 return showvars(nullstr, 0, VUNSET);
11129
11130         INT_OFF;
11131         retval = options(/*cmdline:*/ 0, NULL);
11132         if (retval == 0) { /* if no parse error... */
11133                 optschanged();
11134                 if (*argptr != NULL) {
11135                         setparam(argptr);
11136                 }
11137         }
11138         INT_ON;
11139         return retval;
11140 }
11141
11142 #if ENABLE_ASH_RANDOM_SUPPORT
11143 static void FAST_FUNC
11144 change_random(const char *value)
11145 {
11146         uint32_t t;
11147
11148         if (value == NULL) {
11149                 /* "get", generate */
11150                 t = next_random(&random_gen);
11151                 /* set without recursion */
11152                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
11153                 vrandom.flags &= ~VNOFUNC;
11154         } else {
11155                 /* set/reset */
11156                 t = strtoul(value, NULL, 10);
11157                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
11158         }
11159 }
11160 #endif
11161
11162 #if ENABLE_ASH_GETOPTS
11163 static int
11164 getopts(char *optstr, char *optvar, char **optfirst)
11165 {
11166         char *p, *q;
11167         char c = '?';
11168         int done = 0;
11169         char sbuf[2];
11170         char **optnext;
11171         int ind = shellparam.optind;
11172         int off = shellparam.optoff;
11173
11174         sbuf[1] = '\0';
11175
11176         shellparam.optind = -1;
11177         optnext = optfirst + ind - 1;
11178
11179         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
11180                 p = NULL;
11181         else
11182                 p = optnext[-1] + off;
11183         if (p == NULL || *p == '\0') {
11184                 /* Current word is done, advance */
11185                 p = *optnext;
11186                 if (p == NULL || *p != '-' || *++p == '\0') {
11187  atend:
11188                         unsetvar("OPTARG");
11189                         p = NULL;
11190                         done = 1;
11191                         goto out;
11192                 }
11193                 optnext++;
11194                 if (LONE_DASH(p))        /* check for "--" */
11195                         goto atend;
11196         }
11197
11198         c = *p++;
11199         for (q = optstr; *q != c;) {
11200                 if (*q == '\0') {
11201                         /* OPTERR is a bashism */
11202                         const char *cp = lookupvar("OPTERR");
11203                         if ((cp && LONE_CHAR(cp, '0'))
11204                          || (optstr[0] == ':')
11205                         ) {
11206                                 sbuf[0] = c;
11207                                 /*sbuf[1] = '\0'; - already is */
11208                                 setvar0("OPTARG", sbuf);
11209                         } else {
11210                                 fprintf(stderr, "Illegal option -%c\n", c);
11211                                 unsetvar("OPTARG");
11212                         }
11213                         c = '?';
11214                         goto out;
11215                 }
11216                 if (*++q == ':')
11217                         q++;
11218         }
11219
11220         if (*++q == ':') {
11221                 if (*p == '\0' && (p = *optnext) == NULL) {
11222                         /* OPTERR is a bashism */
11223                         const char *cp = lookupvar("OPTERR");
11224                         if ((cp && LONE_CHAR(cp, '0'))
11225                          || (optstr[0] == ':')
11226                         ) {
11227                                 sbuf[0] = c;
11228                                 /*sbuf[1] = '\0'; - already is */
11229                                 setvar0("OPTARG", sbuf);
11230                                 c = ':';
11231                         } else {
11232                                 fprintf(stderr, "No arg for -%c option\n", c);
11233                                 unsetvar("OPTARG");
11234                                 c = '?';
11235                         }
11236                         goto out;
11237                 }
11238
11239                 if (p == *optnext)
11240                         optnext++;
11241                 setvar0("OPTARG", p);
11242                 p = NULL;
11243         } else
11244                 setvar0("OPTARG", nullstr);
11245  out:
11246         ind = optnext - optfirst + 1;
11247         setvar("OPTIND", itoa(ind), VNOFUNC);
11248         sbuf[0] = c;
11249         /*sbuf[1] = '\0'; - already is */
11250         setvar0(optvar, sbuf);
11251
11252         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11253         shellparam.optind = ind;
11254
11255         return done;
11256 }
11257
11258 /*
11259  * The getopts builtin.  Shellparam.optnext points to the next argument
11260  * to be processed.  Shellparam.optptr points to the next character to
11261  * be processed in the current argument.  If shellparam.optnext is NULL,
11262  * then it's the first time getopts has been called.
11263  */
11264 static int FAST_FUNC
11265 getoptscmd(int argc, char **argv)
11266 {
11267         char **optbase;
11268
11269         if (argc < 3)
11270                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11271         if (argc == 3) {
11272                 optbase = shellparam.p;
11273                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11274                         shellparam.optind = 1;
11275                         shellparam.optoff = -1;
11276                 }
11277         } else {
11278                 optbase = &argv[3];
11279                 if ((unsigned)shellparam.optind > argc - 2) {
11280                         shellparam.optind = 1;
11281                         shellparam.optoff = -1;
11282                 }
11283         }
11284
11285         return getopts(argv[1], argv[2], optbase);
11286 }
11287 #endif /* ASH_GETOPTS */
11288
11289
11290 /* ============ Shell parser */
11291
11292 struct heredoc {
11293         struct heredoc *next;   /* next here document in list */
11294         union node *here;       /* redirection node */
11295         char *eofmark;          /* string indicating end of input */
11296         smallint striptabs;     /* if set, strip leading tabs */
11297 };
11298
11299 static smallint tokpushback;           /* last token pushed back */
11300 static smallint quoteflag;             /* set if (part of) last token was quoted */
11301 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11302 static struct heredoc *heredoclist;    /* list of here documents to read */
11303 static char *wordtext;                 /* text of last word returned by readtoken */
11304 static struct nodelist *backquotelist;
11305 static union node *redirnode;
11306 static struct heredoc *heredoc;
11307
11308 static const char *
11309 tokname(char *buf, int tok)
11310 {
11311         if (tok < TSEMI)
11312                 return tokname_array[tok];
11313         sprintf(buf, "\"%s\"", tokname_array[tok]);
11314         return buf;
11315 }
11316
11317 /* raise_error_unexpected_syntax:
11318  * Called when an unexpected token is read during the parse.  The argument
11319  * is the token that is expected, or -1 if more than one type of token can
11320  * occur at this point.
11321  */
11322 static void raise_error_unexpected_syntax(int) NORETURN;
11323 static void
11324 raise_error_unexpected_syntax(int token)
11325 {
11326         char msg[64];
11327         char buf[16];
11328         int l;
11329
11330         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11331         if (token >= 0)
11332                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11333         raise_error_syntax(msg);
11334         /* NOTREACHED */
11335 }
11336
11337 /* parsing is heavily cross-recursive, need these forward decls */
11338 static union node *andor(void);
11339 static union node *pipeline(void);
11340 static union node *parse_command(void);
11341 static void parseheredoc(void);
11342 static int peektoken(void);
11343 static int readtoken(void);
11344
11345 static union node *
11346 list(int nlflag)
11347 {
11348         union node *n1, *n2, *n3;
11349         int tok;
11350
11351         n1 = NULL;
11352         for (;;) {
11353                 switch (peektoken()) {
11354                 case TNL:
11355                         if (!(nlflag & 1))
11356                                 break;
11357                         parseheredoc();
11358                         return n1;
11359
11360                 case TEOF:
11361                         if (!n1 && (nlflag & 1))
11362                                 n1 = NODE_EOF;
11363                         parseheredoc();
11364                         return n1;
11365                 }
11366
11367                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11368                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11369                         return n1;
11370                 nlflag |= 2;
11371
11372                 n2 = andor();
11373                 tok = readtoken();
11374                 if (tok == TBACKGND) {
11375                         if (n2->type == NPIPE) {
11376                                 n2->npipe.pipe_backgnd = 1;
11377                         } else {
11378                                 if (n2->type != NREDIR) {
11379                                         n3 = stzalloc(sizeof(struct nredir));
11380                                         n3->nredir.n = n2;
11381                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11382                                         n2 = n3;
11383                                 }
11384                                 n2->type = NBACKGND;
11385                         }
11386                 }
11387                 if (n1 == NULL) {
11388                         n1 = n2;
11389                 } else {
11390                         n3 = stzalloc(sizeof(struct nbinary));
11391                         n3->type = NSEMI;
11392                         n3->nbinary.ch1 = n1;
11393                         n3->nbinary.ch2 = n2;
11394                         n1 = n3;
11395                 }
11396                 switch (tok) {
11397                 case TNL:
11398                 case TEOF:
11399                         tokpushback = 1;
11400                         /* fall through */
11401                 case TBACKGND:
11402                 case TSEMI:
11403                         break;
11404                 default:
11405                         if ((nlflag & 1))
11406                                 raise_error_unexpected_syntax(-1);
11407                         tokpushback = 1;
11408                         return n1;
11409                 }
11410         }
11411 }
11412
11413 static union node *
11414 andor(void)
11415 {
11416         union node *n1, *n2, *n3;
11417         int t;
11418
11419         n1 = pipeline();
11420         for (;;) {
11421                 t = readtoken();
11422                 if (t == TAND) {
11423                         t = NAND;
11424                 } else if (t == TOR) {
11425                         t = NOR;
11426                 } else {
11427                         tokpushback = 1;
11428                         return n1;
11429                 }
11430                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11431                 n2 = pipeline();
11432                 n3 = stzalloc(sizeof(struct nbinary));
11433                 n3->type = t;
11434                 n3->nbinary.ch1 = n1;
11435                 n3->nbinary.ch2 = n2;
11436                 n1 = n3;
11437         }
11438 }
11439
11440 static union node *
11441 pipeline(void)
11442 {
11443         union node *n1, *n2, *pipenode;
11444         struct nodelist *lp, *prev;
11445         int negate;
11446
11447         negate = 0;
11448         TRACE(("pipeline: entered\n"));
11449         if (readtoken() == TNOT) {
11450                 negate = !negate;
11451                 checkkwd = CHKKWD | CHKALIAS;
11452         } else
11453                 tokpushback = 1;
11454         n1 = parse_command();
11455         if (readtoken() == TPIPE) {
11456                 pipenode = stzalloc(sizeof(struct npipe));
11457                 pipenode->type = NPIPE;
11458                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11459                 lp = stzalloc(sizeof(struct nodelist));
11460                 pipenode->npipe.cmdlist = lp;
11461                 lp->n = n1;
11462                 do {
11463                         prev = lp;
11464                         lp = stzalloc(sizeof(struct nodelist));
11465                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11466                         lp->n = parse_command();
11467                         prev->next = lp;
11468                 } while (readtoken() == TPIPE);
11469                 lp->next = NULL;
11470                 n1 = pipenode;
11471         }
11472         tokpushback = 1;
11473         if (negate) {
11474                 n2 = stzalloc(sizeof(struct nnot));
11475                 n2->type = NNOT;
11476                 n2->nnot.com = n1;
11477                 return n2;
11478         }
11479         return n1;
11480 }
11481
11482 static union node *
11483 makename(void)
11484 {
11485         union node *n;
11486
11487         n = stzalloc(sizeof(struct narg));
11488         n->type = NARG;
11489         /*n->narg.next = NULL; - stzalloc did it */
11490         n->narg.text = wordtext;
11491         n->narg.backquote = backquotelist;
11492         return n;
11493 }
11494
11495 static void
11496 fixredir(union node *n, const char *text, int err)
11497 {
11498         int fd;
11499
11500         TRACE(("Fix redir %s %d\n", text, err));
11501         if (!err)
11502                 n->ndup.vname = NULL;
11503
11504         fd = bb_strtou(text, NULL, 10);
11505         if (!errno && fd >= 0)
11506                 n->ndup.dupfd = fd;
11507         else if (LONE_DASH(text))
11508                 n->ndup.dupfd = -1;
11509         else {
11510                 if (err)
11511                         raise_error_syntax("bad fd number");
11512                 n->ndup.vname = makename();
11513         }
11514 }
11515
11516 static void
11517 parsefname(void)
11518 {
11519         union node *n = redirnode;
11520
11521         if (n->type == NHERE)
11522                 checkkwd = CHKEOFMARK;
11523         if (readtoken() != TWORD)
11524                 raise_error_unexpected_syntax(-1);
11525         if (n->type == NHERE) {
11526                 struct heredoc *here = heredoc;
11527                 struct heredoc *p;
11528
11529                 if (quoteflag == 0)
11530                         n->type = NXHERE;
11531                 TRACE(("Here document %d\n", n->type));
11532                 rmescapes(wordtext, 0, NULL);
11533                 here->eofmark = wordtext;
11534                 here->next = NULL;
11535                 if (heredoclist == NULL)
11536                         heredoclist = here;
11537                 else {
11538                         for (p = heredoclist; p->next; p = p->next)
11539                                 continue;
11540                         p->next = here;
11541                 }
11542         } else if (n->type == NTOFD || n->type == NFROMFD) {
11543                 fixredir(n, wordtext, 0);
11544         } else {
11545                 n->nfile.fname = makename();
11546         }
11547 }
11548
11549 static union node *
11550 simplecmd(void)
11551 {
11552         union node *args, **app;
11553         union node *n = NULL;
11554         union node *vars, **vpp;
11555         union node **rpp, *redir;
11556         int savecheckkwd;
11557         int savelinno;
11558 #if BASH_TEST2
11559         smallint double_brackets_flag = 0;
11560 #endif
11561         IF_BASH_FUNCTION(smallint function_flag = 0;)
11562
11563         args = NULL;
11564         app = &args;
11565         vars = NULL;
11566         vpp = &vars;
11567         redir = NULL;
11568         rpp = &redir;
11569
11570         savecheckkwd = CHKALIAS;
11571         savelinno = g_parsefile->linno;
11572         for (;;) {
11573                 int t;
11574                 checkkwd = savecheckkwd;
11575                 t = readtoken();
11576                 switch (t) {
11577 #if BASH_FUNCTION
11578                 case TFUNCTION:
11579                         if (peektoken() != TWORD)
11580                                 raise_error_unexpected_syntax(TWORD);
11581                         function_flag = 1;
11582                         break;
11583 #endif
11584 #if BASH_TEST2
11585                 case TAND: /* "&&" */
11586                 case TOR: /* "||" */
11587                         if (!double_brackets_flag) {
11588                                 tokpushback = 1;
11589                                 goto out;
11590                         }
11591                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11592 #endif
11593                 case TWORD:
11594                         n = stzalloc(sizeof(struct narg));
11595                         n->type = NARG;
11596                         /*n->narg.next = NULL; - stzalloc did it */
11597                         n->narg.text = wordtext;
11598 #if BASH_TEST2
11599                         if (strcmp("[[", wordtext) == 0)
11600                                 double_brackets_flag = 1;
11601                         else if (strcmp("]]", wordtext) == 0)
11602                                 double_brackets_flag = 0;
11603 #endif
11604                         n->narg.backquote = backquotelist;
11605                         if (savecheckkwd && isassignment(wordtext)) {
11606                                 *vpp = n;
11607                                 vpp = &n->narg.next;
11608                         } else {
11609                                 *app = n;
11610                                 app = &n->narg.next;
11611                                 savecheckkwd = 0;
11612                         }
11613 #if BASH_FUNCTION
11614                         if (function_flag) {
11615                                 checkkwd = CHKNL | CHKKWD;
11616                                 switch (peektoken()) {
11617                                 case TBEGIN:
11618                                 case TIF:
11619                                 case TCASE:
11620                                 case TUNTIL:
11621                                 case TWHILE:
11622                                 case TFOR:
11623                                         goto do_func;
11624                                 case TLP:
11625                                         function_flag = 0;
11626                                         break;
11627 # if BASH_TEST2
11628                                 case TWORD:
11629                                         if (strcmp("[[", wordtext) == 0)
11630                                                 goto do_func;
11631                                         /* fall through */
11632 # endif
11633                                 default:
11634                                         raise_error_unexpected_syntax(-1);
11635                                 }
11636                         }
11637 #endif
11638                         break;
11639                 case TREDIR:
11640                         *rpp = n = redirnode;
11641                         rpp = &n->nfile.next;
11642                         parsefname();   /* read name of redirection file */
11643                         break;
11644                 case TLP:
11645  IF_BASH_FUNCTION(do_func:)
11646                         if (args && app == &args->narg.next
11647                          && !vars && !redir
11648                         ) {
11649                                 struct builtincmd *bcmd;
11650                                 const char *name;
11651
11652                                 /* We have a function */
11653                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11654                                         raise_error_unexpected_syntax(TRP);
11655                                 name = n->narg.text;
11656                                 if (!goodname(name)
11657                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11658                                 ) {
11659                                         raise_error_syntax("bad function name");
11660                                 }
11661                                 n->type = NDEFUN;
11662                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11663                                 n->ndefun.text = n->narg.text;
11664                                 n->ndefun.linno = g_parsefile->linno;
11665                                 n->ndefun.body = parse_command();
11666                                 return n;
11667                         }
11668                         IF_BASH_FUNCTION(function_flag = 0;)
11669                         /* fall through */
11670                 default:
11671                         tokpushback = 1;
11672                         goto out;
11673                 }
11674         }
11675  out:
11676         *app = NULL;
11677         *vpp = NULL;
11678         *rpp = NULL;
11679         n = stzalloc(sizeof(struct ncmd));
11680         if (NCMD != 0)
11681                 n->type = NCMD;
11682         n->ncmd.linno = savelinno;
11683         n->ncmd.args = args;
11684         n->ncmd.assign = vars;
11685         n->ncmd.redirect = redir;
11686         return n;
11687 }
11688
11689 static union node *
11690 parse_command(void)
11691 {
11692         union node *n1, *n2;
11693         union node *ap, **app;
11694         union node *cp, **cpp;
11695         union node *redir, **rpp;
11696         union node **rpp2;
11697         int t;
11698         int savelinno;
11699
11700         redir = NULL;
11701         rpp2 = &redir;
11702
11703         savelinno = g_parsefile->linno;
11704
11705         switch (readtoken()) {
11706         default:
11707                 raise_error_unexpected_syntax(-1);
11708                 /* NOTREACHED */
11709         case TIF:
11710                 n1 = stzalloc(sizeof(struct nif));
11711                 n1->type = NIF;
11712                 n1->nif.test = list(0);
11713                 if (readtoken() != TTHEN)
11714                         raise_error_unexpected_syntax(TTHEN);
11715                 n1->nif.ifpart = list(0);
11716                 n2 = n1;
11717                 while (readtoken() == TELIF) {
11718                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11719                         n2 = n2->nif.elsepart;
11720                         n2->type = NIF;
11721                         n2->nif.test = list(0);
11722                         if (readtoken() != TTHEN)
11723                                 raise_error_unexpected_syntax(TTHEN);
11724                         n2->nif.ifpart = list(0);
11725                 }
11726                 if (lasttoken == TELSE)
11727                         n2->nif.elsepart = list(0);
11728                 else {
11729                         n2->nif.elsepart = NULL;
11730                         tokpushback = 1;
11731                 }
11732                 t = TFI;
11733                 break;
11734         case TWHILE:
11735         case TUNTIL: {
11736                 int got;
11737                 n1 = stzalloc(sizeof(struct nbinary));
11738                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11739                 n1->nbinary.ch1 = list(0);
11740                 got = readtoken();
11741                 if (got != TDO) {
11742                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11743                                         got == TWORD ? wordtext : ""));
11744                         raise_error_unexpected_syntax(TDO);
11745                 }
11746                 n1->nbinary.ch2 = list(0);
11747                 t = TDONE;
11748                 break;
11749         }
11750         case TFOR:
11751                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11752                         raise_error_syntax("bad for loop variable");
11753                 n1 = stzalloc(sizeof(struct nfor));
11754                 n1->type = NFOR;
11755                 n1->nfor.linno = savelinno;
11756                 n1->nfor.var = wordtext;
11757                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11758                 if (readtoken() == TIN) {
11759                         app = &ap;
11760                         while (readtoken() == TWORD) {
11761                                 n2 = stzalloc(sizeof(struct narg));
11762                                 n2->type = NARG;
11763                                 /*n2->narg.next = NULL; - stzalloc did it */
11764                                 n2->narg.text = wordtext;
11765                                 n2->narg.backquote = backquotelist;
11766                                 *app = n2;
11767                                 app = &n2->narg.next;
11768                         }
11769                         *app = NULL;
11770                         n1->nfor.args = ap;
11771                         if (lasttoken != TNL && lasttoken != TSEMI)
11772                                 raise_error_unexpected_syntax(-1);
11773                 } else {
11774                         n2 = stzalloc(sizeof(struct narg));
11775                         n2->type = NARG;
11776                         /*n2->narg.next = NULL; - stzalloc did it */
11777                         n2->narg.text = (char *)dolatstr;
11778                         /*n2->narg.backquote = NULL;*/
11779                         n1->nfor.args = n2;
11780                         /*
11781                          * Newline or semicolon here is optional (but note
11782                          * that the original Bourne shell only allowed NL).
11783                          */
11784                         if (lasttoken != TSEMI)
11785                                 tokpushback = 1;
11786                 }
11787                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11788                 if (readtoken() != TDO)
11789                         raise_error_unexpected_syntax(TDO);
11790                 n1->nfor.body = list(0);
11791                 t = TDONE;
11792                 break;
11793         case TCASE:
11794                 n1 = stzalloc(sizeof(struct ncase));
11795                 n1->type = NCASE;
11796                 n1->ncase.linno = savelinno;
11797                 if (readtoken() != TWORD)
11798                         raise_error_unexpected_syntax(TWORD);
11799                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11800                 n2->type = NARG;
11801                 /*n2->narg.next = NULL; - stzalloc did it */
11802                 n2->narg.text = wordtext;
11803                 n2->narg.backquote = backquotelist;
11804                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11805                 if (readtoken() != TIN)
11806                         raise_error_unexpected_syntax(TIN);
11807                 cpp = &n1->ncase.cases;
11808  next_case:
11809                 checkkwd = CHKNL | CHKKWD;
11810                 t = readtoken();
11811                 while (t != TESAC) {
11812                         if (lasttoken == TLP)
11813                                 readtoken();
11814                         *cpp = cp = stzalloc(sizeof(struct nclist));
11815                         cp->type = NCLIST;
11816                         app = &cp->nclist.pattern;
11817                         for (;;) {
11818                                 *app = ap = stzalloc(sizeof(struct narg));
11819                                 ap->type = NARG;
11820                                 /*ap->narg.next = NULL; - stzalloc did it */
11821                                 ap->narg.text = wordtext;
11822                                 ap->narg.backquote = backquotelist;
11823                                 if (readtoken() != TPIPE)
11824                                         break;
11825                                 app = &ap->narg.next;
11826                                 readtoken();
11827                         }
11828                         //ap->narg.next = NULL;
11829                         if (lasttoken != TRP)
11830                                 raise_error_unexpected_syntax(TRP);
11831                         cp->nclist.body = list(2);
11832
11833                         cpp = &cp->nclist.next;
11834
11835                         checkkwd = CHKNL | CHKKWD;
11836                         t = readtoken();
11837                         if (t != TESAC) {
11838                                 if (t != TENDCASE)
11839                                         raise_error_unexpected_syntax(TENDCASE);
11840                                 goto next_case;
11841                         }
11842                 }
11843                 *cpp = NULL;
11844                 goto redir;
11845         case TLP:
11846                 n1 = stzalloc(sizeof(struct nredir));
11847                 n1->type = NSUBSHELL;
11848                 n1->nredir.linno = savelinno;
11849                 n1->nredir.n = list(0);
11850                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11851                 t = TRP;
11852                 break;
11853         case TBEGIN:
11854                 n1 = list(0);
11855                 t = TEND;
11856                 break;
11857         IF_BASH_FUNCTION(case TFUNCTION:)
11858         case TWORD:
11859         case TREDIR:
11860                 tokpushback = 1;
11861                 return simplecmd();
11862         }
11863
11864         if (readtoken() != t)
11865                 raise_error_unexpected_syntax(t);
11866
11867  redir:
11868         /* Now check for redirection which may follow command */
11869         checkkwd = CHKKWD | CHKALIAS;
11870         rpp = rpp2;
11871         while (readtoken() == TREDIR) {
11872                 *rpp = n2 = redirnode;
11873                 rpp = &n2->nfile.next;
11874                 parsefname();
11875         }
11876         tokpushback = 1;
11877         *rpp = NULL;
11878         if (redir) {
11879                 if (n1->type != NSUBSHELL) {
11880                         n2 = stzalloc(sizeof(struct nredir));
11881                         n2->type = NREDIR;
11882                         n2->nredir.linno = savelinno;
11883                         n2->nredir.n = n1;
11884                         n1 = n2;
11885                 }
11886                 n1->nredir.redirect = redir;
11887         }
11888         return n1;
11889 }
11890
11891 #if BASH_DOLLAR_SQUOTE
11892 static int
11893 decode_dollar_squote(void)
11894 {
11895         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11896         int c, cnt;
11897         char *p;
11898         char buf[4];
11899
11900         c = pgetc();
11901         p = strchr(C_escapes, c);
11902         if (p) {
11903                 buf[0] = c;
11904                 p = buf;
11905                 cnt = 3;
11906                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11907                         do {
11908                                 c = pgetc();
11909                                 *++p = c;
11910                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11911                         pungetc();
11912                 } else if (c == 'x') { /* \xHH */
11913                         do {
11914                                 c = pgetc();
11915                                 *++p = c;
11916                         } while (isxdigit(c) && --cnt);
11917                         pungetc();
11918                         if (cnt == 3) { /* \x but next char is "bad" */
11919                                 c = 'x';
11920                                 goto unrecognized;
11921                         }
11922                 } else { /* simple seq like \\ or \t */
11923                         p++;
11924                 }
11925                 *p = '\0';
11926                 p = buf;
11927                 c = bb_process_escape_sequence((void*)&p);
11928         } else { /* unrecognized "\z": print both chars unless ' or " */
11929                 if (c != '\'' && c != '"') {
11930  unrecognized:
11931                         c |= 0x100; /* "please encode \, then me" */
11932                 }
11933         }
11934         return c;
11935 }
11936 #endif
11937
11938 /* Used by expandstr to get here-doc like behaviour. */
11939 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11940
11941 static ALWAYS_INLINE int
11942 realeofmark(const char *eofmark)
11943 {
11944         return eofmark && eofmark != FAKEEOFMARK;
11945 }
11946
11947 /*
11948  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11949  * is not NULL, read a here document.  In the latter case, eofmark is the
11950  * word which marks the end of the document and striptabs is true if
11951  * leading tabs should be stripped from the document.  The argument c
11952  * is the first character of the input token or document.
11953  *
11954  * Because C does not have internal subroutines, I have simulated them
11955  * using goto's to implement the subroutine linkage.  The following macros
11956  * will run code that appears at the end of readtoken1.
11957  */
11958 #define CHECKEND()      {goto checkend; checkend_return:;}
11959 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11960 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11961 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11962 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11963 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11964 static int
11965 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11966 {
11967         /* NB: syntax parameter fits into smallint */
11968         /* c parameter is an unsigned char or PEOF or PEOA */
11969         char *out;
11970         size_t len;
11971         struct nodelist *bqlist;
11972         smallint quotef;
11973         smallint oldstyle;
11974         smallint pssyntax;   /* we are expanding a prompt string */
11975         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11976         /* syntax stack */
11977         struct synstack synbase = { };
11978         struct synstack *synstack = &synbase;
11979
11980 #if ENABLE_ASH_EXPAND_PRMT
11981         pssyntax = (syntax == PSSYNTAX);
11982         if (pssyntax)
11983                 syntax = DQSYNTAX;
11984 #else
11985         pssyntax = 0; /* constant */
11986 #endif
11987         synstack->syntax = syntax;
11988
11989         if (syntax == DQSYNTAX)
11990                 synstack->dblquote = 1;
11991         quotef = 0;
11992         bqlist = NULL;
11993
11994         STARTSTACKSTR(out);
11995  loop:
11996         /* For each line, until end of word */
11997         CHECKEND();     /* set c to PEOF if at end of here document */
11998         for (;;) {      /* until end of line or end of word */
11999                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
12000                 switch (SIT(c, synstack->syntax)) {
12001                 case CNL:       /* '\n' */
12002                         if (synstack->syntax == BASESYNTAX)
12003                                 goto endword;   /* exit outer loop */
12004                         USTPUTC(c, out);
12005                         nlprompt();
12006                         c = pgetc();
12007                         goto loop;              /* continue outer loop */
12008                 case CWORD:
12009                         USTPUTC(c, out);
12010                         break;
12011                 case CCTL:
12012 #if BASH_DOLLAR_SQUOTE
12013                         if (c == '\\' && bash_dollar_squote) {
12014                                 c = decode_dollar_squote();
12015                                 if (c == '\0') {
12016                                         /* skip $'\000', $'\x00' (like bash) */
12017                                         break;
12018                                 }
12019                                 if (c & 0x100) {
12020                                         /* Unknown escape. Encode as '\z' */
12021                                         c = (unsigned char)c;
12022                                         if (eofmark == NULL || synstack->dblquote)
12023                                                 USTPUTC(CTLESC, out);
12024                                         USTPUTC('\\', out);
12025                                 }
12026                         }
12027 #endif
12028                         if (!eofmark || synstack->dblquote || synstack->varnest)
12029                                 USTPUTC(CTLESC, out);
12030                         USTPUTC(c, out);
12031                         break;
12032                 case CBACK:     /* backslash */
12033                         c = pgetc_without_PEOA();
12034                         if (c == PEOF) {
12035                                 USTPUTC(CTLESC, out);
12036                                 USTPUTC('\\', out);
12037                                 pungetc();
12038                         } else if (c == '\n') {
12039                                 nlprompt();
12040                         } else {
12041                                 if (pssyntax && c == '$') {
12042                                         USTPUTC(CTLESC, out);
12043                                         USTPUTC('\\', out);
12044                                 }
12045                                 /* Backslash is retained if we are in "str"
12046                                  * and next char isn't dquote-special.
12047                                  */
12048                                 if (synstack->dblquote
12049                                  && c != '\\'
12050                                  && c != '`'
12051                                  && c != '$'
12052                                  && (c != '"' || (eofmark != NULL && !synstack->varnest))
12053                                  && (c != '}' || !synstack->varnest)
12054                                 ) {
12055                                         USTPUTC(CTLESC, out); /* protect '\' from glob */
12056                                         USTPUTC('\\', out);
12057                                 }
12058                                 USTPUTC(CTLESC, out);
12059                                 USTPUTC(c, out);
12060                                 quotef = 1;
12061                         }
12062                         break;
12063                 case CSQUOTE:
12064                         synstack->syntax = SQSYNTAX;
12065  quotemark:
12066                         if (eofmark == NULL) {
12067                                 USTPUTC(CTLQUOTEMARK, out);
12068                         }
12069                         break;
12070                 case CDQUOTE:
12071                         synstack->syntax = DQSYNTAX;
12072                         synstack->dblquote = 1;
12073  toggledq:
12074                         if (synstack->varnest)
12075                                 synstack->innerdq ^= 1;
12076                         goto quotemark;
12077                 case CENDQUOTE:
12078                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
12079                         if (eofmark != NULL && synstack->varnest == 0) {
12080                                 USTPUTC(c, out);
12081                                 break;
12082                         }
12083
12084                         if (synstack->dqvarnest == 0) {
12085                                 synstack->syntax = BASESYNTAX;
12086                                 synstack->dblquote = 0;
12087                         }
12088
12089                         quotef = 1;
12090
12091                         if (c == '"')
12092                                 goto toggledq;
12093
12094                         goto quotemark;
12095                 case CVAR:      /* '$' */
12096                         PARSESUB();             /* parse substitution */
12097                         break;
12098                 case CENDVAR:   /* '}' */
12099                         if (!synstack->innerdq && synstack->varnest > 0) {
12100                                 if (!--synstack->varnest && synstack->varpushed)
12101                                         synstack_pop(&synstack);
12102                                 else if (synstack->dqvarnest > 0)
12103                                         synstack->dqvarnest--;
12104                                 c = CTLENDVAR;
12105                         }
12106                         USTPUTC(c, out);
12107                         break;
12108 #if ENABLE_FEATURE_SH_MATH
12109                 case CLP:       /* '(' in arithmetic */
12110                         synstack->parenlevel++;
12111                         USTPUTC(c, out);
12112                         break;
12113                 case CRP:       /* ')' in arithmetic */
12114                         if (synstack->parenlevel > 0) {
12115                                 synstack->parenlevel--;
12116                         } else {
12117                                 if (pgetc_eatbnl() == ')') {
12118                                         c = CTLENDARI;
12119                                         synstack_pop(&synstack);
12120                                 } else {
12121                                         /*
12122                                          * unbalanced parens
12123                                          * (don't 2nd guess - no error)
12124                                          */
12125                                         pungetc();
12126                                 }
12127                         }
12128                         USTPUTC(c, out);
12129                         break;
12130 #endif
12131                 case CBQUOTE:   /* '`' */
12132                         if (checkkwd & CHKEOFMARK) {
12133                                 quotef = 1;
12134                                 USTPUTC('`', out);
12135                                 break;
12136                         }
12137
12138                         PARSEBACKQOLD();
12139                         break;
12140                 case CENDFILE:
12141                         goto endword;           /* exit outer loop */
12142                 case CIGN:
12143                         break;
12144                 default:
12145                         if (synstack->varnest == 0) {
12146 #if BASH_REDIR_OUTPUT
12147                                 if (c == '&') {
12148 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
12149                                         if (pgetc() == '>')
12150                                                 c = 0x100 + '>'; /* flag &> */
12151                                         pungetc();
12152                                 }
12153 #endif
12154                                 goto endword;   /* exit outer loop */
12155                         }
12156                         IF_ASH_ALIAS(if (c != PEOA))
12157                                 USTPUTC(c, out);
12158                 }
12159                 c = pgetc();
12160         } /* for (;;) */
12161  endword:
12162
12163 #if ENABLE_FEATURE_SH_MATH
12164         if (synstack->syntax == ARISYNTAX)
12165                 raise_error_syntax("missing '))'");
12166 #endif
12167         if (synstack->syntax != BASESYNTAX && eofmark == NULL)
12168                 raise_error_syntax("unterminated quoted string");
12169         if (synstack->varnest != 0) {
12170                 /* { */
12171                 raise_error_syntax("missing '}'");
12172         }
12173         USTPUTC('\0', out);
12174         len = out - (char *)stackblock();
12175         out = stackblock();
12176         if (eofmark == NULL) {
12177                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
12178                  && quotef == 0
12179                 ) {
12180                         if (isdigit_str9(out)) {
12181                                 PARSEREDIR(); /* passed as params: out, c */
12182                                 lasttoken = TREDIR;
12183                                 return lasttoken;
12184                         }
12185                         /* else: non-number X seen, interpret it
12186                          * as "NNNX>file" = "NNNX >file" */
12187                 }
12188                 pungetc();
12189         }
12190         quoteflag = quotef;
12191         backquotelist = bqlist;
12192         grabstackblock(len);
12193         wordtext = out;
12194         lasttoken = TWORD;
12195         return lasttoken;
12196 /* end of readtoken routine */
12197
12198 /*
12199  * Check to see whether we are at the end of the here document.  When this
12200  * is called, c is set to the first character of the next input line.  If
12201  * we are at the end of the here document, this routine sets the c to PEOF.
12202  */
12203 checkend: {
12204         if (realeofmark(eofmark)) {
12205                 int markloc;
12206                 char *p;
12207
12208 #if ENABLE_ASH_ALIAS
12209                 if (c == PEOA)
12210                         c = pgetc_without_PEOA();
12211 #endif
12212                 if (striptabs) {
12213                         while (c == '\t') {
12214                                 c = pgetc_without_PEOA();
12215                         }
12216                 }
12217
12218                 markloc = out - (char *)stackblock();
12219                 for (p = eofmark; STPUTC(c, out), *p; p++) {
12220                         if (c != *p)
12221                                 goto more_heredoc;
12222
12223                         c = pgetc_without_PEOA();
12224                 }
12225
12226                 if (c == '\n' || c == PEOF) {
12227                         c = PEOF;
12228                         g_parsefile->linno++;
12229                         needprompt = doprompt;
12230                 } else {
12231                         int len_here;
12232
12233  more_heredoc:
12234                         p = (char *)stackblock() + markloc + 1;
12235                         len_here = out - p;
12236
12237                         if (len_here) {
12238                                 len_here -= (c >= PEOF);
12239                                 c = p[-1];
12240
12241                                 if (len_here) {
12242                                         char *str;
12243
12244                                         str = alloca(len_here + 1);
12245                                         *(char *)mempcpy(str, p, len_here) = '\0';
12246
12247                                         pushstring(str, NULL);
12248                                 }
12249                         }
12250                 }
12251
12252                 STADJUST((char *)stackblock() + markloc - out, out);
12253         }
12254         goto checkend_return;
12255 }
12256
12257 /*
12258  * Parse a redirection operator.  The variable "out" points to a string
12259  * specifying the fd to be redirected.  The variable "c" contains the
12260  * first character of the redirection operator.
12261  */
12262 parseredir: {
12263         /* out is already checked to be a valid number or "" */
12264         int fd = (*out == '\0' ? -1 : atoi(out));
12265         union node *np;
12266
12267         np = stzalloc(sizeof(struct nfile));
12268         if (c == '>') {
12269                 np->nfile.fd = 1;
12270                 c = pgetc_eatbnl();
12271                 if (c == '>')
12272                         np->type = NAPPEND;
12273                 else if (c == '|')
12274                         np->type = NCLOBBER;
12275                 else if (c == '&')
12276                         np->type = NTOFD;
12277                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12278                 else {
12279                         np->type = NTO;
12280                         pungetc();
12281                 }
12282         }
12283 #if BASH_REDIR_OUTPUT
12284         else if (c == 0x100 + '>') { /* this flags &> redirection */
12285                 np->nfile.fd = 1;
12286                 pgetc(); /* this is '>', no need to check */
12287                 np->type = NTO2;
12288         }
12289 #endif
12290         else { /* c == '<' */
12291                 /*np->nfile.fd = 0; - stzalloc did it */
12292                 c = pgetc_eatbnl();
12293                 switch (c) {
12294                 case '<':
12295                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12296                                 np = stzalloc(sizeof(struct nhere));
12297                                 /*np->nfile.fd = 0; - stzalloc did it */
12298                         }
12299                         np->type = NHERE;
12300                         heredoc = stzalloc(sizeof(struct heredoc));
12301                         heredoc->here = np;
12302                         c = pgetc_eatbnl();
12303                         if (c == '-') {
12304                                 heredoc->striptabs = 1;
12305                         } else {
12306                                 /*heredoc->striptabs = 0; - stzalloc did it */
12307                                 pungetc();
12308                         }
12309                         break;
12310
12311                 case '&':
12312                         np->type = NFROMFD;
12313                         break;
12314
12315                 case '>':
12316                         np->type = NFROMTO;
12317                         break;
12318
12319                 default:
12320                         np->type = NFROM;
12321                         pungetc();
12322                         break;
12323                 }
12324         }
12325         if (fd >= 0)
12326                 np->nfile.fd = fd;
12327         redirnode = np;
12328         goto parseredir_return;
12329 }
12330
12331 /*
12332  * Parse a substitution.  At this point, we have read the dollar sign
12333  * and nothing else.
12334  */
12335
12336 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12337  * (assuming ascii char codes, as the original implementation did) */
12338 #define is_special(c) \
12339         (((unsigned)(c) - 33 < 32) \
12340                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12341 parsesub: {
12342         unsigned char subtype;
12343         int typeloc;
12344
12345         c = pgetc_eatbnl();
12346         if ((checkkwd & CHKEOFMARK)
12347          || c > 255 /* PEOA or PEOF */
12348          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12349         ) {
12350 #if BASH_DOLLAR_SQUOTE
12351                 if (synstack->syntax != DQSYNTAX && c == '\'')
12352                         bash_dollar_squote = 1;
12353                 else
12354 #endif
12355                         USTPUTC('$', out);
12356                 pungetc();
12357         } else if (c == '(') {
12358                 /* $(command) or $((arith)) */
12359                 if (pgetc_eatbnl() == '(') {
12360 #if ENABLE_FEATURE_SH_MATH
12361                         PARSEARITH();
12362 #else
12363                         raise_error_syntax("support for $((arith)) is disabled");
12364 #endif
12365                 } else {
12366                         pungetc();
12367                         PARSEBACKQNEW();
12368                 }
12369         } else {
12370                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12371                 smalluint newsyn = synstack->syntax;
12372
12373                 USTPUTC(CTLVAR, out);
12374                 typeloc = out - (char *)stackblock();
12375                 STADJUST(1, out);
12376                 subtype = VSNORMAL;
12377                 if (c == '{') {
12378                         c = pgetc_eatbnl();
12379                         subtype = 0;
12380                 }
12381  varname:
12382                 if (is_name(c)) {
12383                         /* $[{[#]]NAME[}] */
12384                         do {
12385                                 STPUTC(c, out);
12386                                 c = pgetc_eatbnl();
12387                         } while (is_in_name(c));
12388                 } else if (isdigit(c)) {
12389                         /* $[{[#]]NUM[}] */
12390                         do {
12391                                 STPUTC(c, out);
12392                                 c = pgetc_eatbnl();
12393                         } while (isdigit(c));
12394                 } else {
12395                         /* $[{[#]]<specialchar>[}] */
12396                         int cc = c;
12397
12398                         c = pgetc_eatbnl();
12399                         if (!subtype && cc == '#') {
12400                                 subtype = VSLENGTH;
12401                                 if (c == '_' || isalnum(c))
12402                                         goto varname;
12403                                 cc = c;
12404                                 c = pgetc_eatbnl();
12405                                 if (cc == '}' || c != '}') {
12406                                         pungetc();
12407                                         subtype = 0;
12408                                         c = cc;
12409                                         cc = '#';
12410                                 }
12411                         }
12412
12413                         if (!is_special(cc)) {
12414                                 if (subtype == VSLENGTH)
12415                                         subtype = 0;
12416                                 goto badsub;
12417                         }
12418
12419                         USTPUTC(cc, out);
12420                 }
12421
12422                 if (c != '}' && subtype == VSLENGTH) {
12423                         /* ${#VAR didn't end with } */
12424                         goto badsub;
12425                 }
12426
12427                 if (subtype == 0) {
12428                         static const char types[] ALIGN1 = "}-+?=";
12429                         /* ${VAR...} but not $VAR or ${#VAR} */
12430                         /* c == first char after VAR */
12431                         int cc = c;
12432
12433                         switch (c) {
12434                         case ':':
12435                                 c = pgetc_eatbnl();
12436 #if BASH_SUBSTR
12437                                 /* This check is only needed to not misinterpret
12438                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12439                                  * constructs.
12440                                  */
12441                                 if (!strchr(types, c)) {
12442                                         subtype = VSSUBSTR;
12443                                         pungetc();
12444                                         break; /* "goto badsub" is bigger (!) */
12445                                 }
12446 #endif
12447                                 subtype = VSNUL;
12448                                 /*FALLTHROUGH*/
12449                         default: {
12450                                 const char *p = strchr(types, c);
12451                                 if (p == NULL)
12452                                         break;
12453                                 subtype |= p - types + VSNORMAL;
12454                                 break;
12455                         }
12456                         case '%':
12457                         case '#':
12458                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12459                                 c = pgetc_eatbnl();
12460                                 if (c == cc)
12461                                         subtype++;
12462                                 else
12463                                         pungetc();
12464
12465                                 newsyn = BASESYNTAX;
12466                                 break;
12467 #if BASH_PATTERN_SUBST
12468                         case '/':
12469                                 /* ${v/[/]pattern/repl} */
12470 //TODO: encode pattern and repl separately.
12471 // Currently cases like: v=1;echo ${v/$((1/1))/ONE}
12472 // are broken (should print "ONE")
12473                                 subtype = VSREPLACE;
12474                                 newsyn = BASESYNTAX;
12475                                 c = pgetc_eatbnl();
12476                                 if (c != '/')
12477                                         goto badsub;
12478                                 subtype++; /* VSREPLACEALL */
12479                                 break;
12480 #endif
12481                         }
12482                 } else {
12483  badsub:
12484                         pungetc();
12485                 }
12486
12487                 if (newsyn == ARISYNTAX)
12488                         newsyn = DQSYNTAX;
12489
12490                 if ((newsyn != synstack->syntax || synstack->innerdq)
12491                  && subtype != VSNORMAL
12492                 ) {
12493                         synstack_push(&synstack,
12494                                 synstack->prev ?: alloca(sizeof(*synstack)),
12495                                 newsyn);
12496
12497                         synstack->varpushed = 1;
12498                         synstack->dblquote = newsyn != BASESYNTAX;
12499                 }
12500
12501                 ((unsigned char *)stackblock())[typeloc] = subtype;
12502                 if (subtype != VSNORMAL) {
12503                         synstack->varnest++;
12504                         if (synstack->dblquote)
12505                                 synstack->dqvarnest++;
12506                 }
12507                 STPUTC('=', out);
12508         }
12509         goto parsesub_return;
12510 }
12511
12512 /*
12513  * Called to parse command substitutions.  Newstyle is set if the command
12514  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12515  * list of commands (passed by reference), and savelen is the number of
12516  * characters on the top of the stack which must be preserved.
12517  */
12518 parsebackq: {
12519         struct nodelist **nlpp;
12520         union node *n;
12521         char *str;
12522         size_t savelen;
12523         smallint saveprompt = 0;
12524
12525         str = NULL;
12526         savelen = out - (char *)stackblock();
12527         if (savelen > 0) {
12528                 /*
12529                  * FIXME: this can allocate very large block on stack and SEGV.
12530                  * Example:
12531                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12532                  * allocates 100kb for every command subst. With about
12533                  * a hundred command substitutions stack overflows.
12534                  * With larger prepended string, SEGV happens sooner.
12535                  */
12536                 str = alloca(savelen);
12537                 memcpy(str, stackblock(), savelen);
12538         }
12539
12540         if (oldstyle) {
12541                 /* We must read until the closing backquote, giving special
12542                  * treatment to some slashes, and then push the string and
12543                  * reread it as input, interpreting it normally.
12544                  */
12545                 char *pout;
12546                 size_t psavelen;
12547                 char *pstr;
12548
12549                 STARTSTACKSTR(pout);
12550                 for (;;) {
12551                         int pc;
12552
12553                         setprompt_if(needprompt, 2);
12554                         pc = pgetc_eatbnl();
12555                         switch (pc) {
12556                         case '`':
12557                                 goto done;
12558
12559                         case '\\':
12560                                 pc = pgetc(); /* or pgetc_eatbnl()? why (example)? */
12561                                 if (pc != '\\' && pc != '`' && pc != '$'
12562                                  && (!synstack->dblquote || pc != '"')
12563                                 ) {
12564                                         STPUTC('\\', pout);
12565                                 }
12566                                 if (pc <= 255 /* not PEOA or PEOF */) {
12567                                         break;
12568                                 }
12569                                 /* fall through */
12570
12571                         case PEOF:
12572                         IF_ASH_ALIAS(case PEOA:)
12573                                 raise_error_syntax("EOF in backquote substitution");
12574
12575                         case '\n':
12576                                 nlnoprompt();
12577                                 break;
12578
12579                         default:
12580                                 break;
12581                         }
12582                         STPUTC(pc, pout);
12583                 }
12584  done:
12585                 STPUTC('\0', pout);
12586                 psavelen = pout - (char *)stackblock();
12587                 if (psavelen > 0) {
12588                         pstr = grabstackstr(pout);
12589                         setinputstring(pstr);
12590                 }
12591         }
12592         nlpp = &bqlist;
12593         while (*nlpp)
12594                 nlpp = &(*nlpp)->next;
12595         *nlpp = stzalloc(sizeof(**nlpp));
12596         /* (*nlpp)->next = NULL; - stzalloc did it */
12597
12598         if (oldstyle) {
12599                 saveprompt = doprompt;
12600                 doprompt = 0;
12601         }
12602
12603         n = list(2);
12604
12605         if (oldstyle)
12606                 doprompt = saveprompt;
12607         else if (readtoken() != TRP)
12608                 raise_error_unexpected_syntax(TRP);
12609
12610         (*nlpp)->n = n;
12611         if (oldstyle) {
12612                 /*
12613                  * Start reading from old file again, ignoring any pushed back
12614                  * tokens left from the backquote parsing
12615                  */
12616                 popfile();
12617                 tokpushback = 0;
12618         }
12619         while (stackblocksize() <= savelen)
12620                 growstackblock();
12621         STARTSTACKSTR(out);
12622         if (str) {
12623                 memcpy(out, str, savelen);
12624                 STADJUST(savelen, out);
12625         }
12626         USTPUTC(CTLBACKQ, out);
12627         if (oldstyle)
12628                 goto parsebackq_oldreturn;
12629         goto parsebackq_newreturn;
12630 }
12631
12632 #if ENABLE_FEATURE_SH_MATH
12633 /*
12634  * Parse an arithmetic expansion (indicate start of one and set state)
12635  */
12636 parsearith: {
12637
12638         synstack_push(&synstack,
12639                         synstack->prev ?: alloca(sizeof(*synstack)),
12640                         ARISYNTAX);
12641         synstack->dblquote = 1;
12642         USTPUTC(CTLARI, out);
12643         goto parsearith_return;
12644 }
12645 #endif
12646 } /* end of readtoken */
12647
12648 /*
12649  * Read the next input token.
12650  * If the token is a word, we set backquotelist to the list of cmds in
12651  *      backquotes.  We set quoteflag to true if any part of the word was
12652  *      quoted.
12653  * If the token is TREDIR, then we set redirnode to a structure containing
12654  *      the redirection.
12655  *
12656  * [Change comment:  here documents and internal procedures]
12657  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12658  *  word parsing code into a separate routine.  In this case, readtoken
12659  *  doesn't need to have any internal procedures, but parseword does.
12660  *  We could also make parseoperator in essence the main routine, and
12661  *  have parseword (readtoken1?) handle both words and redirection.]
12662  */
12663 #define NEW_xxreadtoken
12664 #ifdef NEW_xxreadtoken
12665 /* singles must be first! */
12666 static const char xxreadtoken_chars[7] ALIGN1 = {
12667         '\n', '(', ')', /* singles */
12668         '&', '|', ';',  /* doubles */
12669         0
12670 };
12671
12672 #define xxreadtoken_singles 3
12673 #define xxreadtoken_doubles 3
12674
12675 static const char xxreadtoken_tokens[] ALIGN1 = {
12676         TNL, TLP, TRP,          /* only single occurrence allowed */
12677         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12678         TEOF,                   /* corresponds to trailing nul */
12679         TAND, TOR, TENDCASE     /* if double occurrence */
12680 };
12681
12682 static int
12683 xxreadtoken(void)
12684 {
12685         int c;
12686
12687         if (tokpushback) {
12688                 tokpushback = 0;
12689                 return lasttoken;
12690         }
12691         setprompt_if(needprompt, 2);
12692         for (;;) {                      /* until token or start of word found */
12693                 c = pgetc_eatbnl();
12694                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12695                         continue;
12696
12697                 if (c == '#') {
12698                         while ((c = pgetc()) != '\n' && c != PEOF)
12699                                 continue;
12700                         pungetc();
12701                 } else if (c == '\\') {
12702                         break; /* return readtoken1(...) */
12703                 } else {
12704                         const char *p;
12705
12706                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12707                         if (c != PEOF) {
12708                                 if (c == '\n') {
12709                                         nlnoprompt();
12710                                 }
12711
12712                                 p = strchr(xxreadtoken_chars, c);
12713                                 if (p == NULL)
12714                                         break; /* return readtoken1(...) */
12715
12716                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12717                                         int cc = pgetc_eatbnl();
12718                                         if (cc == c) {    /* double occurrence? */
12719                                                 p += xxreadtoken_doubles + 1;
12720                                         } else {
12721                                                 pungetc();
12722 #if BASH_REDIR_OUTPUT
12723                                                 if (c == '&' && cc == '>') /* &> */
12724                                                         break; /* return readtoken1(...) */
12725 #endif
12726                                         }
12727                                 }
12728                         }
12729                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12730                         return lasttoken;
12731                 }
12732         } /* for (;;) */
12733
12734         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12735 }
12736 #else /* old xxreadtoken */
12737 #define RETURN(token)   return lasttoken = token
12738 static int
12739 xxreadtoken(void)
12740 {
12741         int c;
12742
12743         if (tokpushback) {
12744                 tokpushback = 0;
12745                 return lasttoken;
12746         }
12747         setprompt_if(needprompt, 2);
12748         for (;;) {      /* until token or start of word found */
12749                 c = pgetc_eatbnl();
12750                 switch (c) {
12751                 case ' ': case '\t':
12752                 IF_ASH_ALIAS(case PEOA:)
12753                         continue;
12754                 case '#':
12755                         while ((c = pgetc()) != '\n' && c != PEOF)
12756                                 continue;
12757                         pungetc();
12758                         continue;
12759                 case '\n':
12760                         nlnoprompt();
12761                         RETURN(TNL);
12762                 case PEOF:
12763                         RETURN(TEOF);
12764                 case '&':
12765                         if (pgetc_eatbnl() == '&')
12766                                 RETURN(TAND);
12767                         pungetc();
12768                         RETURN(TBACKGND);
12769                 case '|':
12770                         if (pgetc_eatbnl() == '|')
12771                                 RETURN(TOR);
12772                         pungetc();
12773                         RETURN(TPIPE);
12774                 case ';':
12775                         if (pgetc_eatbnl() == ';')
12776                                 RETURN(TENDCASE);
12777                         pungetc();
12778                         RETURN(TSEMI);
12779                 case '(':
12780                         RETURN(TLP);
12781                 case ')':
12782                         RETURN(TRP);
12783                 }
12784                 break;
12785         }
12786         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12787 #undef RETURN
12788 }
12789 #endif /* old xxreadtoken */
12790
12791 static int
12792 readtoken(void)
12793 {
12794         int t;
12795         int kwd = checkkwd;
12796 #if DEBUG
12797         smallint alreadyseen = tokpushback;
12798 #endif
12799
12800 #if ENABLE_ASH_ALIAS
12801  top:
12802 #endif
12803
12804         t = xxreadtoken();
12805
12806         /*
12807          * eat newlines
12808          */
12809         if (kwd & CHKNL) {
12810                 while (t == TNL) {
12811                         parseheredoc();
12812                         t = xxreadtoken();
12813                 }
12814         }
12815
12816         if (t != TWORD || quoteflag) {
12817                 goto out;
12818         }
12819
12820         /*
12821          * check for keywords
12822          */
12823         if (kwd & CHKKWD) {
12824                 const char *const *pp;
12825
12826                 pp = findkwd(wordtext);
12827                 if (pp) {
12828                         lasttoken = t = pp - tokname_array;
12829                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12830                         goto out;
12831                 }
12832         }
12833
12834         if (checkkwd & CHKALIAS) {
12835 #if ENABLE_ASH_ALIAS
12836                 struct alias *ap;
12837                 ap = lookupalias(wordtext, 1);
12838                 if (ap != NULL) {
12839                         if (*ap->val) {
12840                                 pushstring(ap->val, ap);
12841                         }
12842                         goto top;
12843                 }
12844 #endif
12845         }
12846  out:
12847         checkkwd = 0;
12848 #if DEBUG
12849         if (!alreadyseen)
12850                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12851         else
12852                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12853 #endif
12854         return t;
12855 }
12856
12857 static int
12858 peektoken(void)
12859 {
12860         int t;
12861
12862         t = readtoken();
12863         tokpushback = 1;
12864         return t;
12865 }
12866
12867 /*
12868  * Read and parse a command.  Returns NODE_EOF on end of file.
12869  * (NULL is a valid parse tree indicating a blank line.)
12870  */
12871 static union node *
12872 parsecmd(int interact)
12873 {
12874         tokpushback = 0;
12875         checkkwd = 0;
12876         heredoclist = 0;
12877         doprompt = interact;
12878         setprompt_if(doprompt, doprompt);
12879         needprompt = 0;
12880         return list(1);
12881 }
12882
12883 /*
12884  * Input any here documents.
12885  */
12886 static void
12887 parseheredoc(void)
12888 {
12889         struct heredoc *here;
12890         union node *n;
12891
12892         here = heredoclist;
12893         heredoclist = NULL;
12894
12895         while (here) {
12896                 setprompt_if(needprompt, 2);
12897                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12898                                 here->eofmark, here->striptabs);
12899                 n = stzalloc(sizeof(struct narg));
12900                 n->narg.type = NARG;
12901                 /*n->narg.next = NULL; - stzalloc did it */
12902                 n->narg.text = wordtext;
12903                 n->narg.backquote = backquotelist;
12904                 here->here->nhere.doc = n;
12905                 here = here->next;
12906         }
12907 }
12908
12909
12910 static const char *
12911 expandstr(const char *ps, int syntax_type)
12912 {
12913         union node n;
12914         int saveprompt;
12915
12916         /* XXX Fix (char *) cast. */
12917         setinputstring((char *)ps);
12918
12919         saveprompt = doprompt;
12920         doprompt = 0;
12921
12922         /* readtoken1() might die horribly.
12923          * Try a prompt with syntactically wrong command:
12924          * PS1='$(date "+%H:%M:%S) > '
12925          */
12926         {
12927                 volatile int saveint;
12928                 struct jmploc *volatile savehandler = exception_handler;
12929                 struct jmploc jmploc;
12930                 SAVE_INT(saveint);
12931                 if (setjmp(jmploc.loc) == 0) {
12932                         exception_handler = &jmploc;
12933                         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12934                 }
12935                 exception_handler = savehandler;
12936                 RESTORE_INT(saveint);
12937         }
12938
12939         doprompt = saveprompt;
12940
12941         popfile();
12942
12943         n.narg.type = NARG;
12944         n.narg.next = NULL;
12945         n.narg.text = wordtext;
12946         n.narg.backquote = backquotelist;
12947
12948         expandarg(&n, NULL, EXP_QUOTED);
12949         return stackblock();
12950 }
12951
12952 static inline int
12953 parser_eof(void)
12954 {
12955         return tokpushback && lasttoken == TEOF;
12956 }
12957
12958 /*
12959  * Execute a command or commands contained in a string.
12960  */
12961 static int
12962 evalstring(char *s, int flags)
12963 {
12964         struct jmploc *volatile savehandler;
12965         struct jmploc jmploc;
12966         int ex;
12967
12968         union node *n;
12969         struct stackmark smark;
12970         int status;
12971
12972         s = sstrdup(s);
12973         setinputstring(s);
12974         setstackmark(&smark);
12975
12976         status = 0;
12977         /* On exception inside execution loop, we must popfile().
12978          * Try interactively:
12979          *      readonly a=a
12980          *      command eval "a=b"  # throws "is read only" error
12981          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12982          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12983          */
12984         savehandler = exception_handler;
12985         ex = setjmp(jmploc.loc);
12986         if (ex)
12987                 goto out;
12988         exception_handler = &jmploc;
12989
12990         while ((n = parsecmd(0)) != NODE_EOF) {
12991                 int i;
12992
12993                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12994                 if (n)
12995                         status = i;
12996                 popstackmark(&smark);
12997                 if (evalskip)
12998                         break;
12999         }
13000  out:
13001         popstackmark(&smark);
13002         popfile();
13003         stunalloc(s);
13004
13005         exception_handler = savehandler;
13006         if (ex)
13007                 longjmp(exception_handler->loc, ex);
13008
13009         return status;
13010 }
13011
13012 /*
13013  * The eval command.
13014  */
13015 static int FAST_FUNC
13016 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
13017 {
13018         char *p;
13019         char *concat;
13020
13021         if (argv[1]) {
13022                 p = argv[1];
13023                 argv += 2;
13024                 if (argv[0]) {
13025                         STARTSTACKSTR(concat);
13026                         for (;;) {
13027                                 concat = stack_putstr(p, concat);
13028                                 p = *argv++;
13029                                 if (p == NULL)
13030                                         break;
13031                                 STPUTC(' ', concat);
13032                         }
13033                         STPUTC('\0', concat);
13034                         p = grabstackstr(concat);
13035                 }
13036                 return evalstring(p, flags & EV_TESTED);
13037         }
13038         return 0;
13039 }
13040
13041 /*
13042  * Read and execute commands.
13043  * "Top" is nonzero for the top level command loop;
13044  * it turns on prompting if the shell is interactive.
13045  */
13046 static int
13047 cmdloop(int top)
13048 {
13049         union node *n;
13050         struct stackmark smark;
13051         int inter;
13052         int status = 0;
13053         int numeof = 0;
13054
13055         TRACE(("cmdloop(%d) called\n", top));
13056         for (;;) {
13057                 int skip;
13058
13059                 setstackmark(&smark);
13060 #if JOBS
13061                 if (doing_jobctl)
13062                         showjobs(SHOW_CHANGED|SHOW_STDERR);
13063 #endif
13064                 inter = 0;
13065                 if (iflag && top) {
13066                         inter++;
13067                         chkmail();
13068                 }
13069                 n = parsecmd(inter);
13070 #if DEBUG
13071                 if (DEBUG > 2 && debug && (n != NODE_EOF))
13072                         showtree(n);
13073 #endif
13074                 if (n == NODE_EOF) {
13075                         if (!top || numeof >= 50)
13076                                 break;
13077                         if (!stoppedjobs()) {
13078                                 if (!Iflag)
13079                                         break;
13080                                 out2str("\nUse \"exit\" to leave shell.\n");
13081                         }
13082                         numeof++;
13083                 } else if (nflag == 0) {
13084                         int i;
13085
13086                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
13087                         job_warning >>= 1;
13088                         numeof = 0;
13089                         i = evaltree(n, 0);
13090                         if (n)
13091                                 status = i;
13092                 }
13093                 popstackmark(&smark);
13094                 skip = evalskip;
13095
13096                 if (skip) {
13097                         evalskip &= ~SKIPFUNC;
13098                         break;
13099                 }
13100         }
13101         return status;
13102 }
13103
13104 /*
13105  * Take commands from a file.  To be compatible we should do a path
13106  * search for the file, which is necessary to find sub-commands.
13107  */
13108 static char *
13109 find_dot_file(char *name)
13110 {
13111         char *fullname;
13112         const char *path = pathval();
13113         struct stat statb;
13114
13115         /* don't try this for absolute or relative paths */
13116         if (strchr(name, '/'))
13117                 return name;
13118
13119         while ((fullname = path_advance(&path, name)) != NULL) {
13120                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
13121                         /*
13122                          * Don't bother freeing here, since it will
13123                          * be freed by the caller.
13124                          */
13125                         return fullname;
13126                 }
13127                 if (fullname != name)
13128                         stunalloc(fullname);
13129         }
13130         /* not found in PATH */
13131
13132 #if ENABLE_ASH_BASH_SOURCE_CURDIR
13133         return name;
13134 #else
13135         ash_msg_and_raise_error("%s: not found", name);
13136         /* NOTREACHED */
13137 #endif
13138 }
13139
13140 static int FAST_FUNC
13141 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
13142 {
13143         /* "false; . empty_file; echo $?" should print 0, not 1: */
13144         int status = 0;
13145         char *fullname;
13146         char **argv;
13147         char *args_need_save;
13148         volatile struct shparam saveparam;
13149
13150 //???
13151 //      struct strlist *sp;
13152 //      for (sp = cmdenviron; sp; sp = sp->next)
13153 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
13154
13155         nextopt(nullstr); /* handle possible "--" */
13156         argv = argptr;
13157
13158         if (!argv[0]) {
13159                 /* bash says: "bash: .: filename argument required" */
13160                 return 2; /* bash compat */
13161         }
13162
13163         /* This aborts if file isn't found, which is POSIXly correct.
13164          * bash returns exitcode 1 instead.
13165          */
13166         fullname = find_dot_file(argv[0]);
13167         argv++;
13168         args_need_save = argv[0];
13169         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
13170                 int argc;
13171                 saveparam = shellparam;
13172                 shellparam.malloced = 0;
13173                 argc = 1;
13174                 while (argv[argc])
13175                         argc++;
13176                 shellparam.nparam = argc;
13177                 shellparam.p = argv;
13178         };
13179
13180         /* This aborts if file can't be opened, which is POSIXly correct.
13181          * bash returns exitcode 1 instead.
13182          */
13183         setinputfile(fullname, INPUT_PUSH_FILE);
13184         commandname = fullname;
13185         status = cmdloop(0);
13186         popfile();
13187
13188         if (args_need_save) {
13189                 freeparam(&shellparam);
13190                 shellparam = saveparam;
13191         };
13192
13193         return status;
13194 }
13195
13196 static int FAST_FUNC
13197 exitcmd(int argc UNUSED_PARAM, char **argv)
13198 {
13199         if (stoppedjobs())
13200                 return 0;
13201         if (argv[1])
13202                 exitstatus = number(argv[1]);
13203         raise_exception(EXEXIT);
13204         /* NOTREACHED */
13205 }
13206
13207 /*
13208  * Read a file containing shell functions.
13209  */
13210 static void
13211 readcmdfile(char *name)
13212 {
13213         setinputfile(name, INPUT_PUSH_FILE);
13214         cmdloop(0);
13215         popfile();
13216 }
13217
13218
13219 /* ============ find_command inplementation */
13220
13221 /*
13222  * Resolve a command name.  If you change this routine, you may have to
13223  * change the shellexec routine as well.
13224  */
13225 static void
13226 find_command(char *name, struct cmdentry *entry, int act, const char *path)
13227 {
13228         struct tblentry *cmdp;
13229         int idx;
13230         int prev;
13231         char *fullname;
13232         struct stat statb;
13233         int e;
13234         int updatetbl;
13235         struct builtincmd *bcmd;
13236
13237         /* If name contains a slash, don't use PATH or hash table */
13238         if (strchr(name, '/') != NULL) {
13239                 entry->u.index = -1;
13240                 if (act & DO_ABS) {
13241                         while (stat(name, &statb) < 0) {
13242 #ifdef SYSV
13243                                 if (errno == EINTR)
13244                                         continue;
13245 #endif
13246                                 entry->cmdtype = CMDUNKNOWN;
13247                                 return;
13248                         }
13249                 }
13250                 entry->cmdtype = CMDNORMAL;
13251                 return;
13252         }
13253
13254 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
13255
13256         updatetbl = (path == pathval());
13257         if (!updatetbl) {
13258                 act |= DO_ALTPATH;
13259                 if (strstr(path, "%builtin") != NULL)
13260                         act |= DO_ALTBLTIN;
13261         }
13262
13263         /* If name is in the table, check answer will be ok */
13264         cmdp = cmdlookup(name, 0);
13265         if (cmdp != NULL) {
13266                 int bit;
13267
13268                 switch (cmdp->cmdtype) {
13269                 default:
13270 #if DEBUG
13271                         abort();
13272 #endif
13273                 case CMDNORMAL:
13274                         bit = DO_ALTPATH;
13275                         break;
13276                 case CMDFUNCTION:
13277                         bit = DO_NOFUNC;
13278                         break;
13279                 case CMDBUILTIN:
13280                         bit = DO_ALTBLTIN;
13281                         break;
13282                 }
13283                 if (act & bit) {
13284                         updatetbl = 0;
13285                         cmdp = NULL;
13286                 } else if (cmdp->rehash == 0)
13287                         /* if not invalidated by cd, we're done */
13288                         goto success;
13289         }
13290
13291         /* If %builtin not in path, check for builtin next */
13292         bcmd = find_builtin(name);
13293         if (bcmd) {
13294                 if (IS_BUILTIN_REGULAR(bcmd))
13295                         goto builtin_success;
13296                 if (act & DO_ALTPATH) {
13297                         if (!(act & DO_ALTBLTIN))
13298                                 goto builtin_success;
13299                 } else if (builtinloc <= 0) {
13300                         goto builtin_success;
13301                 }
13302         }
13303
13304 #if ENABLE_FEATURE_SH_STANDALONE
13305         {
13306                 int applet_no = find_applet_by_name(name);
13307                 if (applet_no >= 0) {
13308                         entry->cmdtype = CMDNORMAL;
13309                         entry->u.index = -2 - applet_no;
13310                         return;
13311                 }
13312         }
13313 #endif
13314
13315         /* We have to search path. */
13316         prev = -1;              /* where to start */
13317         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13318                 if (cmdp->cmdtype == CMDBUILTIN)
13319                         prev = builtinloc;
13320                 else
13321                         prev = cmdp->param.index;
13322         }
13323
13324         e = ENOENT;
13325         idx = -1;
13326  loop:
13327         while ((fullname = path_advance(&path, name)) != NULL) {
13328                 stunalloc(fullname);
13329                 /* NB: code below will still use fullname
13330                  * despite it being "unallocated" */
13331                 idx++;
13332                 if (pathopt) {
13333                         if (prefix(pathopt, "builtin")) {
13334                                 if (bcmd)
13335                                         goto builtin_success;
13336                                 continue;
13337                         }
13338                         if ((act & DO_NOFUNC)
13339                          || !prefix(pathopt, "func")
13340                         ) {     /* ignore unimplemented options */
13341                                 continue;
13342                         }
13343                 }
13344                 /* if rehash, don't redo absolute path names */
13345                 if (fullname[0] == '/' && idx <= prev) {
13346                         if (idx < prev)
13347                                 continue;
13348                         TRACE(("searchexec \"%s\": no change\n", name));
13349                         goto success;
13350                 }
13351                 while (stat(fullname, &statb) < 0) {
13352 #ifdef SYSV
13353                         if (errno == EINTR)
13354                                 continue;
13355 #endif
13356                         if (errno != ENOENT && errno != ENOTDIR)
13357                                 e = errno;
13358                         goto loop;
13359                 }
13360                 e = EACCES;     /* if we fail, this will be the error */
13361                 if (!S_ISREG(statb.st_mode))
13362                         continue;
13363                 if (pathopt) {          /* this is a %func directory */
13364                         stalloc(strlen(fullname) + 1);
13365                         /* NB: stalloc will return space pointed by fullname
13366                          * (because we don't have any intervening allocations
13367                          * between stunalloc above and this stalloc) */
13368                         readcmdfile(fullname);
13369                         cmdp = cmdlookup(name, 0);
13370                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13371                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13372                         stunalloc(fullname);
13373                         goto success;
13374                 }
13375                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13376                 if (!updatetbl) {
13377                         entry->cmdtype = CMDNORMAL;
13378                         entry->u.index = idx;
13379                         return;
13380                 }
13381                 INT_OFF;
13382                 cmdp = cmdlookup(name, 1);
13383                 cmdp->cmdtype = CMDNORMAL;
13384                 cmdp->param.index = idx;
13385                 INT_ON;
13386                 goto success;
13387         }
13388
13389         /* We failed.  If there was an entry for this command, delete it */
13390         if (cmdp && updatetbl)
13391                 delete_cmd_entry();
13392         if (act & DO_ERR) {
13393 #if ENABLE_ASH_BASH_NOT_FOUND_HOOK
13394                 struct tblentry *hookp = cmdlookup("command_not_found_handle", 0);
13395                 if (hookp && hookp->cmdtype == CMDFUNCTION) {
13396                         char *argv[3];
13397                         argv[0] = (char*) "command_not_found_handle";
13398                         argv[1] = name;
13399                         argv[2] = NULL;
13400                         evalfun(hookp->param.func, 2, argv, 0);
13401                         entry->cmdtype = CMDUNKNOWN;
13402                         return;
13403                 }
13404 #endif
13405                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13406         }
13407         entry->cmdtype = CMDUNKNOWN;
13408         return;
13409
13410  builtin_success:
13411         if (!updatetbl) {
13412                 entry->cmdtype = CMDBUILTIN;
13413                 entry->u.cmd = bcmd;
13414                 return;
13415         }
13416         INT_OFF;
13417         cmdp = cmdlookup(name, 1);
13418         cmdp->cmdtype = CMDBUILTIN;
13419         cmdp->param.cmd = bcmd;
13420         INT_ON;
13421  success:
13422         cmdp->rehash = 0;
13423         entry->cmdtype = cmdp->cmdtype;
13424         entry->u = cmdp->param;
13425 }
13426
13427
13428 /*
13429  * The trap builtin.
13430  */
13431 static int FAST_FUNC
13432 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13433 {
13434         char *action;
13435         char **ap;
13436         int signo, exitcode;
13437
13438         nextopt(nullstr);
13439         ap = argptr;
13440         if (!*ap) {
13441                 for (signo = 0; signo < NSIG; signo++) {
13442                         char *tr = trap_ptr[signo];
13443                         if (tr) {
13444                                 /* note: bash adds "SIG", but only if invoked
13445                                  * as "bash". If called as "sh", or if set -o posix,
13446                                  * then it prints short signal names.
13447                                  * We are printing short names: */
13448                                 out1fmt("trap -- %s %s\n",
13449                                                 single_quote(tr),
13450                                                 get_signame(signo));
13451                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13452                  * In this case, we will exit very soon, no need to free(). */
13453                                 /* if (trap_ptr != trap && tp[0]) */
13454                                 /*      free(tr); */
13455                         }
13456                 }
13457                 /*
13458                 if (trap_ptr != trap) {
13459                         free(trap_ptr);
13460                         trap_ptr = trap;
13461                 }
13462                 */
13463                 return 0;
13464         }
13465
13466         /* Why the second check?
13467          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13468          * In this case, NUM is signal no, not an action.
13469          */
13470         action = NULL;
13471         if (ap[1] && !is_number(ap[0]))
13472                 action = *ap++;
13473
13474         exitcode = 0;
13475         while (*ap) {
13476                 signo = get_signum(*ap);
13477                 if (signo < 0) {
13478                         /* Mimic bash message exactly */
13479                         ash_msg("%s: invalid signal specification", *ap);
13480                         exitcode = 1;
13481                         goto next;
13482                 }
13483                 INT_OFF;
13484                 if (action) {
13485                         if (LONE_DASH(action))
13486                                 action = NULL;
13487                         else {
13488                                 if (action[0]) /* not NULL and not "" and not "-" */
13489                                         may_have_traps = 1;
13490                                 action = ckstrdup(action);
13491                         }
13492                 }
13493                 free(trap[signo]);
13494                 trap[signo] = action;
13495                 if (signo != 0)
13496                         setsignal(signo);
13497                 INT_ON;
13498  next:
13499                 ap++;
13500         }
13501         return exitcode;
13502 }
13503
13504
13505 /* ============ Builtins */
13506
13507 #if ENABLE_ASH_HELP
13508 static int FAST_FUNC
13509 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13510 {
13511         unsigned col;
13512         unsigned i;
13513
13514         out1fmt(
13515                 "Built-in commands:\n"
13516                 "------------------\n");
13517         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13518                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13519                                         builtintab[i].name + 1);
13520                 if (col > 60) {
13521                         out1fmt("\n");
13522                         col = 0;
13523                 }
13524         }
13525 # if ENABLE_FEATURE_SH_STANDALONE
13526         {
13527                 const char *a = applet_names;
13528                 while (*a) {
13529                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13530                         if (col > 60) {
13531                                 out1fmt("\n");
13532                                 col = 0;
13533                         }
13534                         while (*a++ != '\0')
13535                                 continue;
13536                 }
13537         }
13538 # endif
13539         newline_and_flush(stdout);
13540         return EXIT_SUCCESS;
13541 }
13542 #endif
13543
13544 #if MAX_HISTORY
13545 static int FAST_FUNC
13546 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13547 {
13548         show_history(line_input_state);
13549         return EXIT_SUCCESS;
13550 }
13551 #endif
13552
13553 /*
13554  * The export and readonly commands.
13555  */
13556 static int FAST_FUNC
13557 exportcmd(int argc UNUSED_PARAM, char **argv)
13558 {
13559         struct var *vp;
13560         char *name;
13561         const char *p;
13562         char **aptr;
13563         char opt;
13564         int flag;
13565         int flag_off;
13566
13567         /* "readonly" in bash accepts, but ignores -n.
13568          * We do the same: it saves a conditional in nextopt's param.
13569          */
13570         flag_off = 0;
13571         while ((opt = nextopt("np")) != '\0') {
13572                 if (opt == 'n')
13573                         flag_off = VEXPORT;
13574         }
13575         flag = VEXPORT;
13576         if (argv[0][0] == 'r') {
13577                 flag = VREADONLY;
13578                 flag_off = 0; /* readonly ignores -n */
13579         }
13580         flag_off = ~flag_off;
13581
13582         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13583         {
13584                 aptr = argptr;
13585                 name = *aptr;
13586                 if (name) {
13587                         do {
13588                                 p = strchr(name, '=');
13589                                 if (p != NULL) {
13590                                         p++;
13591                                 } else {
13592                                         vp = *findvar(hashvar(name), name);
13593                                         if (vp) {
13594                                                 vp->flags = ((vp->flags | flag) & flag_off);
13595                                                 continue;
13596                                         }
13597                                 }
13598                                 setvar(name, p, (flag & flag_off));
13599                         } while ((name = *++aptr) != NULL);
13600                         return 0;
13601                 }
13602         }
13603
13604         /* No arguments. Show the list of exported or readonly vars.
13605          * -n is ignored.
13606          */
13607         showvars(argv[0], flag, 0);
13608         return 0;
13609 }
13610
13611 /*
13612  * Delete a function if it exists.
13613  */
13614 static void
13615 unsetfunc(const char *name)
13616 {
13617         struct tblentry *cmdp;
13618
13619         cmdp = cmdlookup(name, 0);
13620         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13621                 delete_cmd_entry();
13622 }
13623
13624 /*
13625  * The unset builtin command.  We unset the function before we unset the
13626  * variable to allow a function to be unset when there is a readonly variable
13627  * with the same name.
13628  */
13629 static int FAST_FUNC
13630 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13631 {
13632         char **ap;
13633         int i;
13634         int flag = 0;
13635
13636         while ((i = nextopt("vf")) != 0) {
13637                 flag = i;
13638         }
13639
13640         for (ap = argptr; *ap; ap++) {
13641                 if (flag != 'f') {
13642                         unsetvar(*ap);
13643                         continue;
13644                 }
13645                 if (flag != 'v')
13646                         unsetfunc(*ap);
13647         }
13648         return 0;
13649 }
13650
13651 static const unsigned char timescmd_str[] ALIGN1 = {
13652         ' ',  offsetof(struct tms, tms_utime),
13653         '\n', offsetof(struct tms, tms_stime),
13654         ' ',  offsetof(struct tms, tms_cutime),
13655         '\n', offsetof(struct tms, tms_cstime),
13656         0
13657 };
13658 static int FAST_FUNC
13659 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13660 {
13661         unsigned clk_tck;
13662         const unsigned char *p;
13663         struct tms buf;
13664
13665         clk_tck = bb_clk_tck();
13666
13667         times(&buf);
13668         p = timescmd_str;
13669         do {
13670                 unsigned sec, frac;
13671                 unsigned long t;
13672                 t = *(clock_t *)(((char *) &buf) + p[1]);
13673                 sec = t / clk_tck;
13674                 frac = t % clk_tck;
13675                 out1fmt("%um%u.%03us%c",
13676                         sec / 60, sec % 60,
13677                         (frac * 1000) / clk_tck,
13678                         p[0]);
13679                 p += 2;
13680         } while (*p);
13681
13682         return 0;
13683 }
13684
13685 #if ENABLE_FEATURE_SH_MATH
13686 /*
13687  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13688  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13689  *
13690  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13691  */
13692 static int FAST_FUNC
13693 letcmd(int argc UNUSED_PARAM, char **argv)
13694 {
13695         arith_t i;
13696
13697         argv++;
13698         if (!*argv)
13699                 ash_msg_and_raise_error("expression expected");
13700         do {
13701                 i = ash_arith(*argv);
13702         } while (*++argv);
13703
13704         return !i;
13705 }
13706 #endif
13707
13708 /*
13709  * The read builtin. Options:
13710  *      -r              Do not interpret '\' specially
13711  *      -s              Turn off echo (tty only)
13712  *      -n NCHARS       Read NCHARS max
13713  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13714  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13715  *      -u FD           Read from given FD instead of fd 0
13716  *      -d DELIM        End on DELIM char, not newline
13717  * This uses unbuffered input, which may be avoidable in some cases.
13718  * TODO: bash also has:
13719  *      -a ARRAY        Read into array[0],[1],etc
13720  *      -e              Use line editing (tty only)
13721  */
13722 static int FAST_FUNC
13723 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13724 {
13725         char *opt_n = NULL;
13726         char *opt_p = NULL;
13727         char *opt_t = NULL;
13728         char *opt_u = NULL;
13729         char *opt_d = NULL; /* optimized out if !BASH */
13730         int read_flags = 0;
13731         const char *r;
13732         int i;
13733
13734         while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
13735                 switch (i) {
13736                 case 'p':
13737                         opt_p = optionarg;
13738                         break;
13739                 case 'n':
13740                         opt_n = optionarg;
13741                         break;
13742                 case 's':
13743                         read_flags |= BUILTIN_READ_SILENT;
13744                         break;
13745                 case 't':
13746                         opt_t = optionarg;
13747                         break;
13748                 case 'r':
13749                         read_flags |= BUILTIN_READ_RAW;
13750                         break;
13751                 case 'u':
13752                         opt_u = optionarg;
13753                         break;
13754 #if BASH_READ_D
13755                 case 'd':
13756                         opt_d = optionarg;
13757                         break;
13758 #endif
13759                 default:
13760                         break;
13761                 }
13762         }
13763
13764         /* "read -s" needs to save/restore termios, can't allow ^C
13765          * to jump out of it.
13766          */
13767  again:
13768         INT_OFF;
13769         r = shell_builtin_read(setvar0,
13770                 argptr,
13771                 bltinlookup("IFS"), /* can be NULL */
13772                 read_flags,
13773                 opt_n,
13774                 opt_p,
13775                 opt_t,
13776                 opt_u,
13777                 opt_d
13778         );
13779         INT_ON;
13780
13781         if ((uintptr_t)r == 1 && errno == EINTR) {
13782                 /* To get SIGCHLD: sleep 1 & read x; echo $x
13783                  * Correct behavior is to not exit "read"
13784                  */
13785                 if (pending_sig == 0)
13786                         goto again;
13787         }
13788
13789         if ((uintptr_t)r > 1)
13790                 ash_msg_and_raise_error(r);
13791
13792         return (uintptr_t)r;
13793 }
13794
13795 static int FAST_FUNC
13796 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13797 {
13798         static const char permuser[3] ALIGN1 = "ogu";
13799
13800         mode_t mask;
13801         int symbolic_mode = 0;
13802
13803         while (nextopt("S") != '\0') {
13804                 symbolic_mode = 1;
13805         }
13806
13807         INT_OFF;
13808         mask = umask(0);
13809         umask(mask);
13810         INT_ON;
13811
13812         if (*argptr == NULL) {
13813                 if (symbolic_mode) {
13814                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13815                         char *p = buf;
13816                         int i;
13817
13818                         i = 2;
13819                         for (;;) {
13820                                 *p++ = ',';
13821                                 *p++ = permuser[i];
13822                                 *p++ = '=';
13823                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13824                                 if (!(mask & 0400)) *p++ = 'r';
13825                                 if (!(mask & 0200)) *p++ = 'w';
13826                                 if (!(mask & 0100)) *p++ = 'x';
13827                                 mask <<= 3;
13828                                 if (--i < 0)
13829                                         break;
13830                         }
13831                         *p = '\0';
13832                         puts(buf + 1);
13833                 } else {
13834                         out1fmt("%04o\n", mask);
13835                 }
13836         } else {
13837                 char *modestr = *argptr;
13838                 /* numeric umasks are taken as-is */
13839                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13840                 if (!isdigit(modestr[0]))
13841                         mask ^= 0777;
13842                 mask = bb_parse_mode(modestr, mask);
13843                 if ((unsigned)mask > 0777) {
13844                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13845                 }
13846                 if (!isdigit(modestr[0]))
13847                         mask ^= 0777;
13848                 umask(mask);
13849         }
13850         return 0;
13851 }
13852
13853 static int FAST_FUNC
13854 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13855 {
13856         return shell_builtin_ulimit(argv);
13857 }
13858
13859 /* ============ main() and helpers */
13860
13861 /*
13862  * Called to exit the shell.
13863  */
13864 static void
13865 exitshell(void)
13866 {
13867         struct jmploc loc;
13868         char *p;
13869         int status;
13870
13871 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13872         save_history(line_input_state);
13873 #endif
13874         status = exitstatus;
13875         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13876         if (setjmp(loc.loc)) {
13877                 if (exception_type == EXEXIT)
13878                         status = exitstatus;
13879                 goto out;
13880         }
13881         exception_handler = &loc;
13882         p = trap[0];
13883         if (p) {
13884                 trap[0] = NULL;
13885                 evalskip = 0;
13886                 evalstring(p, 0);
13887                 /*free(p); - we'll exit soon */
13888         }
13889  out:
13890         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13891          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13892          */
13893         setjobctl(0);
13894         flush_stdout_stderr();
13895         _exit(status);
13896         /* NOTREACHED */
13897 }
13898
13899 /* Don't inline: conserve stack of caller from having our locals too */
13900 static NOINLINE void
13901 init(void)
13902 {
13903         /* we will never free this */
13904         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13905         basepf.linno = 1;
13906
13907         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
13908         setsignal(SIGCHLD);
13909
13910         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13911          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13912          */
13913         signal(SIGHUP, SIG_DFL);
13914
13915         {
13916                 char **envp;
13917                 const char *p;
13918
13919                 initvar();
13920                 for (envp = environ; envp && *envp; envp++) {
13921 /* Used to have
13922  *                      p = endofname(*envp);
13923  *                      if (p != *envp && *p == '=') {
13924  * here to weed out badly-named variables, but this breaks
13925  * scenarios where people do want them passed to children:
13926  * import os
13927  * os.environ["test-test"]="test"
13928  * if os.fork() == 0:
13929  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
13930  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])  # breaks this
13931  */
13932                         if (strchr(*envp, '=')) {
13933                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13934                         }
13935                 }
13936
13937                 setvareq((char*)defoptindvar, VTEXTFIXED);
13938
13939                 setvar0("PPID", utoa(getppid()));
13940 #if BASH_SHLVL_VAR
13941                 p = lookupvar("SHLVL");
13942                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13943 #endif
13944 #if BASH_HOSTNAME_VAR
13945                 if (!lookupvar("HOSTNAME")) {
13946                         struct utsname uts;
13947                         uname(&uts);
13948                         setvar0("HOSTNAME", uts.nodename);
13949                 }
13950 #endif
13951                 p = lookupvar("PWD");
13952                 if (p) {
13953                         struct stat st1, st2;
13954                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13955                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13956                         ) {
13957                                 p = NULL;
13958                         }
13959                 }
13960                 setpwd(p, 0);
13961         }
13962 }
13963
13964
13965 //usage:#define ash_trivial_usage
13966 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS] / -s [ARGS]]"
13967 //usage:#define ash_full_usage "\n\n"
13968 //usage:        "Unix shell interpreter"
13969
13970 /*
13971  * Process the shell command line arguments.
13972  */
13973 static int
13974 procargs(char **argv)
13975 {
13976         int i;
13977         const char *xminusc;
13978         char **xargv;
13979         int login_sh;
13980
13981         xargv = argv;
13982         login_sh = xargv[0] && xargv[0][0] == '-';
13983         arg0 = xargv[0];
13984         /* if (xargv[0]) - mmm, this is always true! */
13985                 xargv++;
13986         for (i = 0; i < NOPTS; i++)
13987                 optlist[i] = 2;
13988         argptr = xargv;
13989         if (options(/*cmdline:*/ 1, &login_sh)) {
13990                 /* it already printed err message */
13991                 raise_exception(EXERROR);
13992         }
13993         xargv = argptr;
13994         xminusc = minusc;
13995         if (*xargv == NULL) {
13996                 if (xminusc)
13997                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13998                 sflag = 1;
13999         }
14000         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
14001                 iflag = 1;
14002         if (mflag == 2)
14003                 mflag = iflag;
14004         for (i = 0; i < NOPTS; i++)
14005                 if (optlist[i] == 2)
14006                         optlist[i] = 0;
14007 #if DEBUG == 2
14008         debug = 1;
14009 #endif
14010         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
14011         if (xminusc) {
14012                 minusc = *xargv++;
14013                 if (*xargv)
14014                         goto setarg0;
14015         } else if (!sflag) {
14016                 setinputfile(*xargv, 0);
14017  setarg0:
14018                 arg0 = *xargv++;
14019                 commandname = arg0;
14020         }
14021
14022         shellparam.p = xargv;
14023 #if ENABLE_ASH_GETOPTS
14024         shellparam.optind = 1;
14025         shellparam.optoff = -1;
14026 #endif
14027         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
14028         while (*xargv) {
14029                 shellparam.nparam++;
14030                 xargv++;
14031         }
14032         optschanged();
14033
14034         return login_sh;
14035 }
14036
14037 /*
14038  * Read /etc/profile, ~/.profile, $ENV.
14039  */
14040 static void
14041 read_profile(const char *name)
14042 {
14043         name = expandstr(name, DQSYNTAX);
14044         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
14045                 return;
14046         cmdloop(0);
14047         popfile();
14048 }
14049
14050 /*
14051  * This routine is called when an error or an interrupt occurs in an
14052  * interactive shell and control is returned to the main command loop.
14053  * (In dash, this function is auto-generated by build machinery).
14054  */
14055 static void
14056 reset(void)
14057 {
14058         /* from eval.c: */
14059         evalskip = 0;
14060         loopnest = 0;
14061
14062         /* from expand.c: */
14063         ifsfree();
14064
14065         /* from input.c: */
14066         g_parsefile->left_in_buffer = 0;
14067         g_parsefile->left_in_line = 0;      /* clear input buffer */
14068         popallfiles();
14069
14070         /* from redir.c: */
14071         unwindredir(NULL);
14072
14073         /* from var.c: */
14074         unwindlocalvars(NULL);
14075 }
14076
14077 #if PROFILE
14078 static short profile_buf[16384];
14079 extern int etext();
14080 #endif
14081
14082 /*
14083  * Main routine.  We initialize things, parse the arguments, execute
14084  * profiles if we're a login shell, and then call cmdloop to execute
14085  * commands.  The setjmp call sets up the location to jump to when an
14086  * exception occurs.  When an exception occurs the variable "state"
14087  * is used to figure out how far we had gotten.
14088  */
14089 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
14090 int ash_main(int argc UNUSED_PARAM, char **argv)
14091 {
14092         volatile smallint state;
14093         struct jmploc jmploc;
14094         struct stackmark smark;
14095         int login_sh;
14096
14097         /* Initialize global data */
14098         INIT_G_misc();
14099         INIT_G_memstack();
14100         INIT_G_var();
14101 #if ENABLE_ASH_ALIAS
14102         INIT_G_alias();
14103 #endif
14104         INIT_G_cmdtable();
14105
14106 #if PROFILE
14107         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
14108 #endif
14109
14110 #if ENABLE_FEATURE_EDITING
14111         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
14112 #endif
14113         state = 0;
14114         if (setjmp(jmploc.loc)) {
14115                 smallint e;
14116                 smallint s;
14117
14118                 reset();
14119
14120                 e = exception_type;
14121                 s = state;
14122                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
14123                         exitshell();
14124                 }
14125                 if (e == EXINT) {
14126                         newline_and_flush(stderr);
14127                 }
14128
14129                 popstackmark(&smark);
14130                 FORCE_INT_ON; /* enable interrupts */
14131                 if (s == 1)
14132                         goto state1;
14133                 if (s == 2)
14134                         goto state2;
14135                 if (s == 3)
14136                         goto state3;
14137                 goto state4;
14138         }
14139         exception_handler = &jmploc;
14140         rootpid = getpid();
14141
14142         init();
14143         setstackmark(&smark);
14144         login_sh = procargs(argv);
14145 #if DEBUG
14146         TRACE(("Shell args: "));
14147         trace_puts_args(argv);
14148 #endif
14149
14150         if (login_sh) {
14151                 const char *hp;
14152
14153                 state = 1;
14154                 read_profile("/etc/profile");
14155  state1:
14156                 state = 2;
14157                 hp = lookupvar("HOME");
14158                 if (hp)
14159                         read_profile("$HOME/.profile");
14160         }
14161  state2:
14162         state = 3;
14163         if (
14164 #ifndef linux
14165          getuid() == geteuid() && getgid() == getegid() &&
14166 #endif
14167          iflag
14168         ) {
14169                 const char *shinit = lookupvar("ENV");
14170                 if (shinit != NULL && *shinit != '\0')
14171                         read_profile(shinit);
14172         }
14173         popstackmark(&smark);
14174  state3:
14175         state = 4;
14176         if (minusc) {
14177                 /* evalstring pushes parsefile stack.
14178                  * Ensure we don't falsely claim that 0 (stdin)
14179                  * is one of stacked source fds.
14180                  * Testcase: ash -c 'exec 1>&0' must not complain. */
14181                 // if (!sflag) g_parsefile->pf_fd = -1;
14182                 // ^^ not necessary since now we special-case fd 0
14183                 // in save_fd_on_redirect()
14184                 evalstring(minusc, sflag ? 0 : EV_EXIT);
14185         }
14186
14187         if (sflag || minusc == NULL) {
14188 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
14189                 if (iflag) {
14190                         const char *hp = lookupvar("HISTFILE");
14191                         if (!hp) {
14192                                 hp = lookupvar("HOME");
14193                                 if (hp) {
14194                                         INT_OFF;
14195                                         hp = concat_path_file(hp, ".ash_history");
14196                                         setvar0("HISTFILE", hp);
14197                                         free((char*)hp);
14198                                         INT_ON;
14199                                         hp = lookupvar("HISTFILE");
14200                                 }
14201                         }
14202                         if (hp)
14203                                 line_input_state->hist_file = hp;
14204 # if ENABLE_FEATURE_SH_HISTFILESIZE
14205                         hp = lookupvar("HISTFILESIZE");
14206                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
14207 # endif
14208                 }
14209 #endif
14210  state4: /* XXX ??? - why isn't this before the "if" statement */
14211                 cmdloop(1);
14212         }
14213 #if PROFILE
14214         monitor(0);
14215 #endif
14216 #ifdef GPROF
14217         {
14218                 extern void _mcleanup(void);
14219                 _mcleanup();
14220         }
14221 #endif
14222         TRACE(("End of main reached\n"));
14223         exitshell();
14224         /* NOTREACHED */
14225 }
14226
14227
14228 /*-
14229  * Copyright (c) 1989, 1991, 1993, 1994
14230  *      The Regents of the University of California.  All rights reserved.
14231  *
14232  * This code is derived from software contributed to Berkeley by
14233  * Kenneth Almquist.
14234  *
14235  * Redistribution and use in source and binary forms, with or without
14236  * modification, are permitted provided that the following conditions
14237  * are met:
14238  * 1. Redistributions of source code must retain the above copyright
14239  *    notice, this list of conditions and the following disclaimer.
14240  * 2. Redistributions in binary form must reproduce the above copyright
14241  *    notice, this list of conditions and the following disclaimer in the
14242  *    documentation and/or other materials provided with the distribution.
14243  * 3. Neither the name of the University nor the names of its contributors
14244  *    may be used to endorse or promote products derived from this software
14245  *    without specific prior written permission.
14246  *
14247  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
14248  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14249  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14250  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
14251  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14252  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14253  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14254  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14255  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14256  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14257  * SUCH DAMAGE.
14258  */