Complie libbb/duration.c if ping[6] is selected
[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/n* ]]; 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 typedef struct exp_t {
7579         char *dir;
7580         unsigned dir_max;
7581 } exp_t;
7582 static void
7583 expmeta(exp_t *exp, char *name, unsigned name_len, unsigned expdir_len)
7584 {
7585 #define expdir exp->dir
7586 #define expdir_max exp->dir_max
7587         char *enddir = expdir + expdir_len;
7588         char *p;
7589         const char *cp;
7590         char *start;
7591         char *endname;
7592         int metaflag;
7593         struct stat statb;
7594         DIR *dirp;
7595         struct dirent *dp;
7596         int atend;
7597         int matchdot;
7598         int esc;
7599
7600         metaflag = 0;
7601         start = name;
7602         for (p = name; esc = 0, *p; p += esc + 1) {
7603                 if (*p == '*' || *p == '?')
7604                         metaflag = 1;
7605                 else if (*p == '[') {
7606                         char *q = p + 1;
7607                         if (*q == '!')
7608                                 q++;
7609                         for (;;) {
7610                                 if (*q == '\\')
7611                                         q++;
7612                                 if (*q == '/' || *q == '\0')
7613                                         break;
7614                                 if (*++q == ']') {
7615                                         metaflag = 1;
7616                                         break;
7617                                 }
7618                         }
7619                 } else {
7620                         if (*p == '\\')
7621                                 esc++;
7622                         if (p[esc] == '/') {
7623                                 if (metaflag)
7624                                         break;
7625                                 start = p + esc + 1;
7626                         }
7627                 }
7628         }
7629         if (metaflag == 0) {    /* we've reached the end of the file name */
7630                 if (!expdir_len)
7631                         return;
7632                 p = name;
7633                 do {
7634                         if (*p == '\\')
7635                                 p++;
7636                         *enddir++ = *p;
7637                 } while (*p++);
7638                 if (lstat(expdir, &statb) == 0)
7639                         addfname(expdir);
7640                 return;
7641         }
7642         endname = p;
7643         if (name < start) {
7644                 p = name;
7645                 do {
7646                         if (*p == '\\')
7647                                 p++;
7648                         *enddir++ = *p++;
7649                 } while (p < start);
7650         }
7651         *enddir = '\0';
7652         cp = expdir;
7653         expdir_len = enddir - cp;
7654         if (!expdir_len)
7655                 cp = ".";
7656         dirp = opendir(cp);
7657         if (dirp == NULL)
7658                 return;
7659         if (*endname == 0) {
7660                 atend = 1;
7661         } else {
7662                 atend = 0;
7663                 *endname = '\0';
7664                 endname += esc + 1;
7665         }
7666         name_len -= endname - name;
7667         matchdot = 0;
7668         p = start;
7669         if (*p == '\\')
7670                 p++;
7671         if (*p == '.')
7672                 matchdot++;
7673         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7674                 if (dp->d_name[0] == '.' && !matchdot)
7675                         continue;
7676                 if (pmatch(start, dp->d_name)) {
7677                         if (atend) {
7678                                 strcpy(enddir, dp->d_name);
7679                                 addfname(expdir);
7680                         } else {
7681                                 unsigned offset;
7682                                 unsigned len;
7683
7684                                 p = stpcpy(enddir, dp->d_name);
7685                                 *p = '/';
7686
7687                                 offset = p - expdir + 1;
7688                                 len = offset + name_len + NAME_MAX;
7689                                 if (len > expdir_max) {
7690                                         len += PATH_MAX;
7691                                         expdir = ckrealloc(expdir, len);
7692                                         expdir_max = len;
7693                                 }
7694
7695                                 expmeta(exp, endname, name_len, offset);
7696                                 enddir = expdir + expdir_len;
7697                         }
7698                 }
7699         }
7700         closedir(dirp);
7701         if (!atend)
7702                 endname[-esc - 1] = esc ? '\\' : '/';
7703 #undef expdir
7704 #undef expdir_max
7705 }
7706
7707 static struct strlist *
7708 msort(struct strlist *list, int len)
7709 {
7710         struct strlist *p, *q = NULL;
7711         struct strlist **lpp;
7712         int half;
7713         int n;
7714
7715         if (len <= 1)
7716                 return list;
7717         half = len >> 1;
7718         p = list;
7719         for (n = half; --n >= 0;) {
7720                 q = p;
7721                 p = p->next;
7722         }
7723         q->next = NULL;                 /* terminate first half of list */
7724         q = msort(list, half);          /* sort first half of list */
7725         p = msort(p, len - half);               /* sort second half */
7726         lpp = &list;
7727         for (;;) {
7728 #if ENABLE_LOCALE_SUPPORT
7729                 if (strcoll(p->text, q->text) < 0)
7730 #else
7731                 if (strcmp(p->text, q->text) < 0)
7732 #endif
7733                                                 {
7734                         *lpp = p;
7735                         lpp = &p->next;
7736                         p = *lpp;
7737                         if (p == NULL) {
7738                                 *lpp = q;
7739                                 break;
7740                         }
7741                 } else {
7742                         *lpp = q;
7743                         lpp = &q->next;
7744                         q = *lpp;
7745                         if (q == NULL) {
7746                                 *lpp = p;
7747                                 break;
7748                         }
7749                 }
7750         }
7751         return list;
7752 }
7753
7754 /*
7755  * Sort the results of file name expansion.  It calculates the number of
7756  * strings to sort and then calls msort (short for merge sort) to do the
7757  * work.
7758  */
7759 static struct strlist *
7760 expsort(struct strlist *str)
7761 {
7762         int len;
7763         struct strlist *sp;
7764
7765         len = 0;
7766         for (sp = str; sp; sp = sp->next)
7767                 len++;
7768         return msort(str, len);
7769 }
7770
7771 static void
7772 expandmeta(struct strlist *str /*, int flag*/)
7773 {
7774         /* TODO - EXP_REDIR */
7775
7776         while (str) {
7777                 exp_t exp;
7778                 struct strlist **savelastp;
7779                 struct strlist *sp;
7780                 char *p;
7781                 unsigned len;
7782
7783                 if (fflag)
7784                         goto nometa;
7785                 if (!hasmeta(str->text))
7786                         goto nometa;
7787                 savelastp = exparg.lastp;
7788
7789                 INT_OFF;
7790                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7791                 len = strlen(p);
7792                 exp.dir_max = len + PATH_MAX;
7793                 exp.dir = ckmalloc(exp.dir_max);
7794
7795                 expmeta(&exp, p, len, 0);
7796                 free(exp.dir);
7797                 if (p != str->text)
7798                         free(p);
7799                 INT_ON;
7800                 if (exparg.lastp == savelastp) {
7801                         /*
7802                          * no matches
7803                          */
7804  nometa:
7805                         *exparg.lastp = str;
7806                         rmescapes(str->text, 0, NULL);
7807                         exparg.lastp = &str->next;
7808                 } else {
7809                         *exparg.lastp = NULL;
7810                         *savelastp = sp = expsort(*savelastp);
7811                         while (sp->next != NULL)
7812                                 sp = sp->next;
7813                         exparg.lastp = &sp->next;
7814                 }
7815                 str = str->next;
7816         }
7817 }
7818 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7819
7820 /*
7821  * Perform variable substitution and command substitution on an argument,
7822  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7823  * perform splitting and file name expansion.  When arglist is NULL, perform
7824  * here document expansion.
7825  */
7826 static void
7827 expandarg(union node *arg, struct arglist *arglist, int flag)
7828 {
7829         struct strlist *sp;
7830         char *p;
7831
7832         argbackq = arg->narg.backquote;
7833         STARTSTACKSTR(expdest);
7834         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7835         argstr(arg->narg.text, flag);
7836         p = _STPUTC('\0', expdest);
7837         expdest = p - 1;
7838         if (arglist == NULL) {
7839                 /* here document expanded */
7840                 goto out;
7841         }
7842         p = grabstackstr(p);
7843         TRACE(("expandarg: p:'%s'\n", p));
7844         exparg.lastp = &exparg.list;
7845         /*
7846          * TODO - EXP_REDIR
7847          */
7848         if (flag & EXP_FULL) {
7849                 ifsbreakup(p, &exparg);
7850                 *exparg.lastp = NULL;
7851                 exparg.lastp = &exparg.list;
7852                 expandmeta(exparg.list /*, flag*/);
7853         } else {
7854                 sp = stzalloc(sizeof(*sp));
7855                 sp->text = p;
7856                 *exparg.lastp = sp;
7857                 exparg.lastp = &sp->next;
7858         }
7859         *exparg.lastp = NULL;
7860         if (exparg.list) {
7861                 *arglist->lastp = exparg.list;
7862                 arglist->lastp = exparg.lastp;
7863         }
7864
7865  out:
7866         ifsfree();
7867 }
7868
7869 /*
7870  * Expand shell variables and backquotes inside a here document.
7871  */
7872 static void
7873 expandhere(union node *arg, int fd)
7874 {
7875         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7876         full_write(fd, stackblock(), expdest - (char *)stackblock());
7877 }
7878
7879 /*
7880  * Returns true if the pattern matches the string.
7881  */
7882 static int
7883 patmatch(char *pattern, const char *string)
7884 {
7885         char *p = preglob(pattern, 0);
7886         int r = pmatch(p, string);
7887         //bb_error_msg("!fnmatch(pattern:'%s',str:'%s',0):%d", p, string, r);
7888         return r;
7889 }
7890
7891 /*
7892  * See if a pattern matches in a case statement.
7893  */
7894 static int
7895 casematch(union node *pattern, char *val)
7896 {
7897         struct stackmark smark;
7898         int result;
7899
7900         setstackmark(&smark);
7901         argbackq = pattern->narg.backquote;
7902         STARTSTACKSTR(expdest);
7903         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7904         STACKSTRNUL(expdest);
7905         ifsfree();
7906         result = patmatch(stackblock(), val);
7907         popstackmark(&smark);
7908         return result;
7909 }
7910
7911
7912 /* ============ find_command */
7913
7914 struct builtincmd {
7915         const char *name;
7916         int (*builtin)(int, char **) FAST_FUNC;
7917         /* unsigned flags; */
7918 };
7919 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7920 /* "regular" builtins always take precedence over commands,
7921  * regardless of PATH=....%builtin... position */
7922 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7923 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7924
7925 struct cmdentry {
7926         smallint cmdtype;       /* CMDxxx */
7927         union param {
7928                 int index;
7929                 /* index >= 0 for commands without path (slashes) */
7930                 /* (TODO: what exactly does the value mean? PATH position?) */
7931                 /* index == -1 for commands with slashes */
7932                 /* index == (-2 - applet_no) for NOFORK applets */
7933                 const struct builtincmd *cmd;
7934                 struct funcnode *func;
7935         } u;
7936 };
7937 /* values of cmdtype */
7938 #define CMDUNKNOWN      -1      /* no entry in table for command */
7939 #define CMDNORMAL       0       /* command is an executable program */
7940 #define CMDFUNCTION     1       /* command is a shell function */
7941 #define CMDBUILTIN      2       /* command is a shell builtin */
7942
7943 /* action to find_command() */
7944 #define DO_ERR          0x01    /* prints errors */
7945 #define DO_ABS          0x02    /* checks absolute paths */
7946 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7947 #define DO_ALTPATH      0x08    /* using alternate path */
7948 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7949
7950 static void find_command(char *, struct cmdentry *, int, const char *);
7951
7952
7953 /* ============ Hashing commands */
7954
7955 /*
7956  * When commands are first encountered, they are entered in a hash table.
7957  * This ensures that a full path search will not have to be done for them
7958  * on each invocation.
7959  *
7960  * We should investigate converting to a linear search, even though that
7961  * would make the command name "hash" a misnomer.
7962  */
7963
7964 struct tblentry {
7965         struct tblentry *next;  /* next entry in hash chain */
7966         union param param;      /* definition of builtin function */
7967         smallint cmdtype;       /* CMDxxx */
7968         char rehash;            /* if set, cd done since entry created */
7969         char cmdname[1];        /* name of command */
7970 };
7971
7972 static struct tblentry **cmdtable;
7973 #define INIT_G_cmdtable() do { \
7974         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7975 } while (0)
7976
7977 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7978
7979
7980 static void
7981 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7982 {
7983 #if ENABLE_FEATURE_SH_STANDALONE
7984         if (applet_no >= 0) {
7985                 if (APPLET_IS_NOEXEC(applet_no)) {
7986                         clearenv();
7987                         while (*envp)
7988                                 putenv(*envp++);
7989                         popredir(/*drop:*/ 1);
7990                         run_noexec_applet_and_exit(applet_no, cmd, argv);
7991                 }
7992                 /* re-exec ourselves with the new arguments */
7993                 execve(bb_busybox_exec_path, argv, envp);
7994                 /* If they called chroot or otherwise made the binary no longer
7995                  * executable, fall through */
7996         }
7997 #endif
7998
7999  repeat:
8000 #ifdef SYSV
8001         do {
8002                 execve(cmd, argv, envp);
8003         } while (errno == EINTR);
8004 #else
8005         execve(cmd, argv, envp);
8006 #endif
8007         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
8008                 /* Run "cmd" as a shell script:
8009                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
8010                  * "If the execve() function fails with ENOEXEC, the shell
8011                  * shall execute a command equivalent to having a shell invoked
8012                  * with the command name as its first operand,
8013                  * with any remaining arguments passed to the new shell"
8014                  *
8015                  * That is, do not use $SHELL, user's shell, or /bin/sh;
8016                  * just call ourselves.
8017                  *
8018                  * Note that bash reads ~80 chars of the file, and if it sees
8019                  * a zero byte before it sees newline, it doesn't try to
8020                  * interpret it, but fails with "cannot execute binary file"
8021                  * message and exit code 126. For one, this prevents attempts
8022                  * to interpret foreign ELF binaries as shell scripts.
8023                  */
8024                 argv[0] = (char*) cmd;
8025                 cmd = bb_busybox_exec_path;
8026                 /* NB: this is only possible because all callers of shellexec()
8027                  * ensure that the argv[-1] slot exists!
8028                  */
8029                 argv--;
8030                 argv[0] = (char*) "ash";
8031                 goto repeat;
8032         }
8033 }
8034
8035 /*
8036  * Exec a program.  Never returns.  If you change this routine, you may
8037  * have to change the find_command routine as well.
8038  * argv[-1] must exist and be writable! See tryexec() for why.
8039  */
8040 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
8041 static void shellexec(char *prog, char **argv, const char *path, int idx)
8042 {
8043         char *cmdname;
8044         int e;
8045         char **envp;
8046         int exerrno;
8047         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
8048
8049         envp = listvars(VEXPORT, VUNSET, /*strlist:*/ NULL, /*end:*/ NULL);
8050         if (strchr(prog, '/') != NULL
8051 #if ENABLE_FEATURE_SH_STANDALONE
8052          || (applet_no = find_applet_by_name(prog)) >= 0
8053 #endif
8054         ) {
8055                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
8056                 if (applet_no >= 0) {
8057                         /* We tried execing ourself, but it didn't work.
8058                          * Maybe /proc/self/exe doesn't exist?
8059                          * Try $PATH search.
8060                          */
8061                         goto try_PATH;
8062                 }
8063                 e = errno;
8064         } else {
8065  try_PATH:
8066                 e = ENOENT;
8067                 while ((cmdname = path_advance(&path, prog)) != NULL) {
8068                         if (--idx < 0 && pathopt == NULL) {
8069                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
8070                                 if (errno != ENOENT && errno != ENOTDIR)
8071                                         e = errno;
8072                         }
8073                         stunalloc(cmdname);
8074                 }
8075         }
8076
8077         /* Map to POSIX errors */
8078         switch (e) {
8079         case EACCES:
8080                 exerrno = 126;
8081                 break;
8082         case ENOENT:
8083                 exerrno = 127;
8084                 break;
8085         default:
8086                 exerrno = 2;
8087                 break;
8088         }
8089         exitstatus = exerrno;
8090         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
8091                 prog, e, suppress_int));
8092         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
8093         /* NOTREACHED */
8094 }
8095
8096 static void
8097 printentry(struct tblentry *cmdp)
8098 {
8099         int idx;
8100         const char *path;
8101         char *name;
8102
8103         idx = cmdp->param.index;
8104         path = pathval();
8105         do {
8106                 name = path_advance(&path, cmdp->cmdname);
8107                 stunalloc(name);
8108         } while (--idx >= 0);
8109         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
8110 }
8111
8112 /*
8113  * Clear out command entries.  The argument specifies the first entry in
8114  * PATH which has changed.
8115  */
8116 static void
8117 clearcmdentry(int firstchange)
8118 {
8119         struct tblentry **tblp;
8120         struct tblentry **pp;
8121         struct tblentry *cmdp;
8122
8123         INT_OFF;
8124         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
8125                 pp = tblp;
8126                 while ((cmdp = *pp) != NULL) {
8127                         if ((cmdp->cmdtype == CMDNORMAL &&
8128                              cmdp->param.index >= firstchange)
8129                          || (cmdp->cmdtype == CMDBUILTIN &&
8130                              builtinloc >= firstchange)
8131                         ) {
8132                                 *pp = cmdp->next;
8133                                 free(cmdp);
8134                         } else {
8135                                 pp = &cmdp->next;
8136                         }
8137                 }
8138         }
8139         INT_ON;
8140 }
8141
8142 /*
8143  * Locate a command in the command hash table.  If "add" is nonzero,
8144  * add the command to the table if it is not already present.  The
8145  * variable "lastcmdentry" is set to point to the address of the link
8146  * pointing to the entry, so that delete_cmd_entry can delete the
8147  * entry.
8148  *
8149  * Interrupts must be off if called with add != 0.
8150  */
8151 static struct tblentry **lastcmdentry;
8152
8153 static struct tblentry *
8154 cmdlookup(const char *name, int add)
8155 {
8156         unsigned int hashval;
8157         const char *p;
8158         struct tblentry *cmdp;
8159         struct tblentry **pp;
8160
8161         p = name;
8162         hashval = (unsigned char)*p << 4;
8163         while (*p)
8164                 hashval += (unsigned char)*p++;
8165         hashval &= 0x7FFF;
8166         pp = &cmdtable[hashval % CMDTABLESIZE];
8167         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8168                 if (strcmp(cmdp->cmdname, name) == 0)
8169                         break;
8170                 pp = &cmdp->next;
8171         }
8172         if (add && cmdp == NULL) {
8173                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
8174                                 + strlen(name)
8175                                 /* + 1 - already done because
8176                                  * tblentry::cmdname is char[1] */);
8177                 /*cmdp->next = NULL; - ckzalloc did it */
8178                 cmdp->cmdtype = CMDUNKNOWN;
8179                 strcpy(cmdp->cmdname, name);
8180         }
8181         lastcmdentry = pp;
8182         return cmdp;
8183 }
8184
8185 /*
8186  * Delete the command entry returned on the last lookup.
8187  */
8188 static void
8189 delete_cmd_entry(void)
8190 {
8191         struct tblentry *cmdp;
8192
8193         INT_OFF;
8194         cmdp = *lastcmdentry;
8195         *lastcmdentry = cmdp->next;
8196         if (cmdp->cmdtype == CMDFUNCTION)
8197                 freefunc(cmdp->param.func);
8198         free(cmdp);
8199         INT_ON;
8200 }
8201
8202 /*
8203  * Add a new command entry, replacing any existing command entry for
8204  * the same name - except special builtins.
8205  */
8206 static void
8207 addcmdentry(char *name, struct cmdentry *entry)
8208 {
8209         struct tblentry *cmdp;
8210
8211         cmdp = cmdlookup(name, 1);
8212         if (cmdp->cmdtype == CMDFUNCTION) {
8213                 freefunc(cmdp->param.func);
8214         }
8215         cmdp->cmdtype = entry->cmdtype;
8216         cmdp->param = entry->u;
8217         cmdp->rehash = 0;
8218 }
8219
8220 static int FAST_FUNC
8221 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8222 {
8223         struct tblentry **pp;
8224         struct tblentry *cmdp;
8225         int c;
8226         struct cmdentry entry;
8227         char *name;
8228
8229         if (nextopt("r") != '\0') {
8230                 clearcmdentry(0);
8231                 return 0;
8232         }
8233
8234         if (*argptr == NULL) {
8235                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8236                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8237                                 if (cmdp->cmdtype == CMDNORMAL)
8238                                         printentry(cmdp);
8239                         }
8240                 }
8241                 return 0;
8242         }
8243
8244         c = 0;
8245         while ((name = *argptr) != NULL) {
8246                 cmdp = cmdlookup(name, 0);
8247                 if (cmdp != NULL
8248                  && (cmdp->cmdtype == CMDNORMAL
8249                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
8250                 ) {
8251                         delete_cmd_entry();
8252                 }
8253                 find_command(name, &entry, DO_ERR, pathval());
8254                 if (entry.cmdtype == CMDUNKNOWN)
8255                         c = 1;
8256                 argptr++;
8257         }
8258         return c;
8259 }
8260
8261 /*
8262  * Called when a cd is done.  Marks all commands so the next time they
8263  * are executed they will be rehashed.
8264  */
8265 static void
8266 hashcd(void)
8267 {
8268         struct tblentry **pp;
8269         struct tblentry *cmdp;
8270
8271         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
8272                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
8273                         if (cmdp->cmdtype == CMDNORMAL
8274                          || (cmdp->cmdtype == CMDBUILTIN
8275                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8276                              && builtinloc > 0)
8277                         ) {
8278                                 cmdp->rehash = 1;
8279                         }
8280                 }
8281         }
8282 }
8283
8284 /*
8285  * Fix command hash table when PATH changed.
8286  * Called before PATH is changed.  The argument is the new value of PATH;
8287  * pathval() still returns the old value at this point.
8288  * Called with interrupts off.
8289  */
8290 static void FAST_FUNC
8291 changepath(const char *new)
8292 {
8293         const char *old;
8294         int firstchange;
8295         int idx;
8296         int idx_bltin;
8297
8298         old = pathval();
8299         firstchange = 9999;     /* assume no change */
8300         idx = 0;
8301         idx_bltin = -1;
8302         for (;;) {
8303                 if (*old != *new) {
8304                         firstchange = idx;
8305                         if ((*old == '\0' && *new == ':')
8306                          || (*old == ':' && *new == '\0')
8307                         ) {
8308                                 firstchange++;
8309                         }
8310                         old = new;      /* ignore subsequent differences */
8311                 }
8312                 if (*new == '\0')
8313                         break;
8314                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8315                         idx_bltin = idx;
8316                 if (*new == ':')
8317                         idx++;
8318                 new++;
8319                 old++;
8320         }
8321         if (builtinloc < 0 && idx_bltin >= 0)
8322                 builtinloc = idx_bltin;             /* zap builtins */
8323         if (builtinloc >= 0 && idx_bltin < 0)
8324                 firstchange = 0;
8325         clearcmdentry(firstchange);
8326         builtinloc = idx_bltin;
8327 }
8328 enum {
8329         TEOF,
8330         TNL,
8331         TREDIR,
8332         TWORD,
8333         TSEMI,
8334         TBACKGND,
8335         TAND,
8336         TOR,
8337         TPIPE,
8338         TLP,
8339         TRP,
8340         TENDCASE,
8341         TENDBQUOTE,
8342         TNOT,
8343         TCASE,
8344         TDO,
8345         TDONE,
8346         TELIF,
8347         TELSE,
8348         TESAC,
8349         TFI,
8350         TFOR,
8351 #if BASH_FUNCTION
8352         TFUNCTION,
8353 #endif
8354         TIF,
8355         TIN,
8356         TTHEN,
8357         TUNTIL,
8358         TWHILE,
8359         TBEGIN,
8360         TEND
8361 };
8362 typedef smallint token_id_t;
8363
8364 /* Nth bit indicates if token marks the end of a list */
8365 enum {
8366         tokendlist = 0
8367         /*  0 */ | (1u << TEOF)
8368         /*  1 */ | (0u << TNL)
8369         /*  2 */ | (0u << TREDIR)
8370         /*  3 */ | (0u << TWORD)
8371         /*  4 */ | (0u << TSEMI)
8372         /*  5 */ | (0u << TBACKGND)
8373         /*  6 */ | (0u << TAND)
8374         /*  7 */ | (0u << TOR)
8375         /*  8 */ | (0u << TPIPE)
8376         /*  9 */ | (0u << TLP)
8377         /* 10 */ | (1u << TRP)
8378         /* 11 */ | (1u << TENDCASE)
8379         /* 12 */ | (1u << TENDBQUOTE)
8380         /* 13 */ | (0u << TNOT)
8381         /* 14 */ | (0u << TCASE)
8382         /* 15 */ | (1u << TDO)
8383         /* 16 */ | (1u << TDONE)
8384         /* 17 */ | (1u << TELIF)
8385         /* 18 */ | (1u << TELSE)
8386         /* 19 */ | (1u << TESAC)
8387         /* 20 */ | (1u << TFI)
8388         /* 21 */ | (0u << TFOR)
8389 #if BASH_FUNCTION
8390         /* 22 */ | (0u << TFUNCTION)
8391 #endif
8392         /* 23 */ | (0u << TIF)
8393         /* 24 */ | (0u << TIN)
8394         /* 25 */ | (1u << TTHEN)
8395         /* 26 */ | (0u << TUNTIL)
8396         /* 27 */ | (0u << TWHILE)
8397         /* 28 */ | (0u << TBEGIN)
8398         /* 29 */ | (1u << TEND)
8399         , /* thus far 29 bits used */
8400 };
8401
8402 static const char *const tokname_array[] = {
8403         "end of file",
8404         "newline",
8405         "redirection",
8406         "word",
8407         ";",
8408         "&",
8409         "&&",
8410         "||",
8411         "|",
8412         "(",
8413         ")",
8414         ";;",
8415         "`",
8416 #define KWDOFFSET 13
8417         /* the following are keywords */
8418         "!",
8419         "case",
8420         "do",
8421         "done",
8422         "elif",
8423         "else",
8424         "esac",
8425         "fi",
8426         "for",
8427 #if BASH_FUNCTION
8428         "function",
8429 #endif
8430         "if",
8431         "in",
8432         "then",
8433         "until",
8434         "while",
8435         "{",
8436         "}",
8437 };
8438
8439 /* Wrapper around strcmp for qsort/bsearch/... */
8440 static int
8441 pstrcmp(const void *a, const void *b)
8442 {
8443         return strcmp((char*)a, *(char**)b);
8444 }
8445
8446 static const char *const *
8447 findkwd(const char *s)
8448 {
8449         return bsearch(s, tokname_array + KWDOFFSET,
8450                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8451                         sizeof(tokname_array[0]), pstrcmp);
8452 }
8453
8454 /*
8455  * Locate and print what a word is...
8456  */
8457 static int
8458 describe_command(char *command, const char *path, int describe_command_verbose)
8459 {
8460         struct cmdentry entry;
8461 #if ENABLE_ASH_ALIAS
8462         const struct alias *ap;
8463 #endif
8464
8465         path = path ? path : pathval();
8466
8467         if (describe_command_verbose) {
8468                 out1str(command);
8469         }
8470
8471         /* First look at the keywords */
8472         if (findkwd(command)) {
8473                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8474                 goto out;
8475         }
8476
8477 #if ENABLE_ASH_ALIAS
8478         /* Then look at the aliases */
8479         ap = lookupalias(command, 0);
8480         if (ap != NULL) {
8481                 if (!describe_command_verbose) {
8482                         out1str("alias ");
8483                         printalias(ap);
8484                         return 0;
8485                 }
8486                 out1fmt(" is an alias for %s", ap->val);
8487                 goto out;
8488         }
8489 #endif
8490         /* Brute force */
8491         find_command(command, &entry, DO_ABS, path);
8492
8493         switch (entry.cmdtype) {
8494         case CMDNORMAL: {
8495                 int j = entry.u.index;
8496                 char *p;
8497                 if (j < 0) {
8498                         p = command;
8499                 } else {
8500                         do {
8501                                 p = path_advance(&path, command);
8502                                 stunalloc(p);
8503                         } while (--j >= 0);
8504                 }
8505                 if (describe_command_verbose) {
8506                         out1fmt(" is %s", p);
8507                 } else {
8508                         out1str(p);
8509                 }
8510                 break;
8511         }
8512
8513         case CMDFUNCTION:
8514                 if (describe_command_verbose) {
8515                         /*out1str(" is a shell function");*/
8516                         out1str(" is a function"); /* bash says this */
8517                 } else {
8518                         out1str(command);
8519                 }
8520                 break;
8521
8522         case CMDBUILTIN:
8523                 if (describe_command_verbose) {
8524                         out1fmt(" is a %sshell builtin",
8525                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8526                                         "special " : nullstr
8527                         );
8528                 } else {
8529                         out1str(command);
8530                 }
8531                 break;
8532
8533         default:
8534                 if (describe_command_verbose) {
8535                         out1str(": not found\n");
8536                 }
8537                 return 127;
8538         }
8539  out:
8540         out1str("\n");
8541         return 0;
8542 }
8543
8544 static int FAST_FUNC
8545 typecmd(int argc UNUSED_PARAM, char **argv)
8546 {
8547         int i = 1;
8548         int err = 0;
8549         int verbose = 1;
8550
8551         /* type -p ... ? (we don't bother checking for 'p') */
8552         if (argv[1] && argv[1][0] == '-') {
8553                 i++;
8554                 verbose = 0;
8555         }
8556         while (argv[i]) {
8557                 err |= describe_command(argv[i++], NULL, verbose);
8558         }
8559         return err;
8560 }
8561
8562 #if ENABLE_ASH_CMDCMD
8563 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8564 static char **
8565 parse_command_args(char **argv, const char **path)
8566 {
8567         char *cp, c;
8568
8569         for (;;) {
8570                 cp = *++argv;
8571                 if (!cp)
8572                         return NULL;
8573                 if (*cp++ != '-')
8574                         break;
8575                 c = *cp++;
8576                 if (!c)
8577                         break;
8578                 if (c == '-' && !*cp) {
8579                         if (!*++argv)
8580                                 return NULL;
8581                         break;
8582                 }
8583                 do {
8584                         switch (c) {
8585                         case 'p':
8586                                 *path = bb_default_path;
8587                                 break;
8588                         default:
8589                                 /* run 'typecmd' for other options */
8590                                 return NULL;
8591                         }
8592                         c = *cp++;
8593                 } while (c);
8594         }
8595         return argv;
8596 }
8597
8598 static int FAST_FUNC
8599 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8600 {
8601         char *cmd;
8602         int c;
8603         enum {
8604                 VERIFY_BRIEF = 1,
8605                 VERIFY_VERBOSE = 2,
8606         } verify = 0;
8607         const char *path = NULL;
8608
8609         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8610          * never reaches this function.
8611          */
8612
8613         while ((c = nextopt("pvV")) != '\0')
8614                 if (c == 'V')
8615                         verify |= VERIFY_VERBOSE;
8616                 else if (c == 'v')
8617                         /*verify |= VERIFY_BRIEF*/;
8618 #if DEBUG
8619                 else if (c != 'p')
8620                         abort();
8621 #endif
8622                 else
8623                         path = bb_default_path;
8624
8625         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8626         cmd = *argptr;
8627         if (/*verify && */ cmd)
8628                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8629
8630         return 0;
8631 }
8632 #endif
8633
8634
8635 /*static int funcblocksize;     // size of structures in function */
8636 /*static int funcstringsize;    // size of strings in node */
8637 static void *funcblock;         /* block to allocate function from */
8638 static char *funcstring_end;    /* end of block to allocate strings from */
8639
8640 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8641         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8642         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8643         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8644         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8645         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8646         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8647         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8648         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8649         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8650         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8651         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8652         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8653         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8654         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8655         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8656         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8657         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8658 #if BASH_REDIR_OUTPUT
8659         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8660 #endif
8661         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8662         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8663         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8664         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8665         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8666         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8667         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8668         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8669         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8670 };
8671
8672 static int calcsize(int funcblocksize, union node *n);
8673
8674 static int
8675 sizenodelist(int funcblocksize, struct nodelist *lp)
8676 {
8677         while (lp) {
8678                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8679                 funcblocksize = calcsize(funcblocksize, lp->n);
8680                 lp = lp->next;
8681         }
8682         return funcblocksize;
8683 }
8684
8685 static int
8686 calcsize(int funcblocksize, union node *n)
8687 {
8688         if (n == NULL)
8689                 return funcblocksize;
8690         funcblocksize += nodesize[n->type];
8691         switch (n->type) {
8692         case NCMD:
8693                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8694                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8695                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8696                 break;
8697         case NPIPE:
8698                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8699                 break;
8700         case NREDIR:
8701         case NBACKGND:
8702         case NSUBSHELL:
8703                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8704                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8705                 break;
8706         case NAND:
8707         case NOR:
8708         case NSEMI:
8709         case NWHILE:
8710         case NUNTIL:
8711                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8712                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8713                 break;
8714         case NIF:
8715                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8716                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8717                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8718                 break;
8719         case NFOR:
8720                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8721                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8722                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8723                 break;
8724         case NCASE:
8725                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8726                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8727                 break;
8728         case NCLIST:
8729                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8730                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8731                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8732                 break;
8733         case NDEFUN:
8734                 funcblocksize = calcsize(funcblocksize, n->ndefun.body);
8735                 funcblocksize += SHELL_ALIGN(strlen(n->ndefun.text) + 1);
8736                 break;
8737         case NARG:
8738                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8739                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8740                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8741                 break;
8742         case NTO:
8743 #if BASH_REDIR_OUTPUT
8744         case NTO2:
8745 #endif
8746         case NCLOBBER:
8747         case NFROM:
8748         case NFROMTO:
8749         case NAPPEND:
8750                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8751                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8752                 break;
8753         case NTOFD:
8754         case NFROMFD:
8755                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8756                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8757         break;
8758         case NHERE:
8759         case NXHERE:
8760                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8761                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8762                 break;
8763         case NNOT:
8764                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8765                 break;
8766         };
8767         return funcblocksize;
8768 }
8769
8770 static char *
8771 nodeckstrdup(char *s)
8772 {
8773         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8774         return strcpy(funcstring_end, s);
8775 }
8776
8777 static union node *copynode(union node *);
8778
8779 static struct nodelist *
8780 copynodelist(struct nodelist *lp)
8781 {
8782         struct nodelist *start;
8783         struct nodelist **lpp;
8784
8785         lpp = &start;
8786         while (lp) {
8787                 *lpp = funcblock;
8788                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8789                 (*lpp)->n = copynode(lp->n);
8790                 lp = lp->next;
8791                 lpp = &(*lpp)->next;
8792         }
8793         *lpp = NULL;
8794         return start;
8795 }
8796
8797 static union node *
8798 copynode(union node *n)
8799 {
8800         union node *new;
8801
8802         if (n == NULL)
8803                 return NULL;
8804         new = funcblock;
8805         funcblock = (char *) funcblock + nodesize[n->type];
8806
8807         switch (n->type) {
8808         case NCMD:
8809                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8810                 new->ncmd.args = copynode(n->ncmd.args);
8811                 new->ncmd.assign = copynode(n->ncmd.assign);
8812                 new->ncmd.linno = n->ncmd.linno;
8813                 break;
8814         case NPIPE:
8815                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8816                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8817                 break;
8818         case NREDIR:
8819         case NBACKGND:
8820         case NSUBSHELL:
8821                 new->nredir.redirect = copynode(n->nredir.redirect);
8822                 new->nredir.n = copynode(n->nredir.n);
8823                 new->nredir.linno = n->nredir.linno;
8824                 break;
8825         case NAND:
8826         case NOR:
8827         case NSEMI:
8828         case NWHILE:
8829         case NUNTIL:
8830                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8831                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8832                 break;
8833         case NIF:
8834                 new->nif.elsepart = copynode(n->nif.elsepart);
8835                 new->nif.ifpart = copynode(n->nif.ifpart);
8836                 new->nif.test = copynode(n->nif.test);
8837                 break;
8838         case NFOR:
8839                 new->nfor.var = nodeckstrdup(n->nfor.var);
8840                 new->nfor.body = copynode(n->nfor.body);
8841                 new->nfor.args = copynode(n->nfor.args);
8842                 new->nfor.linno = n->nfor.linno;
8843                 break;
8844         case NCASE:
8845                 new->ncase.cases = copynode(n->ncase.cases);
8846                 new->ncase.expr = copynode(n->ncase.expr);
8847                 new->ncase.linno = n->ncase.linno;
8848                 break;
8849         case NCLIST:
8850                 new->nclist.body = copynode(n->nclist.body);
8851                 new->nclist.pattern = copynode(n->nclist.pattern);
8852                 new->nclist.next = copynode(n->nclist.next);
8853                 break;
8854         case NDEFUN:
8855                 new->ndefun.body = copynode(n->ndefun.body);
8856                 new->ndefun.text = nodeckstrdup(n->ndefun.text);
8857                 new->ndefun.linno = n->ndefun.linno;
8858                 break;
8859         case NARG:
8860                 new->narg.backquote = copynodelist(n->narg.backquote);
8861                 new->narg.text = nodeckstrdup(n->narg.text);
8862                 new->narg.next = copynode(n->narg.next);
8863                 break;
8864         case NTO:
8865 #if BASH_REDIR_OUTPUT
8866         case NTO2:
8867 #endif
8868         case NCLOBBER:
8869         case NFROM:
8870         case NFROMTO:
8871         case NAPPEND:
8872                 new->nfile.fname = copynode(n->nfile.fname);
8873                 new->nfile.fd = n->nfile.fd;
8874                 new->nfile.next = copynode(n->nfile.next);
8875                 break;
8876         case NTOFD:
8877         case NFROMFD:
8878                 new->ndup.vname = copynode(n->ndup.vname);
8879                 new->ndup.dupfd = n->ndup.dupfd;
8880                 new->ndup.fd = n->ndup.fd;
8881                 new->ndup.next = copynode(n->ndup.next);
8882                 break;
8883         case NHERE:
8884         case NXHERE:
8885                 new->nhere.doc = copynode(n->nhere.doc);
8886                 new->nhere.fd = n->nhere.fd;
8887                 new->nhere.next = copynode(n->nhere.next);
8888                 break;
8889         case NNOT:
8890                 new->nnot.com = copynode(n->nnot.com);
8891                 break;
8892         };
8893         new->type = n->type;
8894         return new;
8895 }
8896
8897 /*
8898  * Make a copy of a parse tree.
8899  */
8900 static struct funcnode *
8901 copyfunc(union node *n)
8902 {
8903         struct funcnode *f;
8904         size_t blocksize;
8905
8906         /*funcstringsize = 0;*/
8907         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8908         f = ckzalloc(blocksize /* + funcstringsize */);
8909         funcblock = (char *) f + offsetof(struct funcnode, n);
8910         funcstring_end = (char *) f + blocksize;
8911         copynode(n);
8912         /* f->count = 0; - ckzalloc did it */
8913         return f;
8914 }
8915
8916 /*
8917  * Define a shell function.
8918  */
8919 static void
8920 defun(union node *func)
8921 {
8922         struct cmdentry entry;
8923
8924         INT_OFF;
8925         entry.cmdtype = CMDFUNCTION;
8926         entry.u.func = copyfunc(func);
8927         addcmdentry(func->ndefun.text, &entry);
8928         INT_ON;
8929 }
8930
8931 /* Reasons for skipping commands (see comment on breakcmd routine) */
8932 #define SKIPBREAK      (1 << 0)
8933 #define SKIPCONT       (1 << 1)
8934 #define SKIPFUNC       (1 << 2)
8935 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8936 static int skipcount;           /* number of levels to skip */
8937 static int loopnest;            /* current loop nesting level */
8938 static int funcline;            /* starting line number of current function, or 0 if not in a function */
8939
8940 /* Forward decl way out to parsing code - dotrap needs it */
8941 static int evalstring(char *s, int flags);
8942
8943 /* Called to execute a trap.
8944  * Single callsite - at the end of evaltree().
8945  * If we return non-zero, evaltree raises EXEXIT exception.
8946  *
8947  * Perhaps we should avoid entering new trap handlers
8948  * while we are executing a trap handler. [is it a TODO?]
8949  */
8950 static void
8951 dotrap(void)
8952 {
8953         uint8_t *g;
8954         int sig;
8955         uint8_t last_status;
8956
8957         if (!pending_sig)
8958                 return;
8959
8960         last_status = exitstatus;
8961         pending_sig = 0;
8962         barrier();
8963
8964         TRACE(("dotrap entered\n"));
8965         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8966                 char *p;
8967
8968                 if (!*g)
8969                         continue;
8970
8971                 if (evalskip) {
8972                         pending_sig = sig;
8973                         break;
8974                 }
8975
8976                 p = trap[sig];
8977                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8978                  * don't upset it by resetting gotsig[SIGINT-1] */
8979                 if (sig == SIGINT && !p)
8980                         continue;
8981
8982                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8983                 *g = 0;
8984                 if (!p)
8985                         continue;
8986                 evalstring(p, 0);
8987         }
8988         exitstatus = last_status;
8989         TRACE(("dotrap returns\n"));
8990 }
8991
8992 /* forward declarations - evaluation is fairly recursive business... */
8993 static int evalloop(union node *, int);
8994 static int evalfor(union node *, int);
8995 static int evalcase(union node *, int);
8996 static int evalsubshell(union node *, int);
8997 static void expredir(union node *);
8998 static int evalpipe(union node *, int);
8999 static int evalcommand(union node *, int);
9000 static int evalbltin(const struct builtincmd *, int, char **, int);
9001 static void prehash(union node *);
9002
9003 /*
9004  * Evaluate a parse tree.  The value is left in the global variable
9005  * exitstatus.
9006  */
9007 static int
9008 evaltree(union node *n, int flags)
9009 {
9010         int checkexit = 0;
9011         int (*evalfn)(union node *, int);
9012         int status = 0;
9013
9014         if (n == NULL) {
9015                 TRACE(("evaltree(NULL) called\n"));
9016                 goto out;
9017         }
9018         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
9019
9020         dotrap();
9021
9022         switch (n->type) {
9023         default:
9024 #if DEBUG
9025                 out1fmt("Node type = %d\n", n->type);
9026                 fflush_all();
9027                 break;
9028 #endif
9029         case NNOT:
9030                 status = !evaltree(n->nnot.com, EV_TESTED);
9031                 goto setstatus;
9032         case NREDIR:
9033                 errlinno = lineno = n->nredir.linno;
9034                 if (funcline)
9035                         lineno -= funcline - 1;
9036                 expredir(n->nredir.redirect);
9037                 pushredir(n->nredir.redirect);
9038                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
9039                 if (!status) {
9040                         status = evaltree(n->nredir.n, flags & EV_TESTED);
9041                 }
9042                 if (n->nredir.redirect)
9043                         popredir(/*drop:*/ 0);
9044                 goto setstatus;
9045         case NCMD:
9046                 evalfn = evalcommand;
9047  checkexit:
9048                 if (eflag && !(flags & EV_TESTED))
9049                         checkexit = ~0;
9050                 goto calleval;
9051         case NFOR:
9052                 evalfn = evalfor;
9053                 goto calleval;
9054         case NWHILE:
9055         case NUNTIL:
9056                 evalfn = evalloop;
9057                 goto calleval;
9058         case NSUBSHELL:
9059         case NBACKGND:
9060                 evalfn = evalsubshell;
9061                 goto checkexit;
9062         case NPIPE:
9063                 evalfn = evalpipe;
9064                 goto checkexit;
9065         case NCASE:
9066                 evalfn = evalcase;
9067                 goto calleval;
9068         case NAND:
9069         case NOR:
9070         case NSEMI: {
9071
9072 #if NAND + 1 != NOR
9073 #error NAND + 1 != NOR
9074 #endif
9075 #if NOR + 1 != NSEMI
9076 #error NOR + 1 != NSEMI
9077 #endif
9078                 unsigned is_or = n->type - NAND;
9079                 status = evaltree(
9080                         n->nbinary.ch1,
9081                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
9082                 );
9083                 if ((!status) == is_or || evalskip)
9084                         break;
9085                 n = n->nbinary.ch2;
9086  evaln:
9087                 evalfn = evaltree;
9088  calleval:
9089                 status = evalfn(n, flags);
9090                 goto setstatus;
9091         }
9092         case NIF:
9093                 status = evaltree(n->nif.test, EV_TESTED);
9094                 if (evalskip)
9095                         break;
9096                 if (!status) {
9097                         n = n->nif.ifpart;
9098                         goto evaln;
9099                 }
9100                 if (n->nif.elsepart) {
9101                         n = n->nif.elsepart;
9102                         goto evaln;
9103                 }
9104                 status = 0;
9105                 goto setstatus;
9106         case NDEFUN:
9107                 defun(n);
9108                 /* Not necessary. To test it:
9109                  * "false; f() { qwerty; }; echo $?" should print 0.
9110                  */
9111                 /* status = 0; */
9112  setstatus:
9113                 exitstatus = status;
9114                 break;
9115         }
9116  out:
9117         /* Order of checks below is important:
9118          * signal handlers trigger before exit caused by "set -e".
9119          */
9120         dotrap();
9121
9122         if (checkexit & status)
9123                 raise_exception(EXEXIT);
9124         if (flags & EV_EXIT)
9125                 raise_exception(EXEXIT);
9126
9127         TRACE(("leaving evaltree (no interrupts)\n"));
9128         return exitstatus;
9129 }
9130
9131 static int
9132 skiploop(void)
9133 {
9134         int skip = evalskip;
9135
9136         switch (skip) {
9137         case 0:
9138                 break;
9139         case SKIPBREAK:
9140         case SKIPCONT:
9141                 if (--skipcount <= 0) {
9142                         evalskip = 0;
9143                         break;
9144                 }
9145                 skip = SKIPBREAK;
9146                 break;
9147         }
9148         return skip;
9149 }
9150
9151 static int
9152 evalloop(union node *n, int flags)
9153 {
9154         int skip;
9155         int status;
9156
9157         loopnest++;
9158         status = 0;
9159         flags &= EV_TESTED;
9160         do {
9161                 int i;
9162
9163                 i = evaltree(n->nbinary.ch1, EV_TESTED);
9164                 skip = skiploop();
9165                 if (skip == SKIPFUNC)
9166                         status = i;
9167                 if (skip)
9168                         continue;
9169                 if (n->type != NWHILE)
9170                         i = !i;
9171                 if (i != 0)
9172                         break;
9173                 status = evaltree(n->nbinary.ch2, flags);
9174                 skip = skiploop();
9175         } while (!(skip & ~SKIPCONT));
9176         loopnest--;
9177
9178         return status;
9179 }
9180
9181 static int
9182 evalfor(union node *n, int flags)
9183 {
9184         struct arglist arglist;
9185         union node *argp;
9186         struct strlist *sp;
9187         struct stackmark smark;
9188         int status = 0;
9189
9190         errlinno = lineno = n->ncase.linno;
9191         if (funcline)
9192                 lineno -= funcline - 1;
9193
9194         setstackmark(&smark);
9195         arglist.list = NULL;
9196         arglist.lastp = &arglist.list;
9197         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
9198                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9199         }
9200         *arglist.lastp = NULL;
9201
9202         loopnest++;
9203         flags &= EV_TESTED;
9204         for (sp = arglist.list; sp; sp = sp->next) {
9205                 setvar0(n->nfor.var, sp->text);
9206                 status = evaltree(n->nfor.body, flags);
9207                 if (skiploop() & ~SKIPCONT)
9208                         break;
9209         }
9210         loopnest--;
9211         popstackmark(&smark);
9212
9213         return status;
9214 }
9215
9216 static int
9217 evalcase(union node *n, int flags)
9218 {
9219         union node *cp;
9220         union node *patp;
9221         struct arglist arglist;
9222         struct stackmark smark;
9223         int status = 0;
9224
9225         errlinno = lineno = n->ncase.linno;
9226         if (funcline)
9227                 lineno -= funcline - 1;
9228
9229         setstackmark(&smark);
9230         arglist.list = NULL;
9231         arglist.lastp = &arglist.list;
9232         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
9233         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
9234                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
9235                         if (casematch(patp, arglist.list->text)) {
9236                                 /* Ensure body is non-empty as otherwise
9237                                  * EV_EXIT may prevent us from setting the
9238                                  * exit status.
9239                                  */
9240                                 if (evalskip == 0 && cp->nclist.body) {
9241                                         status = evaltree(cp->nclist.body, flags);
9242                                 }
9243                                 goto out;
9244                         }
9245                 }
9246         }
9247  out:
9248         popstackmark(&smark);
9249
9250         return status;
9251 }
9252
9253 /*
9254  * Kick off a subshell to evaluate a tree.
9255  */
9256 static int
9257 evalsubshell(union node *n, int flags)
9258 {
9259         struct job *jp;
9260         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
9261         int status;
9262
9263         errlinno = lineno = n->nredir.linno;
9264         if (funcline)
9265                 lineno -= funcline - 1;
9266
9267         expredir(n->nredir.redirect);
9268         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
9269                 goto nofork;
9270         INT_OFF;
9271         if (backgnd == FORK_FG)
9272                 get_tty_state();
9273         jp = makejob(/*n,*/ 1);
9274         if (forkshell(jp, n, backgnd) == 0) {
9275                 /* child */
9276                 INT_ON;
9277                 flags |= EV_EXIT;
9278                 if (backgnd)
9279                         flags &= ~EV_TESTED;
9280  nofork:
9281                 redirect(n->nredir.redirect, 0);
9282                 evaltreenr(n->nredir.n, flags);
9283                 /* never returns */
9284         }
9285         /* parent */
9286         status = 0;
9287         if (backgnd == FORK_FG)
9288                 status = waitforjob(jp);
9289         INT_ON;
9290         return status;
9291 }
9292
9293 /*
9294  * Compute the names of the files in a redirection list.
9295  */
9296 static void fixredir(union node *, const char *, int);
9297 static void
9298 expredir(union node *n)
9299 {
9300         union node *redir;
9301
9302         for (redir = n; redir; redir = redir->nfile.next) {
9303                 struct arglist fn;
9304
9305                 fn.list = NULL;
9306                 fn.lastp = &fn.list;
9307                 switch (redir->type) {
9308                 case NFROMTO:
9309                 case NFROM:
9310                 case NTO:
9311 #if BASH_REDIR_OUTPUT
9312                 case NTO2:
9313 #endif
9314                 case NCLOBBER:
9315                 case NAPPEND:
9316                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9317                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9318 #if BASH_REDIR_OUTPUT
9319  store_expfname:
9320 #endif
9321 #if 0
9322 // By the design of stack allocator, the loop of this kind:
9323 //      while true; do while true; do break; done </dev/null; done
9324 // will look like a memory leak: ash plans to free expfname's
9325 // of "/dev/null" as soon as it finishes running the loop
9326 // (in this case, never).
9327 // This "fix" is wrong:
9328                         if (redir->nfile.expfname)
9329                                 stunalloc(redir->nfile.expfname);
9330 // It results in corrupted state of stacked allocations.
9331 #endif
9332                         redir->nfile.expfname = fn.list->text;
9333                         break;
9334                 case NFROMFD:
9335                 case NTOFD: /* >& */
9336                         if (redir->ndup.vname) {
9337                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9338                                 if (fn.list == NULL)
9339                                         ash_msg_and_raise_error("redir error");
9340 #if BASH_REDIR_OUTPUT
9341 //FIXME: we used expandarg with different args!
9342                                 if (!isdigit_str9(fn.list->text)) {
9343                                         /* >&file, not >&fd */
9344                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9345                                                 ash_msg_and_raise_error("redir error");
9346                                         redir->type = NTO2;
9347                                         goto store_expfname;
9348                                 }
9349 #endif
9350                                 fixredir(redir, fn.list->text, 1);
9351                         }
9352                         break;
9353                 }
9354         }
9355 }
9356
9357 /*
9358  * Evaluate a pipeline.  All the processes in the pipeline are children
9359  * of the process creating the pipeline.  (This differs from some versions
9360  * of the shell, which make the last process in a pipeline the parent
9361  * of all the rest.)
9362  */
9363 static int
9364 evalpipe(union node *n, int flags)
9365 {
9366         struct job *jp;
9367         struct nodelist *lp;
9368         int pipelen;
9369         int prevfd;
9370         int pip[2];
9371         int status = 0;
9372
9373         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9374         pipelen = 0;
9375         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9376                 pipelen++;
9377         flags |= EV_EXIT;
9378         INT_OFF;
9379         if (n->npipe.pipe_backgnd == 0)
9380                 get_tty_state();
9381         jp = makejob(/*n,*/ pipelen);
9382         prevfd = -1;
9383         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9384                 prehash(lp->n);
9385                 pip[1] = -1;
9386                 if (lp->next) {
9387                         if (pipe(pip) < 0) {
9388                                 close(prevfd);
9389                                 ash_msg_and_raise_perror("can't create pipe");
9390                         }
9391                 }
9392                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9393                         /* child */
9394                         INT_ON;
9395                         if (pip[1] >= 0) {
9396                                 close(pip[0]);
9397                         }
9398                         if (prevfd > 0) {
9399                                 dup2(prevfd, 0);
9400                                 close(prevfd);
9401                         }
9402                         if (pip[1] > 1) {
9403                                 dup2(pip[1], 1);
9404                                 close(pip[1]);
9405                         }
9406                         evaltreenr(lp->n, flags);
9407                         /* never returns */
9408                 }
9409                 /* parent */
9410                 if (prevfd >= 0)
9411                         close(prevfd);
9412                 prevfd = pip[0];
9413                 /* Don't want to trigger debugging */
9414                 if (pip[1] != -1)
9415                         close(pip[1]);
9416         }
9417         if (n->npipe.pipe_backgnd == 0) {
9418                 status = waitforjob(jp);
9419                 TRACE(("evalpipe:  job done exit status %d\n", status));
9420         }
9421         INT_ON;
9422
9423         return status;
9424 }
9425
9426 /*
9427  * Controls whether the shell is interactive or not.
9428  */
9429 static void
9430 setinteractive(int on)
9431 {
9432         static smallint is_interactive;
9433
9434         if (++on == is_interactive)
9435                 return;
9436         is_interactive = on;
9437         setsignal(SIGINT);
9438         setsignal(SIGQUIT);
9439         setsignal(SIGTERM);
9440 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9441         if (is_interactive > 1) {
9442                 /* Looks like they want an interactive shell */
9443                 static smallint did_banner;
9444
9445                 if (!did_banner) {
9446                         /* note: ash and hush share this string */
9447                         out1fmt("\n\n%s %s\n"
9448                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9449                                 "\n",
9450                                 bb_banner,
9451                                 "built-in shell (ash)"
9452                         );
9453                         did_banner = 1;
9454                 }
9455         }
9456 #endif
9457 }
9458
9459 static void
9460 optschanged(void)
9461 {
9462 #if DEBUG
9463         opentrace();
9464 #endif
9465         setinteractive(iflag);
9466         setjobctl(mflag);
9467 #if ENABLE_FEATURE_EDITING_VI
9468         if (viflag)
9469                 line_input_state->flags |= VI_MODE;
9470         else
9471                 line_input_state->flags &= ~VI_MODE;
9472 #else
9473         viflag = 0; /* forcibly keep the option off */
9474 #endif
9475 }
9476
9477 struct localvar_list {
9478         struct localvar_list *next;
9479         struct localvar *lv;
9480 };
9481
9482 static struct localvar_list *localvar_stack;
9483
9484 /*
9485  * Called after a function returns.
9486  * Interrupts must be off.
9487  */
9488 static void
9489 poplocalvars(int keep)
9490 {
9491         struct localvar_list *ll;
9492         struct localvar *lvp, *next;
9493         struct var *vp;
9494
9495         INT_OFF;
9496         ll = localvar_stack;
9497         localvar_stack = ll->next;
9498
9499         next = ll->lv;
9500         free(ll);
9501
9502         while ((lvp = next) != NULL) {
9503                 next = lvp->next;
9504                 vp = lvp->vp;
9505                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9506                 if (keep) {
9507                         int bits = VSTRFIXED;
9508
9509                         if (lvp->flags != VUNSET) {
9510                                 if (vp->var_text == lvp->text)
9511                                         bits |= VTEXTFIXED;
9512                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9513                                         free((char*)lvp->text);
9514                         }
9515
9516                         vp->flags &= ~bits;
9517                         vp->flags |= (lvp->flags & bits);
9518
9519                         if ((vp->flags &
9520                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9521                                 unsetvar(vp->var_text);
9522                 } else if (vp == NULL) {        /* $- saved */
9523                         memcpy(optlist, lvp->text, sizeof(optlist));
9524                         free((char*)lvp->text);
9525                         optschanged();
9526                 } else if (lvp->flags == VUNSET) {
9527                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9528                         unsetvar(vp->var_text);
9529                 } else {
9530                         if (vp->var_func)
9531                                 vp->var_func(var_end(lvp->text));
9532                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9533                                 free((char*)vp->var_text);
9534                         vp->flags = lvp->flags;
9535                         vp->var_text = lvp->text;
9536                 }
9537                 free(lvp);
9538         }
9539         INT_ON;
9540 }
9541
9542 /*
9543  * Create a new localvar environment.
9544  */
9545 static struct localvar_list *
9546 pushlocalvars(void)
9547 {
9548         struct localvar_list *ll;
9549
9550         INT_OFF;
9551         ll = ckzalloc(sizeof(*ll));
9552         /*ll->lv = NULL; - zalloc did it */
9553         ll->next = localvar_stack;
9554         localvar_stack = ll;
9555         INT_ON;
9556
9557         return ll->next;
9558 }
9559
9560 static void
9561 unwindlocalvars(struct localvar_list *stop)
9562 {
9563         while (localvar_stack != stop)
9564                 poplocalvars(0);
9565 }
9566
9567 static int
9568 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9569 {
9570         volatile struct shparam saveparam;
9571         struct jmploc *volatile savehandler;
9572         struct jmploc jmploc;
9573         int e;
9574         int savefuncline;
9575
9576         saveparam = shellparam;
9577         savefuncline = funcline;
9578         savehandler = exception_handler;
9579         e = setjmp(jmploc.loc);
9580         if (e) {
9581                 goto funcdone;
9582         }
9583         INT_OFF;
9584         exception_handler = &jmploc;
9585         shellparam.malloced = 0;
9586         func->count++;
9587         funcline = func->n.ndefun.linno;
9588         INT_ON;
9589         shellparam.nparam = argc - 1;
9590         shellparam.p = argv + 1;
9591 #if ENABLE_ASH_GETOPTS
9592         shellparam.optind = 1;
9593         shellparam.optoff = -1;
9594 #endif
9595         pushlocalvars();
9596         evaltree(func->n.ndefun.body, flags & EV_TESTED);
9597         poplocalvars(0);
9598  funcdone:
9599         INT_OFF;
9600         funcline = savefuncline;
9601         freefunc(func);
9602         freeparam(&shellparam);
9603         shellparam = saveparam;
9604         exception_handler = savehandler;
9605         INT_ON;
9606         evalskip &= ~SKIPFUNC;
9607         return e;
9608 }
9609
9610 /*
9611  * Make a variable a local variable.  When a variable is made local, it's
9612  * value and flags are saved in a localvar structure.  The saved values
9613  * will be restored when the shell function returns.  We handle the name
9614  * "-" as a special case: it makes changes to "set +-options" local
9615  * (options will be restored on return from the function).
9616  */
9617 static void
9618 mklocal(char *name)
9619 {
9620         struct localvar *lvp;
9621         struct var **vpp;
9622         struct var *vp;
9623         char *eq = strchr(name, '=');
9624
9625         INT_OFF;
9626         /* Cater for duplicate "local". Examples:
9627          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9628          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9629          */
9630         lvp = localvar_stack->lv;
9631         while (lvp) {
9632                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9633                         if (eq)
9634                                 setvareq(name, 0);
9635                         /* else:
9636                          * it's a duplicate "local VAR" declaration, do nothing
9637                          */
9638                         goto ret;
9639                 }
9640                 lvp = lvp->next;
9641         }
9642
9643         lvp = ckzalloc(sizeof(*lvp));
9644         if (LONE_DASH(name)) {
9645                 char *p;
9646                 p = ckmalloc(sizeof(optlist));
9647                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9648                 vp = NULL;
9649         } else {
9650                 vpp = hashvar(name);
9651                 vp = *findvar(vpp, name);
9652                 if (vp == NULL) {
9653                         /* variable did not exist yet */
9654                         if (eq)
9655                                 vp = setvareq(name, VSTRFIXED);
9656                         else
9657                                 vp = setvar(name, NULL, VSTRFIXED);
9658                         lvp->flags = VUNSET;
9659                 } else {
9660                         lvp->text = vp->var_text;
9661                         lvp->flags = vp->flags;
9662                         /* make sure neither "struct var" nor string gets freed
9663                          * during (un)setting:
9664                          */
9665                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9666                         if (eq)
9667                                 setvareq(name, 0);
9668                         else
9669                                 /* "local VAR" unsets VAR: */
9670                                 setvar0(name, NULL);
9671                 }
9672         }
9673         lvp->vp = vp;
9674         lvp->next = localvar_stack->lv;
9675         localvar_stack->lv = lvp;
9676  ret:
9677         INT_ON;
9678 }
9679
9680 /*
9681  * The "local" command.
9682  */
9683 static int FAST_FUNC
9684 localcmd(int argc UNUSED_PARAM, char **argv)
9685 {
9686         char *name;
9687
9688         if (!localvar_stack)
9689                 ash_msg_and_raise_error("not in a function");
9690
9691         argv = argptr;
9692         while ((name = *argv++) != NULL) {
9693                 mklocal(name);
9694         }
9695         return 0;
9696 }
9697
9698 static int FAST_FUNC
9699 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9700 {
9701         return 1;
9702 }
9703
9704 static int FAST_FUNC
9705 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9706 {
9707         return 0;
9708 }
9709
9710 static int FAST_FUNC
9711 execcmd(int argc UNUSED_PARAM, char **argv)
9712 {
9713         optionarg = NULL;
9714         while (nextopt("a:") != '\0')
9715                 /* nextopt() sets optionarg to "-a ARGV0" */;
9716
9717         argv = argptr;
9718         if (argv[0]) {
9719                 char *prog;
9720
9721                 iflag = 0;              /* exit on error */
9722                 mflag = 0;
9723                 optschanged();
9724                 /* We should set up signals for "exec CMD"
9725                  * the same way as for "CMD" without "exec".
9726                  * But optschanged->setinteractive->setsignal
9727                  * still thought we are a root shell. Therefore, for example,
9728                  * SIGQUIT is still set to IGN. Fix it:
9729                  */
9730                 shlvl++;
9731                 setsignal(SIGQUIT);
9732                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9733                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9734                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9735
9736                 prog = argv[0];
9737                 if (optionarg)
9738                         argv[0] = optionarg;
9739                 shellexec(prog, argv, pathval(), 0);
9740                 /* NOTREACHED */
9741         }
9742         return 0;
9743 }
9744
9745 /*
9746  * The return command.
9747  */
9748 static int FAST_FUNC
9749 returncmd(int argc UNUSED_PARAM, char **argv)
9750 {
9751         /*
9752          * If called outside a function, do what ksh does;
9753          * skip the rest of the file.
9754          */
9755         evalskip = SKIPFUNC;
9756         return argv[1] ? number(argv[1]) : exitstatus;
9757 }
9758
9759 /* Forward declarations for builtintab[] */
9760 static int breakcmd(int, char **) FAST_FUNC;
9761 static int dotcmd(int, char **) FAST_FUNC;
9762 static int evalcmd(int, char **, int) FAST_FUNC;
9763 static int exitcmd(int, char **) FAST_FUNC;
9764 static int exportcmd(int, char **) FAST_FUNC;
9765 #if ENABLE_ASH_GETOPTS
9766 static int getoptscmd(int, char **) FAST_FUNC;
9767 #endif
9768 #if ENABLE_ASH_HELP
9769 static int helpcmd(int, char **) FAST_FUNC;
9770 #endif
9771 #if MAX_HISTORY
9772 static int historycmd(int, char **) FAST_FUNC;
9773 #endif
9774 #if ENABLE_FEATURE_SH_MATH
9775 static int letcmd(int, char **) FAST_FUNC;
9776 #endif
9777 static int readcmd(int, char **) FAST_FUNC;
9778 static int setcmd(int, char **) FAST_FUNC;
9779 static int shiftcmd(int, char **) FAST_FUNC;
9780 static int timescmd(int, char **) FAST_FUNC;
9781 static int trapcmd(int, char **) FAST_FUNC;
9782 static int umaskcmd(int, char **) FAST_FUNC;
9783 static int unsetcmd(int, char **) FAST_FUNC;
9784 static int ulimitcmd(int, char **) FAST_FUNC;
9785
9786 #define BUILTIN_NOSPEC          "0"
9787 #define BUILTIN_SPECIAL         "1"
9788 #define BUILTIN_REGULAR         "2"
9789 #define BUILTIN_SPEC_REG        "3"
9790 #define BUILTIN_ASSIGN          "4"
9791 #define BUILTIN_SPEC_ASSG       "5"
9792 #define BUILTIN_REG_ASSG        "6"
9793 #define BUILTIN_SPEC_REG_ASSG   "7"
9794
9795 /* Stubs for calling non-FAST_FUNC's */
9796 #if ENABLE_ASH_ECHO
9797 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9798 #endif
9799 #if ENABLE_ASH_PRINTF
9800 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9801 #endif
9802 #if ENABLE_ASH_TEST || BASH_TEST2
9803 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9804 #endif
9805
9806 /* Keep these in proper order since it is searched via bsearch() */
9807 static const struct builtincmd builtintab[] = {
9808         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9809         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9810 #if ENABLE_ASH_TEST
9811         { BUILTIN_REGULAR       "["       , testcmd    },
9812 #endif
9813 #if BASH_TEST2
9814         { BUILTIN_REGULAR       "[["      , testcmd    },
9815 #endif
9816 #if ENABLE_ASH_ALIAS
9817         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9818 #endif
9819 #if JOBS
9820         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9821 #endif
9822         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9823         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9824         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9825 #if ENABLE_ASH_CMDCMD
9826         { BUILTIN_REGULAR       "command" , commandcmd },
9827 #endif
9828         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9829 #if ENABLE_ASH_ECHO
9830         { BUILTIN_REGULAR       "echo"    , echocmd    },
9831 #endif
9832         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9833         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9834         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9835         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9836         { BUILTIN_REGULAR       "false"   , falsecmd   },
9837 #if JOBS
9838         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9839 #endif
9840 #if ENABLE_ASH_GETOPTS
9841         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9842 #endif
9843         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9844 #if ENABLE_ASH_HELP
9845         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9846 #endif
9847 #if MAX_HISTORY
9848         { BUILTIN_NOSPEC        "history" , historycmd },
9849 #endif
9850 #if JOBS
9851         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9852         { BUILTIN_REGULAR       "kill"    , killcmd    },
9853 #endif
9854 #if ENABLE_FEATURE_SH_MATH
9855         { BUILTIN_NOSPEC        "let"     , letcmd     },
9856 #endif
9857         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9858 #if ENABLE_ASH_PRINTF
9859         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9860 #endif
9861         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9862         { BUILTIN_REGULAR       "read"    , readcmd    },
9863         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9864         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9865         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9866         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9867 #if BASH_SOURCE
9868         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9869 #endif
9870 #if ENABLE_ASH_TEST
9871         { BUILTIN_REGULAR       "test"    , testcmd    },
9872 #endif
9873         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9874         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9875         { BUILTIN_REGULAR       "true"    , truecmd    },
9876         { BUILTIN_NOSPEC        "type"    , typecmd    },
9877         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9878         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9879 #if ENABLE_ASH_ALIAS
9880         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9881 #endif
9882         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9883         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9884 };
9885
9886 /* Should match the above table! */
9887 #define COMMANDCMD (builtintab + \
9888         /* . : */       2 + \
9889         /* [ */         1 * ENABLE_ASH_TEST + \
9890         /* [[ */        1 * BASH_TEST2 + \
9891         /* alias */     1 * ENABLE_ASH_ALIAS + \
9892         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9893         /* break cd cddir  */   3)
9894 #define EVALCMD (COMMANDCMD + \
9895         /* command */   1 * ENABLE_ASH_CMDCMD + \
9896         /* continue */  1 + \
9897         /* echo */      1 * ENABLE_ASH_ECHO + \
9898         0)
9899 #define EXECCMD (EVALCMD + \
9900         /* eval */      1)
9901
9902 /*
9903  * Search the table of builtin commands.
9904  */
9905 static int
9906 pstrcmp1(const void *a, const void *b)
9907 {
9908         return strcmp((char*)a, *(char**)b + 1);
9909 }
9910 static struct builtincmd *
9911 find_builtin(const char *name)
9912 {
9913         struct builtincmd *bp;
9914
9915         bp = bsearch(
9916                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9917                 pstrcmp1
9918         );
9919         return bp;
9920 }
9921
9922 /*
9923  * Execute a simple command.
9924  */
9925 static int
9926 isassignment(const char *p)
9927 {
9928         const char *q = endofname(p);
9929         if (p == q)
9930                 return 0;
9931         return *q == '=';
9932 }
9933 static int FAST_FUNC
9934 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9935 {
9936         /* Preserve exitstatus of a previous possible redirection
9937          * as POSIX mandates */
9938         return back_exitstatus;
9939 }
9940 static int
9941 evalcommand(union node *cmd, int flags)
9942 {
9943         static const struct builtincmd null_bltin = {
9944                 "\0\0", bltincmd /* why three NULs? */
9945         };
9946         struct localvar_list *localvar_stop;
9947         struct redirtab *redir_stop;
9948         struct stackmark smark;
9949         union node *argp;
9950         struct arglist arglist;
9951         struct arglist varlist;
9952         char **argv;
9953         int argc;
9954         const struct strlist *sp;
9955         struct cmdentry cmdentry;
9956         struct job *jp;
9957         char *lastarg;
9958         const char *path;
9959         int spclbltin;
9960         int status;
9961         char **nargv;
9962         smallint cmd_is_exec;
9963
9964         errlinno = lineno = cmd->ncmd.linno;
9965         if (funcline)
9966                 lineno -= funcline - 1;
9967
9968         /* First expand the arguments. */
9969         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9970         setstackmark(&smark);
9971         localvar_stop = pushlocalvars();
9972         back_exitstatus = 0;
9973
9974         cmdentry.cmdtype = CMDBUILTIN;
9975         cmdentry.u.cmd = &null_bltin;
9976         varlist.lastp = &varlist.list;
9977         *varlist.lastp = NULL;
9978         arglist.lastp = &arglist.list;
9979         *arglist.lastp = NULL;
9980
9981         argc = 0;
9982         if (cmd->ncmd.args) {
9983                 struct builtincmd *bcmd;
9984                 smallint pseudovarflag;
9985
9986                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9987                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9988
9989                 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9990                         struct strlist **spp;
9991
9992                         spp = arglist.lastp;
9993                         if (pseudovarflag && isassignment(argp->narg.text))
9994                                 expandarg(argp, &arglist, EXP_VARTILDE);
9995                         else
9996                                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9997
9998                         for (sp = *spp; sp; sp = sp->next)
9999                                 argc++;
10000                 }
10001         }
10002
10003         /* Reserve one extra spot at the front for shellexec. */
10004         nargv = stalloc(sizeof(char *) * (argc + 2));
10005         argv = ++nargv;
10006         for (sp = arglist.list; sp; sp = sp->next) {
10007                 TRACE(("evalcommand arg: %s\n", sp->text));
10008                 *nargv++ = sp->text;
10009         }
10010         *nargv = NULL;
10011
10012         lastarg = NULL;
10013         if (iflag && funcline == 0 && argc > 0)
10014                 lastarg = nargv[-1];
10015
10016         expredir(cmd->ncmd.redirect);
10017         redir_stop = pushredir(cmd->ncmd.redirect);
10018         preverrout_fd = 2;
10019         if (BASH_XTRACEFD && xflag) {
10020                 /* NB: bash closes fd == $BASH_XTRACEFD when it is changed.
10021                  * we do not emulate this. We only use its value.
10022                  */
10023                 const char *xtracefd = lookupvar("BASH_XTRACEFD");
10024                 if (xtracefd && is_number(xtracefd))
10025                         preverrout_fd = atoi(xtracefd);
10026
10027         }
10028         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
10029
10030         path = vpath.var_text;
10031         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
10032                 struct strlist **spp;
10033                 char *p;
10034
10035                 spp = varlist.lastp;
10036                 expandarg(argp, &varlist, EXP_VARTILDE);
10037
10038                 mklocal((*spp)->text);
10039
10040                 /*
10041                  * Modify the command lookup path, if a PATH= assignment
10042                  * is present
10043                  */
10044                 p = (*spp)->text;
10045                 if (varcmp(p, path) == 0)
10046                         path = p;
10047         }
10048
10049         /* Print the command if xflag is set. */
10050         if (xflag) {
10051                 const char *pfx = "";
10052
10053                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
10054
10055                 sp = varlist.list;
10056                 while (sp) {
10057                         char *varval = sp->text;
10058                         char *eq = strchrnul(varval, '=');
10059                         if (*eq)
10060                                 eq++;
10061                         fdprintf(preverrout_fd, "%s%.*s%s",
10062                                 pfx,
10063                                 (int)(eq - varval), varval,
10064                                 maybe_single_quote(eq)
10065                         );
10066                         sp = sp->next;
10067                         pfx = " ";
10068                 }
10069
10070                 sp = arglist.list;
10071                 while (sp) {
10072                         fdprintf(preverrout_fd, "%s%s",
10073                                 pfx,
10074                                 /* always quote if matches reserved word: */
10075                                 findkwd(sp->text)
10076                                 ? single_quote(sp->text)
10077                                 : maybe_single_quote(sp->text)
10078                         );
10079                         sp = sp->next;
10080                         pfx = " ";
10081                 }
10082                 safe_write(preverrout_fd, "\n", 1);
10083         }
10084
10085         cmd_is_exec = 0;
10086         spclbltin = -1;
10087
10088         /* Now locate the command. */
10089         if (argc) {
10090                 int cmd_flag = DO_ERR;
10091 #if ENABLE_ASH_CMDCMD
10092                 const char *oldpath = path + 5;
10093 #endif
10094                 path += 5;
10095                 for (;;) {
10096                         find_command(argv[0], &cmdentry, cmd_flag, path);
10097                         if (cmdentry.cmdtype == CMDUNKNOWN) {
10098                                 flush_stdout_stderr();
10099                                 status = 127;
10100                                 goto bail;
10101                         }
10102
10103                         /* implement bltin and command here */
10104                         if (cmdentry.cmdtype != CMDBUILTIN)
10105                                 break;
10106                         if (spclbltin < 0)
10107                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
10108                         if (cmdentry.u.cmd == EXECCMD)
10109                                 cmd_is_exec = 1;
10110 #if ENABLE_ASH_CMDCMD
10111                         if (cmdentry.u.cmd == COMMANDCMD) {
10112                                 path = oldpath;
10113                                 nargv = parse_command_args(argv, &path);
10114                                 if (!nargv)
10115                                         break;
10116                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
10117                                  * nargv => "PROG". path is updated if -p.
10118                                  */
10119                                 argc -= nargv - argv;
10120                                 argv = nargv;
10121                                 cmd_flag |= DO_NOFUNC;
10122                         } else
10123 #endif
10124                                 break;
10125                 }
10126         }
10127
10128         if (status) {
10129  bail:
10130                 exitstatus = status;
10131
10132                 /* We have a redirection error. */
10133                 if (spclbltin > 0)
10134                         raise_exception(EXERROR);
10135
10136                 goto out;
10137         }
10138
10139         /* Execute the command. */
10140         switch (cmdentry.cmdtype) {
10141         default: {
10142
10143 #if ENABLE_FEATURE_SH_STANDALONE \
10144  && ENABLE_FEATURE_SH_NOFORK \
10145  && NUM_APPLETS > 1
10146 /* (1) BUG: if variables are set, we need to fork, or save/restore them
10147  *     around run_nofork_applet() call.
10148  * (2) Should this check also be done in forkshell()?
10149  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
10150  */
10151                 /* find_command() encodes applet_no as (-2 - applet_no) */
10152                 int applet_no = (- cmdentry.u.index - 2);
10153                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
10154                         char **sv_environ;
10155
10156                         INT_OFF;
10157                         sv_environ = environ;
10158                         environ = listvars(VEXPORT, VUNSET, varlist.list, /*end:*/ NULL);
10159                         /*
10160                          * Run <applet>_main().
10161                          * Signals (^C) can't interrupt here.
10162                          * Otherwise we can mangle stdio or malloc internal state.
10163                          * This makes applets which can run for a long time
10164                          * and/or wait for user input ineligible for NOFORK:
10165                          * for example, "yes" or "rm" (rm -i waits for input).
10166                          */
10167                         status = run_nofork_applet(applet_no, argv);
10168                         environ = sv_environ;
10169                         /*
10170                          * Try enabling NOFORK for "yes" applet.
10171                          * ^C _will_ stop it (write returns EINTR),
10172                          * but this causes stdout FILE to be stuck
10173                          * and needing clearerr(). What if other applets
10174                          * also can get EINTRs? Do we need to switch
10175                          * our signals to SA_RESTART?
10176                          */
10177                         /*clearerr(stdout);*/
10178                         INT_ON;
10179                         break;
10180                 }
10181 #endif
10182                 /* Can we avoid forking? For example, very last command
10183                  * in a script or a subshell does not need forking,
10184                  * we can just exec it.
10185                  */
10186                 if (!(flags & EV_EXIT) || may_have_traps) {
10187                         /* No, forking off a child is necessary */
10188                         INT_OFF;
10189                         get_tty_state();
10190                         jp = makejob(/*cmd,*/ 1);
10191                         if (forkshell(jp, cmd, FORK_FG) != 0) {
10192                                 /* parent */
10193                                 status = waitforjob(jp);
10194                                 INT_ON;
10195                                 TRACE(("forked child exited with %d\n", status));
10196                                 break;
10197                         }
10198                         /* child */
10199                         FORCE_INT_ON;
10200                         /* fall through to exec'ing external program */
10201                 }
10202                 listsetvar(varlist.list, VEXPORT|VSTACK);
10203                 shellexec(argv[0], argv, path, cmdentry.u.index);
10204                 /* NOTREACHED */
10205         } /* default */
10206         case CMDBUILTIN:
10207                 if (spclbltin > 0 || argc == 0) {
10208                         poplocalvars(1);
10209                         if (cmd_is_exec && argc > 1)
10210                                 listsetvar(varlist.list, VEXPORT);
10211                 }
10212
10213                 /* Tight loop with builtins only:
10214                  * "while kill -0 $child; do true; done"
10215                  * will never exit even if $child died, unless we do this
10216                  * to reap the zombie and make kill detect that it's gone: */
10217                 dowait(DOWAIT_NONBLOCK, NULL);
10218
10219                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
10220                         if (exception_type == EXERROR && spclbltin <= 0) {
10221                                 FORCE_INT_ON;
10222                                 goto readstatus;
10223                         }
10224  raise:
10225                         longjmp(exception_handler->loc, 1);
10226                 }
10227                 goto readstatus;
10228
10229         case CMDFUNCTION:
10230                 poplocalvars(1);
10231                 /* See above for the rationale */
10232                 dowait(DOWAIT_NONBLOCK, NULL);
10233                 if (evalfun(cmdentry.u.func, argc, argv, flags))
10234                         goto raise;
10235  readstatus:
10236                 status = exitstatus;
10237                 break;
10238         } /* switch */
10239
10240  out:
10241         if (cmd->ncmd.redirect)
10242                 popredir(/*drop:*/ cmd_is_exec);
10243         unwindredir(redir_stop);
10244         unwindlocalvars(localvar_stop);
10245         if (lastarg) {
10246                 /* dsl: I think this is intended to be used to support
10247                  * '_' in 'vi' command mode during line editing...
10248                  * However I implemented that within libedit itself.
10249                  */
10250                 setvar0("_", lastarg);
10251         }
10252         popstackmark(&smark);
10253
10254         return status;
10255 }
10256
10257 static int
10258 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
10259 {
10260         char *volatile savecmdname;
10261         struct jmploc *volatile savehandler;
10262         struct jmploc jmploc;
10263         int status;
10264         int i;
10265
10266         savecmdname = commandname;
10267         savehandler = exception_handler;
10268         i = setjmp(jmploc.loc);
10269         if (i)
10270                 goto cmddone;
10271         exception_handler = &jmploc;
10272         commandname = argv[0];
10273         argptr = argv + 1;
10274         optptr = NULL;                  /* initialize nextopt */
10275         if (cmd == EVALCMD)
10276                 status = evalcmd(argc, argv, flags);
10277         else
10278                 status = (*cmd->builtin)(argc, argv);
10279         flush_stdout_stderr();
10280         status |= ferror(stdout);
10281         exitstatus = status;
10282  cmddone:
10283         clearerr(stdout);
10284         commandname = savecmdname;
10285         exception_handler = savehandler;
10286
10287         return i;
10288 }
10289
10290 static int
10291 goodname(const char *p)
10292 {
10293         return endofname(p)[0] == '\0';
10294 }
10295
10296
10297 /*
10298  * Search for a command.  This is called before we fork so that the
10299  * location of the command will be available in the parent as well as
10300  * the child.  The check for "goodname" is an overly conservative
10301  * check that the name will not be subject to expansion.
10302  */
10303 static void
10304 prehash(union node *n)
10305 {
10306         struct cmdentry entry;
10307
10308         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
10309                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
10310 }
10311
10312
10313 /* ============ Builtin commands
10314  *
10315  * Builtin commands whose functions are closely tied to evaluation
10316  * are implemented here.
10317  */
10318
10319 /*
10320  * Handle break and continue commands.  Break, continue, and return are
10321  * all handled by setting the evalskip flag.  The evaluation routines
10322  * above all check this flag, and if it is set they start skipping
10323  * commands rather than executing them.  The variable skipcount is
10324  * the number of loops to break/continue, or the number of function
10325  * levels to return.  (The latter is always 1.)  It should probably
10326  * be an error to break out of more loops than exist, but it isn't
10327  * in the standard shell so we don't make it one here.
10328  */
10329 static int FAST_FUNC
10330 breakcmd(int argc UNUSED_PARAM, char **argv)
10331 {
10332         int n = argv[1] ? number(argv[1]) : 1;
10333
10334         if (n <= 0)
10335                 ash_msg_and_raise_error(msg_illnum, argv[1]);
10336         if (n > loopnest)
10337                 n = loopnest;
10338         if (n > 0) {
10339                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
10340                 skipcount = n;
10341         }
10342         return 0;
10343 }
10344
10345
10346 /*
10347  * This implements the input routines used by the parser.
10348  */
10349
10350 enum {
10351         INPUT_PUSH_FILE = 1,
10352         INPUT_NOFILE_OK = 2,
10353 };
10354
10355 static smallint checkkwd;
10356 /* values of checkkwd variable */
10357 #define CHKALIAS        0x1
10358 #define CHKKWD          0x2
10359 #define CHKNL           0x4
10360 #define CHKEOFMARK      0x8
10361
10362 /*
10363  * Push a string back onto the input at this current parsefile level.
10364  * We handle aliases this way.
10365  */
10366 #if !ENABLE_ASH_ALIAS
10367 #define pushstring(s, ap) pushstring(s)
10368 #endif
10369 static void
10370 pushstring(char *s, struct alias *ap)
10371 {
10372         struct strpush *sp;
10373         int len;
10374
10375         len = strlen(s);
10376         INT_OFF;
10377         if (g_parsefile->strpush) {
10378                 sp = ckzalloc(sizeof(*sp));
10379                 sp->prev = g_parsefile->strpush;
10380         } else {
10381                 sp = &(g_parsefile->basestrpush);
10382         }
10383         g_parsefile->strpush = sp;
10384         sp->prev_string = g_parsefile->next_to_pgetc;
10385         sp->prev_left_in_line = g_parsefile->left_in_line;
10386         sp->unget = g_parsefile->unget;
10387         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10388 #if ENABLE_ASH_ALIAS
10389         sp->ap = ap;
10390         if (ap) {
10391                 ap->flag |= ALIASINUSE;
10392                 sp->string = s;
10393         }
10394 #endif
10395         g_parsefile->next_to_pgetc = s;
10396         g_parsefile->left_in_line = len;
10397         g_parsefile->unget = 0;
10398         INT_ON;
10399 }
10400
10401 static void
10402 popstring(void)
10403 {
10404         struct strpush *sp = g_parsefile->strpush;
10405
10406         INT_OFF;
10407 #if ENABLE_ASH_ALIAS
10408         if (sp->ap) {
10409                 if (g_parsefile->next_to_pgetc[-1] == ' '
10410                  || g_parsefile->next_to_pgetc[-1] == '\t'
10411                 ) {
10412                         checkkwd |= CHKALIAS;
10413                 }
10414                 if (sp->string != sp->ap->val) {
10415                         free(sp->string);
10416                 }
10417                 sp->ap->flag &= ~ALIASINUSE;
10418                 if (sp->ap->flag & ALIASDEAD) {
10419                         unalias(sp->ap->name);
10420                 }
10421         }
10422 #endif
10423         g_parsefile->next_to_pgetc = sp->prev_string;
10424         g_parsefile->left_in_line = sp->prev_left_in_line;
10425         g_parsefile->unget = sp->unget;
10426         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10427         g_parsefile->strpush = sp->prev;
10428         if (sp != &(g_parsefile->basestrpush))
10429                 free(sp);
10430         INT_ON;
10431 }
10432
10433 static int
10434 preadfd(void)
10435 {
10436         int nr;
10437         char *buf = g_parsefile->buf;
10438
10439         g_parsefile->next_to_pgetc = buf;
10440 #if ENABLE_FEATURE_EDITING
10441  retry:
10442         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10443                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10444         else {
10445 # if ENABLE_ASH_IDLE_TIMEOUT
10446                 int timeout = -1;
10447                 if (iflag) {
10448                         const char *tmout_var = lookupvar("TMOUT");
10449                         if (tmout_var) {
10450                                 timeout = atoi(tmout_var) * 1000;
10451                                 if (timeout <= 0)
10452                                         timeout = -1;
10453                         }
10454                 }
10455                 line_input_state->timeout = timeout;
10456 # endif
10457 # if ENABLE_FEATURE_TAB_COMPLETION
10458                 line_input_state->path_lookup = pathval();
10459 # endif
10460                 reinit_unicode_for_ash();
10461                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ);
10462                 if (nr == 0) {
10463                         /* ^C pressed, "convert" to SIGINT */
10464                         write(STDOUT_FILENO, "^C", 2);
10465                         if (trap[SIGINT]) {
10466                                 buf[0] = '\n';
10467                                 buf[1] = '\0';
10468                                 raise(SIGINT);
10469                                 return 1;
10470                         }
10471                         exitstatus = 128 + SIGINT;
10472                         bb_putchar('\n');
10473                         goto retry;
10474                 }
10475                 if (nr < 0) {
10476                         if (errno == 0) {
10477                                 /* Ctrl+D pressed */
10478                                 nr = 0;
10479                         }
10480 # if ENABLE_ASH_IDLE_TIMEOUT
10481                         else if (errno == EAGAIN && timeout > 0) {
10482                                 puts("\007timed out waiting for input: auto-logout");
10483                                 exitshell();
10484                         }
10485 # endif
10486                 }
10487         }
10488 #else
10489         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10490 #endif
10491
10492 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10493         if (nr < 0) {
10494                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10495                         int flags = fcntl(0, F_GETFL);
10496                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10497                                 flags &= ~O_NONBLOCK;
10498                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10499                                         out2str("sh: turning off NDELAY mode\n");
10500                                         goto retry;
10501                                 }
10502                         }
10503                 }
10504         }
10505 #endif
10506         return nr;
10507 }
10508
10509 /*
10510  * Refill the input buffer and return the next input character:
10511  *
10512  * 1) If a string was pushed back on the input, pop it;
10513  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10514  *    or we are reading from a string so we can't refill the buffer,
10515  *    return EOF.
10516  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10517  * 4) Process input up to the next newline, deleting nul characters.
10518  */
10519 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10520 #define pgetc_debug(...) ((void)0)
10521 static int pgetc(void);
10522 static int
10523 preadbuffer(void)
10524 {
10525         char *q;
10526         int more;
10527
10528         if (g_parsefile->strpush) {
10529 #if ENABLE_ASH_ALIAS
10530                 if (g_parsefile->left_in_line == -1
10531                  && g_parsefile->strpush->ap
10532                  && g_parsefile->next_to_pgetc[-1] != ' '
10533                  && g_parsefile->next_to_pgetc[-1] != '\t'
10534                 ) {
10535                         pgetc_debug("preadbuffer PEOA");
10536                         return PEOA;
10537                 }
10538 #endif
10539                 popstring();
10540                 return pgetc();
10541         }
10542         /* on both branches above g_parsefile->left_in_line < 0.
10543          * "pgetc" needs refilling.
10544          */
10545
10546         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10547          * pungetc() may increment it a few times.
10548          * Assuming it won't increment it to less than -90.
10549          */
10550         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10551                 pgetc_debug("preadbuffer PEOF1");
10552                 /* even in failure keep left_in_line and next_to_pgetc
10553                  * in lock step, for correct multi-layer pungetc.
10554                  * left_in_line was decremented before preadbuffer(),
10555                  * must inc next_to_pgetc: */
10556                 g_parsefile->next_to_pgetc++;
10557                 return PEOF;
10558         }
10559
10560         more = g_parsefile->left_in_buffer;
10561         if (more <= 0) {
10562                 flush_stdout_stderr();
10563  again:
10564                 more = preadfd();
10565                 if (more <= 0) {
10566                         /* don't try reading again */
10567                         g_parsefile->left_in_line = -99;
10568                         pgetc_debug("preadbuffer PEOF2");
10569                         g_parsefile->next_to_pgetc++;
10570                         return PEOF;
10571                 }
10572         }
10573
10574         /* Find out where's the end of line.
10575          * Set g_parsefile->left_in_line
10576          * and g_parsefile->left_in_buffer acordingly.
10577          * NUL chars are deleted.
10578          */
10579         q = g_parsefile->next_to_pgetc;
10580         for (;;) {
10581                 char c;
10582
10583                 more--;
10584
10585                 c = *q;
10586                 if (c == '\0') {
10587                         memmove(q, q + 1, more);
10588                 } else {
10589                         q++;
10590                         if (c == '\n') {
10591                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10592                                 break;
10593                         }
10594                 }
10595
10596                 if (more <= 0) {
10597                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10598                         if (g_parsefile->left_in_line < 0)
10599                                 goto again;
10600                         break;
10601                 }
10602         }
10603         g_parsefile->left_in_buffer = more;
10604
10605         if (vflag) {
10606                 char save = *q;
10607                 *q = '\0';
10608                 out2str(g_parsefile->next_to_pgetc);
10609                 *q = save;
10610         }
10611
10612         pgetc_debug("preadbuffer at %d:%p'%s'",
10613                         g_parsefile->left_in_line,
10614                         g_parsefile->next_to_pgetc,
10615                         g_parsefile->next_to_pgetc);
10616         return (unsigned char)*g_parsefile->next_to_pgetc++;
10617 }
10618
10619 static void
10620 nlprompt(void)
10621 {
10622         g_parsefile->linno++;
10623         setprompt_if(doprompt, 2);
10624 }
10625 static void
10626 nlnoprompt(void)
10627 {
10628         g_parsefile->linno++;
10629         needprompt = doprompt;
10630 }
10631
10632 static int
10633 pgetc(void)
10634 {
10635         int c;
10636
10637         pgetc_debug("pgetc at %d:%p'%s'",
10638                         g_parsefile->left_in_line,
10639                         g_parsefile->next_to_pgetc,
10640                         g_parsefile->next_to_pgetc);
10641         if (g_parsefile->unget)
10642                 return g_parsefile->lastc[--g_parsefile->unget];
10643
10644         if (--g_parsefile->left_in_line >= 0)
10645                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10646         else
10647                 c = preadbuffer();
10648
10649         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10650         g_parsefile->lastc[0] = c;
10651
10652         return c;
10653 }
10654
10655 #if ENABLE_ASH_ALIAS
10656 static int
10657 pgetc_without_PEOA(void)
10658 {
10659         int c;
10660         do {
10661                 pgetc_debug("pgetc at %d:%p'%s'",
10662                                 g_parsefile->left_in_line,
10663                                 g_parsefile->next_to_pgetc,
10664                                 g_parsefile->next_to_pgetc);
10665                 c = pgetc();
10666         } while (c == PEOA);
10667         return c;
10668 }
10669 #else
10670 # define pgetc_without_PEOA() pgetc()
10671 #endif
10672
10673 /*
10674  * Undo a call to pgetc.  Only two characters may be pushed back.
10675  * PEOF may be pushed back.
10676  */
10677 static void
10678 pungetc(void)
10679 {
10680         g_parsefile->unget++;
10681 }
10682
10683 /* This one eats backslash+newline */
10684 static int
10685 pgetc_eatbnl(void)
10686 {
10687         int c;
10688
10689         while ((c = pgetc()) == '\\') {
10690                 if (pgetc() != '\n') {
10691                         pungetc();
10692                         break;
10693                 }
10694
10695                 nlprompt();
10696         }
10697
10698         return c;
10699 }
10700
10701 struct synstack {
10702         smalluint syntax;
10703         uint8_t innerdq   :1;
10704         uint8_t varpushed :1;
10705         uint8_t dblquote  :1;
10706         int varnest;            /* levels of variables expansion */
10707         int dqvarnest;          /* levels of variables expansion within double quotes */
10708         int parenlevel;         /* levels of parens in arithmetic */
10709         struct synstack *prev;
10710         struct synstack *next;
10711 };
10712
10713 static void
10714 synstack_push(struct synstack **stack, struct synstack *next, int syntax)
10715 {
10716         memset(next, 0, sizeof(*next));
10717         next->syntax = syntax;
10718         next->next = *stack;
10719         (*stack)->prev = next;
10720         *stack = next;
10721 }
10722
10723 static ALWAYS_INLINE void
10724 synstack_pop(struct synstack **stack)
10725 {
10726         *stack = (*stack)->next;
10727 }
10728
10729 /*
10730  * To handle the "." command, a stack of input files is used.  Pushfile
10731  * adds a new entry to the stack and popfile restores the previous level.
10732  */
10733 static void
10734 pushfile(void)
10735 {
10736         struct parsefile *pf;
10737
10738         pf = ckzalloc(sizeof(*pf));
10739         pf->prev = g_parsefile;
10740         pf->pf_fd = -1;
10741         /*pf->strpush = NULL; - ckzalloc did it */
10742         /*pf->basestrpush.prev = NULL;*/
10743         /*pf->unget = 0;*/
10744         g_parsefile = pf;
10745 }
10746
10747 static void
10748 popfile(void)
10749 {
10750         struct parsefile *pf = g_parsefile;
10751
10752         if (pf == &basepf)
10753                 return;
10754
10755         INT_OFF;
10756         if (pf->pf_fd >= 0)
10757                 close(pf->pf_fd);
10758         free(pf->buf);
10759         while (pf->strpush)
10760                 popstring();
10761         g_parsefile = pf->prev;
10762         free(pf);
10763         INT_ON;
10764 }
10765
10766 /*
10767  * Return to top level.
10768  */
10769 static void
10770 popallfiles(void)
10771 {
10772         while (g_parsefile != &basepf)
10773                 popfile();
10774 }
10775
10776 /*
10777  * Close the file(s) that the shell is reading commands from.  Called
10778  * after a fork is done.
10779  */
10780 static void
10781 closescript(void)
10782 {
10783         popallfiles();
10784         if (g_parsefile->pf_fd > 0) {
10785                 close(g_parsefile->pf_fd);
10786                 g_parsefile->pf_fd = 0;
10787         }
10788 }
10789
10790 /*
10791  * Like setinputfile, but takes an open file descriptor.  Call this with
10792  * interrupts off.
10793  */
10794 static void
10795 setinputfd(int fd, int push)
10796 {
10797         if (push) {
10798                 pushfile();
10799                 g_parsefile->buf = NULL;
10800         }
10801         g_parsefile->pf_fd = fd;
10802         if (g_parsefile->buf == NULL)
10803                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10804         g_parsefile->left_in_buffer = 0;
10805         g_parsefile->left_in_line = 0;
10806         g_parsefile->linno = 1;
10807 }
10808
10809 /*
10810  * Set the input to take input from a file.  If push is set, push the
10811  * old input onto the stack first.
10812  */
10813 static int
10814 setinputfile(const char *fname, int flags)
10815 {
10816         int fd;
10817
10818         INT_OFF;
10819         fd = open(fname, O_RDONLY | O_CLOEXEC);
10820         if (fd < 0) {
10821                 if (flags & INPUT_NOFILE_OK)
10822                         goto out;
10823                 exitstatus = 127;
10824                 ash_msg_and_raise_perror("can't open '%s'", fname);
10825         }
10826         if (fd < 10)
10827                 fd = savefd(fd);
10828         else if (O_CLOEXEC == 0) /* old libc */
10829                 close_on_exec_on(fd);
10830
10831         setinputfd(fd, flags & INPUT_PUSH_FILE);
10832  out:
10833         INT_ON;
10834         return fd;
10835 }
10836
10837 /*
10838  * Like setinputfile, but takes input from a string.
10839  */
10840 static void
10841 setinputstring(char *string)
10842 {
10843         INT_OFF;
10844         pushfile();
10845         g_parsefile->next_to_pgetc = string;
10846         g_parsefile->left_in_line = strlen(string);
10847         g_parsefile->buf = NULL;
10848         g_parsefile->linno = 1;
10849         INT_ON;
10850 }
10851
10852
10853 /*
10854  * Routines to check for mail.
10855  */
10856
10857 #if ENABLE_ASH_MAIL
10858
10859 /* Hash of mtimes of mailboxes */
10860 static unsigned mailtime_hash;
10861 /* Set if MAIL or MAILPATH is changed. */
10862 static smallint mail_var_path_changed;
10863
10864 /*
10865  * Print appropriate message(s) if mail has arrived.
10866  * If mail_var_path_changed is set,
10867  * then the value of MAIL has mail_var_path_changed,
10868  * so we just update the values.
10869  */
10870 static void
10871 chkmail(void)
10872 {
10873         const char *mpath;
10874         char *p;
10875         char *q;
10876         unsigned new_hash;
10877         struct stackmark smark;
10878         struct stat statb;
10879
10880         setstackmark(&smark);
10881         mpath = mpathset() ? mpathval() : mailval();
10882         new_hash = 0;
10883         for (;;) {
10884                 p = path_advance(&mpath, nullstr);
10885                 if (p == NULL)
10886                         break;
10887                 if (*p == '\0')
10888                         continue;
10889                 for (q = p; *q; q++)
10890                         continue;
10891 #if DEBUG
10892                 if (q[-1] != '/')
10893                         abort();
10894 #endif
10895                 q[-1] = '\0';                   /* delete trailing '/' */
10896                 if (stat(p, &statb) < 0) {
10897                         continue;
10898                 }
10899                 /* Very simplistic "hash": just a sum of all mtimes */
10900                 new_hash += (unsigned)statb.st_mtime;
10901         }
10902         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10903                 if (mailtime_hash != 0)
10904                         out2str("you have mail\n");
10905                 mailtime_hash = new_hash;
10906         }
10907         mail_var_path_changed = 0;
10908         popstackmark(&smark);
10909 }
10910
10911 static void FAST_FUNC
10912 changemail(const char *val UNUSED_PARAM)
10913 {
10914         mail_var_path_changed = 1;
10915 }
10916
10917 #endif /* ASH_MAIL */
10918
10919
10920 /* ============ ??? */
10921
10922 /*
10923  * Set the shell parameters.
10924  */
10925 static void
10926 setparam(char **argv)
10927 {
10928         char **newparam;
10929         char **ap;
10930         int nparam;
10931
10932         for (nparam = 0; argv[nparam]; nparam++)
10933                 continue;
10934         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10935         while (*argv) {
10936                 *ap++ = ckstrdup(*argv++);
10937         }
10938         *ap = NULL;
10939         freeparam(&shellparam);
10940         shellparam.malloced = 1;
10941         shellparam.nparam = nparam;
10942         shellparam.p = newparam;
10943 #if ENABLE_ASH_GETOPTS
10944         shellparam.optind = 1;
10945         shellparam.optoff = -1;
10946 #endif
10947 }
10948
10949 /*
10950  * Process shell options.  The global variable argptr contains a pointer
10951  * to the argument list; we advance it past the options.
10952  *
10953  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10954  * For a non-interactive shell, an error condition encountered
10955  * by a special built-in ... shall cause the shell to write a diagnostic message
10956  * to standard error and exit as shown in the following table:
10957  * Error                                           Special Built-In
10958  * ...
10959  * Utility syntax error (option or operand error)  Shall exit
10960  * ...
10961  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10962  * we see that bash does not do that (set "finishes" with error code 1 instead,
10963  * and shell continues), and people rely on this behavior!
10964  * Testcase:
10965  * set -o barfoo 2>/dev/null
10966  * echo $?
10967  *
10968  * Oh well. Let's mimic that.
10969  */
10970 static int
10971 plus_minus_o(char *name, int val)
10972 {
10973         int i;
10974
10975         if (name) {
10976                 for (i = 0; i < NOPTS; i++) {
10977                         if (strcmp(name, optnames(i)) == 0) {
10978                                 optlist[i] = val;
10979                                 return 0;
10980                         }
10981                 }
10982                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10983                 return 1;
10984         }
10985         for (i = 0; i < NOPTS; i++) {
10986                 if (val) {
10987                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10988                 } else {
10989                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10990                 }
10991         }
10992         return 0;
10993 }
10994 static void
10995 setoption(int flag, int val)
10996 {
10997         int i;
10998
10999         for (i = 0; i < NOPTS; i++) {
11000                 if (optletters(i) == flag) {
11001                         optlist[i] = val;
11002                         return;
11003                 }
11004         }
11005         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
11006         /* NOTREACHED */
11007 }
11008 static int
11009 options(int cmdline, int *login_sh)
11010 {
11011         char *p;
11012         int val;
11013         int c;
11014
11015         if (cmdline)
11016                 minusc = NULL;
11017         while ((p = *argptr) != NULL) {
11018                 c = *p++;
11019                 if (c != '-' && c != '+')
11020                         break;
11021                 argptr++;
11022                 val = 0; /* val = 0 if c == '+' */
11023                 if (c == '-') {
11024                         val = 1;
11025                         if (p[0] == '\0' || LONE_DASH(p)) {
11026                                 if (!cmdline) {
11027                                         /* "-" means turn off -x and -v */
11028                                         if (p[0] == '\0')
11029                                                 xflag = vflag = 0;
11030                                         /* "--" means reset params */
11031                                         else if (*argptr == NULL)
11032                                                 setparam(argptr);
11033                                 }
11034                                 break;    /* "-" or "--" terminates options */
11035                         }
11036                 }
11037                 /* first char was + or - */
11038                 while ((c = *p++) != '\0') {
11039                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
11040                         if (c == 'c' && cmdline) {
11041                                 minusc = p;     /* command is after shell args */
11042                         } else if (c == 'o') {
11043                                 if (plus_minus_o(*argptr, val)) {
11044                                         /* it already printed err message */
11045                                         return 1; /* error */
11046                                 }
11047                                 if (*argptr)
11048                                         argptr++;
11049                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
11050                                 if (login_sh)
11051                                         *login_sh = 1;
11052                         /* bash does not accept +-login, we also won't */
11053                         } else if (cmdline && val && (c == '-')) { /* long options */
11054                                 if (strcmp(p, "login") == 0) {
11055                                         if (login_sh)
11056                                                 *login_sh = 1;
11057                                 }
11058                                 break;
11059                         } else {
11060                                 setoption(c, val);
11061                         }
11062                 }
11063         }
11064         return 0;
11065 }
11066
11067 /*
11068  * The shift builtin command.
11069  */
11070 static int FAST_FUNC
11071 shiftcmd(int argc UNUSED_PARAM, char **argv)
11072 {
11073         int n;
11074         char **ap1, **ap2;
11075
11076         n = 1;
11077         if (argv[1])
11078                 n = number(argv[1]);
11079         if (n > shellparam.nparam)
11080                 return 1;
11081         INT_OFF;
11082         shellparam.nparam -= n;
11083         for (ap1 = shellparam.p; --n >= 0; ap1++) {
11084                 if (shellparam.malloced)
11085                         free(*ap1);
11086         }
11087         ap2 = shellparam.p;
11088         while ((*ap2++ = *ap1++) != NULL)
11089                 continue;
11090 #if ENABLE_ASH_GETOPTS
11091         shellparam.optind = 1;
11092         shellparam.optoff = -1;
11093 #endif
11094         INT_ON;
11095         return 0;
11096 }
11097
11098 /*
11099  * POSIX requires that 'set' (but not export or readonly) output the
11100  * variables in lexicographic order - by the locale's collating order (sigh).
11101  * Maybe we could keep them in an ordered balanced binary tree
11102  * instead of hashed lists.
11103  * For now just roll 'em through qsort for printing...
11104  */
11105 static int
11106 showvars(const char *sep_prefix, int on, int off)
11107 {
11108         const char *sep;
11109         char **ep, **epend;
11110
11111         ep = listvars(on, off, /*strlist:*/ NULL, &epend);
11112         qsort(ep, epend - ep, sizeof(char *), vpcmp);
11113
11114         sep = *sep_prefix ? " " : sep_prefix;
11115
11116         for (; ep < epend; ep++) {
11117                 const char *p;
11118                 const char *q;
11119
11120                 p = endofname(*ep);
11121 /* Used to have simple "p = strchrnul(*ep, '=')" here instead, but this
11122  * makes "export -p" to have output not suitable for "eval":
11123  * import os
11124  * os.environ["test-test"]="test"
11125  * if os.fork() == 0:
11126  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
11127  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])
11128  */
11129                 q = nullstr;
11130                 if (*p == '=')
11131                         q = single_quote(++p);
11132                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
11133         }
11134         return 0;
11135 }
11136
11137 /*
11138  * The set command builtin.
11139  */
11140 static int FAST_FUNC
11141 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
11142 {
11143         int retval;
11144
11145         if (!argv[1])
11146                 return showvars(nullstr, 0, VUNSET);
11147
11148         INT_OFF;
11149         retval = options(/*cmdline:*/ 0, NULL);
11150         if (retval == 0) { /* if no parse error... */
11151                 optschanged();
11152                 if (*argptr != NULL) {
11153                         setparam(argptr);
11154                 }
11155         }
11156         INT_ON;
11157         return retval;
11158 }
11159
11160 #if ENABLE_ASH_RANDOM_SUPPORT
11161 static void FAST_FUNC
11162 change_random(const char *value)
11163 {
11164         uint32_t t;
11165
11166         if (value == NULL) {
11167                 /* "get", generate */
11168                 t = next_random(&random_gen);
11169                 /* set without recursion */
11170                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
11171                 vrandom.flags &= ~VNOFUNC;
11172         } else {
11173                 /* set/reset */
11174                 t = strtoul(value, NULL, 10);
11175                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
11176         }
11177 }
11178 #endif
11179
11180 #if ENABLE_ASH_GETOPTS
11181 static int
11182 getopts(char *optstr, char *optvar, char **optfirst)
11183 {
11184         char *p, *q;
11185         char c = '?';
11186         int done = 0;
11187         char sbuf[2];
11188         char **optnext;
11189         int ind = shellparam.optind;
11190         int off = shellparam.optoff;
11191
11192         sbuf[1] = '\0';
11193
11194         shellparam.optind = -1;
11195         optnext = optfirst + ind - 1;
11196
11197         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
11198                 p = NULL;
11199         else
11200                 p = optnext[-1] + off;
11201         if (p == NULL || *p == '\0') {
11202                 /* Current word is done, advance */
11203                 p = *optnext;
11204                 if (p == NULL || *p != '-' || *++p == '\0') {
11205  atend:
11206                         unsetvar("OPTARG");
11207                         p = NULL;
11208                         done = 1;
11209                         goto out;
11210                 }
11211                 optnext++;
11212                 if (LONE_DASH(p))        /* check for "--" */
11213                         goto atend;
11214         }
11215
11216         c = *p++;
11217         for (q = optstr; *q != c;) {
11218                 if (*q == '\0') {
11219                         /* OPTERR is a bashism */
11220                         const char *cp = lookupvar("OPTERR");
11221                         if ((cp && LONE_CHAR(cp, '0'))
11222                          || (optstr[0] == ':')
11223                         ) {
11224                                 sbuf[0] = c;
11225                                 /*sbuf[1] = '\0'; - already is */
11226                                 setvar0("OPTARG", sbuf);
11227                         } else {
11228                                 fprintf(stderr, "Illegal option -%c\n", c);
11229                                 unsetvar("OPTARG");
11230                         }
11231                         c = '?';
11232                         goto out;
11233                 }
11234                 if (*++q == ':')
11235                         q++;
11236         }
11237
11238         if (*++q == ':') {
11239                 if (*p == '\0' && (p = *optnext) == NULL) {
11240                         /* OPTERR is a bashism */
11241                         const char *cp = lookupvar("OPTERR");
11242                         if ((cp && LONE_CHAR(cp, '0'))
11243                          || (optstr[0] == ':')
11244                         ) {
11245                                 sbuf[0] = c;
11246                                 /*sbuf[1] = '\0'; - already is */
11247                                 setvar0("OPTARG", sbuf);
11248                                 c = ':';
11249                         } else {
11250                                 fprintf(stderr, "No arg for -%c option\n", c);
11251                                 unsetvar("OPTARG");
11252                                 c = '?';
11253                         }
11254                         goto out;
11255                 }
11256
11257                 if (p == *optnext)
11258                         optnext++;
11259                 setvar0("OPTARG", p);
11260                 p = NULL;
11261         } else
11262                 setvar0("OPTARG", nullstr);
11263  out:
11264         ind = optnext - optfirst + 1;
11265         setvar("OPTIND", itoa(ind), VNOFUNC);
11266         sbuf[0] = c;
11267         /*sbuf[1] = '\0'; - already is */
11268         setvar0(optvar, sbuf);
11269
11270         shellparam.optoff = p ? p - *(optnext - 1) : -1;
11271         shellparam.optind = ind;
11272
11273         return done;
11274 }
11275
11276 /*
11277  * The getopts builtin.  Shellparam.optnext points to the next argument
11278  * to be processed.  Shellparam.optptr points to the next character to
11279  * be processed in the current argument.  If shellparam.optnext is NULL,
11280  * then it's the first time getopts has been called.
11281  */
11282 static int FAST_FUNC
11283 getoptscmd(int argc, char **argv)
11284 {
11285         char **optbase;
11286
11287         if (argc < 3)
11288                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
11289         if (argc == 3) {
11290                 optbase = shellparam.p;
11291                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
11292                         shellparam.optind = 1;
11293                         shellparam.optoff = -1;
11294                 }
11295         } else {
11296                 optbase = &argv[3];
11297                 if ((unsigned)shellparam.optind > argc - 2) {
11298                         shellparam.optind = 1;
11299                         shellparam.optoff = -1;
11300                 }
11301         }
11302
11303         return getopts(argv[1], argv[2], optbase);
11304 }
11305 #endif /* ASH_GETOPTS */
11306
11307
11308 /* ============ Shell parser */
11309
11310 struct heredoc {
11311         struct heredoc *next;   /* next here document in list */
11312         union node *here;       /* redirection node */
11313         char *eofmark;          /* string indicating end of input */
11314         smallint striptabs;     /* if set, strip leading tabs */
11315 };
11316
11317 static smallint tokpushback;           /* last token pushed back */
11318 static smallint quoteflag;             /* set if (part of) last token was quoted */
11319 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
11320 static struct heredoc *heredoclist;    /* list of here documents to read */
11321 static char *wordtext;                 /* text of last word returned by readtoken */
11322 static struct nodelist *backquotelist;
11323 static union node *redirnode;
11324 static struct heredoc *heredoc;
11325
11326 static const char *
11327 tokname(char *buf, int tok)
11328 {
11329         if (tok < TSEMI)
11330                 return tokname_array[tok];
11331         sprintf(buf, "\"%s\"", tokname_array[tok]);
11332         return buf;
11333 }
11334
11335 /* raise_error_unexpected_syntax:
11336  * Called when an unexpected token is read during the parse.  The argument
11337  * is the token that is expected, or -1 if more than one type of token can
11338  * occur at this point.
11339  */
11340 static void raise_error_unexpected_syntax(int) NORETURN;
11341 static void
11342 raise_error_unexpected_syntax(int token)
11343 {
11344         char msg[64];
11345         char buf[16];
11346         int l;
11347
11348         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
11349         if (token >= 0)
11350                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
11351         raise_error_syntax(msg);
11352         /* NOTREACHED */
11353 }
11354
11355 /* parsing is heavily cross-recursive, need these forward decls */
11356 static union node *andor(void);
11357 static union node *pipeline(void);
11358 static union node *parse_command(void);
11359 static void parseheredoc(void);
11360 static int peektoken(void);
11361 static int readtoken(void);
11362
11363 static union node *
11364 list(int nlflag)
11365 {
11366         union node *n1, *n2, *n3;
11367         int tok;
11368
11369         n1 = NULL;
11370         for (;;) {
11371                 switch (peektoken()) {
11372                 case TNL:
11373                         if (!(nlflag & 1))
11374                                 break;
11375                         parseheredoc();
11376                         return n1;
11377
11378                 case TEOF:
11379                         if (!n1 && (nlflag & 1))
11380                                 n1 = NODE_EOF;
11381                         parseheredoc();
11382                         return n1;
11383                 }
11384
11385                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11386                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
11387                         return n1;
11388                 nlflag |= 2;
11389
11390                 n2 = andor();
11391                 tok = readtoken();
11392                 if (tok == TBACKGND) {
11393                         if (n2->type == NPIPE) {
11394                                 n2->npipe.pipe_backgnd = 1;
11395                         } else {
11396                                 if (n2->type != NREDIR) {
11397                                         n3 = stzalloc(sizeof(struct nredir));
11398                                         n3->nredir.n = n2;
11399                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11400                                         n2 = n3;
11401                                 }
11402                                 n2->type = NBACKGND;
11403                         }
11404                 }
11405                 if (n1 == NULL) {
11406                         n1 = n2;
11407                 } else {
11408                         n3 = stzalloc(sizeof(struct nbinary));
11409                         n3->type = NSEMI;
11410                         n3->nbinary.ch1 = n1;
11411                         n3->nbinary.ch2 = n2;
11412                         n1 = n3;
11413                 }
11414                 switch (tok) {
11415                 case TNL:
11416                 case TEOF:
11417                         tokpushback = 1;
11418                         /* fall through */
11419                 case TBACKGND:
11420                 case TSEMI:
11421                         break;
11422                 default:
11423                         if ((nlflag & 1))
11424                                 raise_error_unexpected_syntax(-1);
11425                         tokpushback = 1;
11426                         return n1;
11427                 }
11428         }
11429 }
11430
11431 static union node *
11432 andor(void)
11433 {
11434         union node *n1, *n2, *n3;
11435         int t;
11436
11437         n1 = pipeline();
11438         for (;;) {
11439                 t = readtoken();
11440                 if (t == TAND) {
11441                         t = NAND;
11442                 } else if (t == TOR) {
11443                         t = NOR;
11444                 } else {
11445                         tokpushback = 1;
11446                         return n1;
11447                 }
11448                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11449                 n2 = pipeline();
11450                 n3 = stzalloc(sizeof(struct nbinary));
11451                 n3->type = t;
11452                 n3->nbinary.ch1 = n1;
11453                 n3->nbinary.ch2 = n2;
11454                 n1 = n3;
11455         }
11456 }
11457
11458 static union node *
11459 pipeline(void)
11460 {
11461         union node *n1, *n2, *pipenode;
11462         struct nodelist *lp, *prev;
11463         int negate;
11464
11465         negate = 0;
11466         TRACE(("pipeline: entered\n"));
11467         if (readtoken() == TNOT) {
11468                 negate = !negate;
11469                 checkkwd = CHKKWD | CHKALIAS;
11470         } else
11471                 tokpushback = 1;
11472         n1 = parse_command();
11473         if (readtoken() == TPIPE) {
11474                 pipenode = stzalloc(sizeof(struct npipe));
11475                 pipenode->type = NPIPE;
11476                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11477                 lp = stzalloc(sizeof(struct nodelist));
11478                 pipenode->npipe.cmdlist = lp;
11479                 lp->n = n1;
11480                 do {
11481                         prev = lp;
11482                         lp = stzalloc(sizeof(struct nodelist));
11483                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11484                         lp->n = parse_command();
11485                         prev->next = lp;
11486                 } while (readtoken() == TPIPE);
11487                 lp->next = NULL;
11488                 n1 = pipenode;
11489         }
11490         tokpushback = 1;
11491         if (negate) {
11492                 n2 = stzalloc(sizeof(struct nnot));
11493                 n2->type = NNOT;
11494                 n2->nnot.com = n1;
11495                 return n2;
11496         }
11497         return n1;
11498 }
11499
11500 static union node *
11501 makename(void)
11502 {
11503         union node *n;
11504
11505         n = stzalloc(sizeof(struct narg));
11506         n->type = NARG;
11507         /*n->narg.next = NULL; - stzalloc did it */
11508         n->narg.text = wordtext;
11509         n->narg.backquote = backquotelist;
11510         return n;
11511 }
11512
11513 static void
11514 fixredir(union node *n, const char *text, int err)
11515 {
11516         int fd;
11517
11518         TRACE(("Fix redir %s %d\n", text, err));
11519         if (!err)
11520                 n->ndup.vname = NULL;
11521
11522         fd = bb_strtou(text, NULL, 10);
11523         if (!errno && fd >= 0)
11524                 n->ndup.dupfd = fd;
11525         else if (LONE_DASH(text))
11526                 n->ndup.dupfd = -1;
11527         else {
11528                 if (err)
11529                         raise_error_syntax("bad fd number");
11530                 n->ndup.vname = makename();
11531         }
11532 }
11533
11534 static void
11535 parsefname(void)
11536 {
11537         union node *n = redirnode;
11538
11539         if (n->type == NHERE)
11540                 checkkwd = CHKEOFMARK;
11541         if (readtoken() != TWORD)
11542                 raise_error_unexpected_syntax(-1);
11543         if (n->type == NHERE) {
11544                 struct heredoc *here = heredoc;
11545                 struct heredoc *p;
11546
11547                 if (quoteflag == 0)
11548                         n->type = NXHERE;
11549                 TRACE(("Here document %d\n", n->type));
11550                 rmescapes(wordtext, 0, NULL);
11551                 here->eofmark = wordtext;
11552                 here->next = NULL;
11553                 if (heredoclist == NULL)
11554                         heredoclist = here;
11555                 else {
11556                         for (p = heredoclist; p->next; p = p->next)
11557                                 continue;
11558                         p->next = here;
11559                 }
11560         } else if (n->type == NTOFD || n->type == NFROMFD) {
11561                 fixredir(n, wordtext, 0);
11562         } else {
11563                 n->nfile.fname = makename();
11564         }
11565 }
11566
11567 static union node *
11568 simplecmd(void)
11569 {
11570         union node *args, **app;
11571         union node *n = NULL;
11572         union node *vars, **vpp;
11573         union node **rpp, *redir;
11574         int savecheckkwd;
11575         int savelinno;
11576 #if BASH_TEST2
11577         smallint double_brackets_flag = 0;
11578 #endif
11579         IF_BASH_FUNCTION(smallint function_flag = 0;)
11580
11581         args = NULL;
11582         app = &args;
11583         vars = NULL;
11584         vpp = &vars;
11585         redir = NULL;
11586         rpp = &redir;
11587
11588         savecheckkwd = CHKALIAS;
11589         savelinno = g_parsefile->linno;
11590         for (;;) {
11591                 int t;
11592                 checkkwd = savecheckkwd;
11593                 t = readtoken();
11594                 switch (t) {
11595 #if BASH_FUNCTION
11596                 case TFUNCTION:
11597                         if (peektoken() != TWORD)
11598                                 raise_error_unexpected_syntax(TWORD);
11599                         function_flag = 1;
11600                         break;
11601 #endif
11602 #if BASH_TEST2
11603                 case TAND: /* "&&" */
11604                 case TOR: /* "||" */
11605                         if (!double_brackets_flag) {
11606                                 tokpushback = 1;
11607                                 goto out;
11608                         }
11609                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11610 #endif
11611                 case TWORD:
11612                         n = stzalloc(sizeof(struct narg));
11613                         n->type = NARG;
11614                         /*n->narg.next = NULL; - stzalloc did it */
11615                         n->narg.text = wordtext;
11616 #if BASH_TEST2
11617                         if (strcmp("[[", wordtext) == 0)
11618                                 double_brackets_flag = 1;
11619                         else if (strcmp("]]", wordtext) == 0)
11620                                 double_brackets_flag = 0;
11621 #endif
11622                         n->narg.backquote = backquotelist;
11623                         if (savecheckkwd && isassignment(wordtext)) {
11624                                 *vpp = n;
11625                                 vpp = &n->narg.next;
11626                         } else {
11627                                 *app = n;
11628                                 app = &n->narg.next;
11629                                 savecheckkwd = 0;
11630                         }
11631 #if BASH_FUNCTION
11632                         if (function_flag) {
11633                                 checkkwd = CHKNL | CHKKWD;
11634                                 switch (peektoken()) {
11635                                 case TBEGIN:
11636                                 case TIF:
11637                                 case TCASE:
11638                                 case TUNTIL:
11639                                 case TWHILE:
11640                                 case TFOR:
11641                                         goto do_func;
11642                                 case TLP:
11643                                         function_flag = 0;
11644                                         break;
11645 # if BASH_TEST2
11646                                 case TWORD:
11647                                         if (strcmp("[[", wordtext) == 0)
11648                                                 goto do_func;
11649                                         /* fall through */
11650 # endif
11651                                 default:
11652                                         raise_error_unexpected_syntax(-1);
11653                                 }
11654                         }
11655 #endif
11656                         break;
11657                 case TREDIR:
11658                         *rpp = n = redirnode;
11659                         rpp = &n->nfile.next;
11660                         parsefname();   /* read name of redirection file */
11661                         break;
11662                 case TLP:
11663  IF_BASH_FUNCTION(do_func:)
11664                         if (args && app == &args->narg.next
11665                          && !vars && !redir
11666                         ) {
11667                                 struct builtincmd *bcmd;
11668                                 const char *name;
11669
11670                                 /* We have a function */
11671                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11672                                         raise_error_unexpected_syntax(TRP);
11673                                 name = n->narg.text;
11674                                 if (!goodname(name)
11675                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11676                                 ) {
11677                                         raise_error_syntax("bad function name");
11678                                 }
11679                                 n->type = NDEFUN;
11680                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11681                                 n->ndefun.text = n->narg.text;
11682                                 n->ndefun.linno = g_parsefile->linno;
11683                                 n->ndefun.body = parse_command();
11684                                 return n;
11685                         }
11686                         IF_BASH_FUNCTION(function_flag = 0;)
11687                         /* fall through */
11688                 default:
11689                         tokpushback = 1;
11690                         goto out;
11691                 }
11692         }
11693  out:
11694         *app = NULL;
11695         *vpp = NULL;
11696         *rpp = NULL;
11697         n = stzalloc(sizeof(struct ncmd));
11698         if (NCMD != 0)
11699                 n->type = NCMD;
11700         n->ncmd.linno = savelinno;
11701         n->ncmd.args = args;
11702         n->ncmd.assign = vars;
11703         n->ncmd.redirect = redir;
11704         return n;
11705 }
11706
11707 static union node *
11708 parse_command(void)
11709 {
11710         union node *n1, *n2;
11711         union node *ap, **app;
11712         union node *cp, **cpp;
11713         union node *redir, **rpp;
11714         union node **rpp2;
11715         int t;
11716         int savelinno;
11717
11718         redir = NULL;
11719         rpp2 = &redir;
11720
11721         savelinno = g_parsefile->linno;
11722
11723         switch (readtoken()) {
11724         default:
11725                 raise_error_unexpected_syntax(-1);
11726                 /* NOTREACHED */
11727         case TIF:
11728                 n1 = stzalloc(sizeof(struct nif));
11729                 n1->type = NIF;
11730                 n1->nif.test = list(0);
11731                 if (readtoken() != TTHEN)
11732                         raise_error_unexpected_syntax(TTHEN);
11733                 n1->nif.ifpart = list(0);
11734                 n2 = n1;
11735                 while (readtoken() == TELIF) {
11736                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11737                         n2 = n2->nif.elsepart;
11738                         n2->type = NIF;
11739                         n2->nif.test = list(0);
11740                         if (readtoken() != TTHEN)
11741                                 raise_error_unexpected_syntax(TTHEN);
11742                         n2->nif.ifpart = list(0);
11743                 }
11744                 if (lasttoken == TELSE)
11745                         n2->nif.elsepart = list(0);
11746                 else {
11747                         n2->nif.elsepart = NULL;
11748                         tokpushback = 1;
11749                 }
11750                 t = TFI;
11751                 break;
11752         case TWHILE:
11753         case TUNTIL: {
11754                 int got;
11755                 n1 = stzalloc(sizeof(struct nbinary));
11756                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11757                 n1->nbinary.ch1 = list(0);
11758                 got = readtoken();
11759                 if (got != TDO) {
11760                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11761                                         got == TWORD ? wordtext : ""));
11762                         raise_error_unexpected_syntax(TDO);
11763                 }
11764                 n1->nbinary.ch2 = list(0);
11765                 t = TDONE;
11766                 break;
11767         }
11768         case TFOR:
11769                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11770                         raise_error_syntax("bad for loop variable");
11771                 n1 = stzalloc(sizeof(struct nfor));
11772                 n1->type = NFOR;
11773                 n1->nfor.linno = savelinno;
11774                 n1->nfor.var = wordtext;
11775                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11776                 if (readtoken() == TIN) {
11777                         app = &ap;
11778                         while (readtoken() == TWORD) {
11779                                 n2 = stzalloc(sizeof(struct narg));
11780                                 n2->type = NARG;
11781                                 /*n2->narg.next = NULL; - stzalloc did it */
11782                                 n2->narg.text = wordtext;
11783                                 n2->narg.backquote = backquotelist;
11784                                 *app = n2;
11785                                 app = &n2->narg.next;
11786                         }
11787                         *app = NULL;
11788                         n1->nfor.args = ap;
11789                         if (lasttoken != TNL && lasttoken != TSEMI)
11790                                 raise_error_unexpected_syntax(-1);
11791                 } else {
11792                         n2 = stzalloc(sizeof(struct narg));
11793                         n2->type = NARG;
11794                         /*n2->narg.next = NULL; - stzalloc did it */
11795                         n2->narg.text = (char *)dolatstr;
11796                         /*n2->narg.backquote = NULL;*/
11797                         n1->nfor.args = n2;
11798                         /*
11799                          * Newline or semicolon here is optional (but note
11800                          * that the original Bourne shell only allowed NL).
11801                          */
11802                         if (lasttoken != TSEMI)
11803                                 tokpushback = 1;
11804                 }
11805                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11806                 if (readtoken() != TDO)
11807                         raise_error_unexpected_syntax(TDO);
11808                 n1->nfor.body = list(0);
11809                 t = TDONE;
11810                 break;
11811         case TCASE:
11812                 n1 = stzalloc(sizeof(struct ncase));
11813                 n1->type = NCASE;
11814                 n1->ncase.linno = savelinno;
11815                 if (readtoken() != TWORD)
11816                         raise_error_unexpected_syntax(TWORD);
11817                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11818                 n2->type = NARG;
11819                 /*n2->narg.next = NULL; - stzalloc did it */
11820                 n2->narg.text = wordtext;
11821                 n2->narg.backquote = backquotelist;
11822                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11823                 if (readtoken() != TIN)
11824                         raise_error_unexpected_syntax(TIN);
11825                 cpp = &n1->ncase.cases;
11826  next_case:
11827                 checkkwd = CHKNL | CHKKWD;
11828                 t = readtoken();
11829                 while (t != TESAC) {
11830                         if (lasttoken == TLP)
11831                                 readtoken();
11832                         *cpp = cp = stzalloc(sizeof(struct nclist));
11833                         cp->type = NCLIST;
11834                         app = &cp->nclist.pattern;
11835                         for (;;) {
11836                                 *app = ap = stzalloc(sizeof(struct narg));
11837                                 ap->type = NARG;
11838                                 /*ap->narg.next = NULL; - stzalloc did it */
11839                                 ap->narg.text = wordtext;
11840                                 ap->narg.backquote = backquotelist;
11841                                 if (readtoken() != TPIPE)
11842                                         break;
11843                                 app = &ap->narg.next;
11844                                 readtoken();
11845                         }
11846                         //ap->narg.next = NULL;
11847                         if (lasttoken != TRP)
11848                                 raise_error_unexpected_syntax(TRP);
11849                         cp->nclist.body = list(2);
11850
11851                         cpp = &cp->nclist.next;
11852
11853                         checkkwd = CHKNL | CHKKWD;
11854                         t = readtoken();
11855                         if (t != TESAC) {
11856                                 if (t != TENDCASE)
11857                                         raise_error_unexpected_syntax(TENDCASE);
11858                                 goto next_case;
11859                         }
11860                 }
11861                 *cpp = NULL;
11862                 goto redir;
11863         case TLP:
11864                 n1 = stzalloc(sizeof(struct nredir));
11865                 n1->type = NSUBSHELL;
11866                 n1->nredir.linno = savelinno;
11867                 n1->nredir.n = list(0);
11868                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11869                 t = TRP;
11870                 break;
11871         case TBEGIN:
11872                 n1 = list(0);
11873                 t = TEND;
11874                 break;
11875         IF_BASH_FUNCTION(case TFUNCTION:)
11876         case TWORD:
11877         case TREDIR:
11878                 tokpushback = 1;
11879                 return simplecmd();
11880         }
11881
11882         if (readtoken() != t)
11883                 raise_error_unexpected_syntax(t);
11884
11885  redir:
11886         /* Now check for redirection which may follow command */
11887         checkkwd = CHKKWD | CHKALIAS;
11888         rpp = rpp2;
11889         while (readtoken() == TREDIR) {
11890                 *rpp = n2 = redirnode;
11891                 rpp = &n2->nfile.next;
11892                 parsefname();
11893         }
11894         tokpushback = 1;
11895         *rpp = NULL;
11896         if (redir) {
11897                 if (n1->type != NSUBSHELL) {
11898                         n2 = stzalloc(sizeof(struct nredir));
11899                         n2->type = NREDIR;
11900                         n2->nredir.linno = savelinno;
11901                         n2->nredir.n = n1;
11902                         n1 = n2;
11903                 }
11904                 n1->nredir.redirect = redir;
11905         }
11906         return n1;
11907 }
11908
11909 #if BASH_DOLLAR_SQUOTE
11910 static int
11911 decode_dollar_squote(void)
11912 {
11913         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11914         int c, cnt;
11915         char *p;
11916         char buf[4];
11917
11918         c = pgetc();
11919         p = strchr(C_escapes, c);
11920         if (p) {
11921                 buf[0] = c;
11922                 p = buf;
11923                 cnt = 3;
11924                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11925                         do {
11926                                 c = pgetc();
11927                                 *++p = c;
11928                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11929                         pungetc();
11930                 } else if (c == 'x') { /* \xHH */
11931                         do {
11932                                 c = pgetc();
11933                                 *++p = c;
11934                         } while (isxdigit(c) && --cnt);
11935                         pungetc();
11936                         if (cnt == 3) { /* \x but next char is "bad" */
11937                                 c = 'x';
11938                                 goto unrecognized;
11939                         }
11940                 } else { /* simple seq like \\ or \t */
11941                         p++;
11942                 }
11943                 *p = '\0';
11944                 p = buf;
11945                 c = bb_process_escape_sequence((void*)&p);
11946         } else { /* unrecognized "\z": print both chars unless ' or " */
11947                 if (c != '\'' && c != '"') {
11948  unrecognized:
11949                         c |= 0x100; /* "please encode \, then me" */
11950                 }
11951         }
11952         return c;
11953 }
11954 #endif
11955
11956 /* Used by expandstr to get here-doc like behaviour. */
11957 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11958
11959 static ALWAYS_INLINE int
11960 realeofmark(const char *eofmark)
11961 {
11962         return eofmark && eofmark != FAKEEOFMARK;
11963 }
11964
11965 /*
11966  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11967  * is not NULL, read a here document.  In the latter case, eofmark is the
11968  * word which marks the end of the document and striptabs is true if
11969  * leading tabs should be stripped from the document.  The argument c
11970  * is the first character of the input token or document.
11971  *
11972  * Because C does not have internal subroutines, I have simulated them
11973  * using goto's to implement the subroutine linkage.  The following macros
11974  * will run code that appears at the end of readtoken1.
11975  */
11976 #define CHECKEND()      {goto checkend; checkend_return:;}
11977 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11978 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11979 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11980 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11981 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11982 static int
11983 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11984 {
11985         /* NB: syntax parameter fits into smallint */
11986         /* c parameter is an unsigned char or PEOF or PEOA */
11987         char *out;
11988         size_t len;
11989         struct nodelist *bqlist;
11990         smallint quotef;
11991         smallint oldstyle;
11992         smallint pssyntax;   /* we are expanding a prompt string */
11993         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11994         /* syntax stack */
11995         struct synstack synbase = { };
11996         struct synstack *synstack = &synbase;
11997
11998 #if ENABLE_ASH_EXPAND_PRMT
11999         pssyntax = (syntax == PSSYNTAX);
12000         if (pssyntax)
12001                 syntax = DQSYNTAX;
12002 #else
12003         pssyntax = 0; /* constant */
12004 #endif
12005         synstack->syntax = syntax;
12006
12007         if (syntax == DQSYNTAX)
12008                 synstack->dblquote = 1;
12009         quotef = 0;
12010         bqlist = NULL;
12011
12012         STARTSTACKSTR(out);
12013  loop:
12014         /* For each line, until end of word */
12015         CHECKEND();     /* set c to PEOF if at end of here document */
12016         for (;;) {      /* until end of line or end of word */
12017                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
12018                 switch (SIT(c, synstack->syntax)) {
12019                 case CNL:       /* '\n' */
12020                         if (synstack->syntax == BASESYNTAX
12021                          && !synstack->varnest
12022                         ) {
12023                                 goto endword;   /* exit outer loop */
12024                         }
12025                         USTPUTC(c, out);
12026                         nlprompt();
12027                         c = pgetc();
12028                         goto loop;              /* continue outer loop */
12029                 case CWORD:
12030                         USTPUTC(c, out);
12031                         break;
12032                 case CCTL:
12033 #if BASH_DOLLAR_SQUOTE
12034                         if (c == '\\' && bash_dollar_squote) {
12035                                 c = decode_dollar_squote();
12036                                 if (c == '\0') {
12037                                         /* skip $'\000', $'\x00' (like bash) */
12038                                         break;
12039                                 }
12040                                 if (c & 0x100) {
12041                                         /* Unknown escape. Encode as '\z' */
12042                                         c = (unsigned char)c;
12043                                         if (eofmark == NULL || synstack->dblquote)
12044                                                 USTPUTC(CTLESC, out);
12045                                         USTPUTC('\\', out);
12046                                 }
12047                         }
12048 #endif
12049                         if (!eofmark || synstack->dblquote || synstack->varnest)
12050                                 USTPUTC(CTLESC, out);
12051                         USTPUTC(c, out);
12052                         break;
12053                 case CBACK:     /* backslash */
12054                         c = pgetc_without_PEOA();
12055                         if (c == PEOF) {
12056                                 USTPUTC(CTLESC, out);
12057                                 USTPUTC('\\', out);
12058                                 pungetc();
12059                         } else if (c == '\n') {
12060                                 nlprompt();
12061                         } else {
12062                                 if (pssyntax && c == '$') {
12063                                         USTPUTC(CTLESC, out);
12064                                         USTPUTC('\\', out);
12065                                 }
12066                                 /* Backslash is retained if we are in "str"
12067                                  * and next char isn't dquote-special.
12068                                  */
12069                                 if (synstack->dblquote
12070                                  && c != '\\'
12071                                  && c != '`'
12072                                  && c != '$'
12073                                  && (c != '"' || (eofmark != NULL && !synstack->varnest))
12074                                  && (c != '}' || !synstack->varnest)
12075                                 ) {
12076                                         USTPUTC(CTLESC, out); /* protect '\' from glob */
12077                                         USTPUTC('\\', out);
12078                                 }
12079                                 USTPUTC(CTLESC, out);
12080                                 USTPUTC(c, out);
12081                                 quotef = 1;
12082                         }
12083                         break;
12084                 case CSQUOTE:
12085                         synstack->syntax = SQSYNTAX;
12086  quotemark:
12087                         if (eofmark == NULL) {
12088                                 USTPUTC(CTLQUOTEMARK, out);
12089                         }
12090                         break;
12091                 case CDQUOTE:
12092                         synstack->syntax = DQSYNTAX;
12093                         synstack->dblquote = 1;
12094  toggledq:
12095                         if (synstack->varnest)
12096                                 synstack->innerdq ^= 1;
12097                         goto quotemark;
12098                 case CENDQUOTE:
12099                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
12100                         if (eofmark != NULL && synstack->varnest == 0) {
12101                                 USTPUTC(c, out);
12102                                 break;
12103                         }
12104
12105                         if (synstack->dqvarnest == 0) {
12106                                 synstack->syntax = BASESYNTAX;
12107                                 synstack->dblquote = 0;
12108                         }
12109
12110                         quotef = 1;
12111
12112                         if (c == '"')
12113                                 goto toggledq;
12114
12115                         goto quotemark;
12116                 case CVAR:      /* '$' */
12117                         PARSESUB();             /* parse substitution */
12118                         break;
12119                 case CENDVAR:   /* '}' */
12120                         if (!synstack->innerdq && synstack->varnest > 0) {
12121                                 if (!--synstack->varnest && synstack->varpushed)
12122                                         synstack_pop(&synstack);
12123                                 else if (synstack->dqvarnest > 0)
12124                                         synstack->dqvarnest--;
12125                                 c = CTLENDVAR;
12126                         }
12127                         USTPUTC(c, out);
12128                         break;
12129 #if ENABLE_FEATURE_SH_MATH
12130                 case CLP:       /* '(' in arithmetic */
12131                         synstack->parenlevel++;
12132                         USTPUTC(c, out);
12133                         break;
12134                 case CRP:       /* ')' in arithmetic */
12135                         if (synstack->parenlevel > 0) {
12136                                 synstack->parenlevel--;
12137                         } else {
12138                                 if (pgetc_eatbnl() == ')') {
12139                                         c = CTLENDARI;
12140                                         synstack_pop(&synstack);
12141                                 } else {
12142                                         /*
12143                                          * unbalanced parens
12144                                          * (don't 2nd guess - no error)
12145                                          */
12146                                         pungetc();
12147                                 }
12148                         }
12149                         USTPUTC(c, out);
12150                         break;
12151 #endif
12152                 case CBQUOTE:   /* '`' */
12153                         if (checkkwd & CHKEOFMARK) {
12154                                 quotef = 1;
12155                                 USTPUTC('`', out);
12156                                 break;
12157                         }
12158
12159                         PARSEBACKQOLD();
12160                         break;
12161                 case CENDFILE:
12162                         goto endword;           /* exit outer loop */
12163                 case CIGN:
12164                         break;
12165                 default:
12166                         if (synstack->varnest == 0) {
12167 #if BASH_REDIR_OUTPUT
12168                                 if (c == '&') {
12169 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
12170                                         if (pgetc() == '>')
12171                                                 c = 0x100 + '>'; /* flag &> */
12172                                         pungetc();
12173                                 }
12174 #endif
12175                                 goto endword;   /* exit outer loop */
12176                         }
12177                         IF_ASH_ALIAS(if (c != PEOA))
12178                                 USTPUTC(c, out);
12179                 }
12180                 c = pgetc();
12181         } /* for (;;) */
12182  endword:
12183
12184 #if ENABLE_FEATURE_SH_MATH
12185         if (synstack->syntax == ARISYNTAX)
12186                 raise_error_syntax("missing '))'");
12187 #endif
12188         if (synstack->syntax != BASESYNTAX && eofmark == NULL)
12189                 raise_error_syntax("unterminated quoted string");
12190         if (synstack->varnest != 0) {
12191                 /* { */
12192                 raise_error_syntax("missing '}'");
12193         }
12194         USTPUTC('\0', out);
12195         len = out - (char *)stackblock();
12196         out = stackblock();
12197         if (eofmark == NULL) {
12198                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
12199                  && quotef == 0
12200                 ) {
12201                         if (isdigit_str9(out)) {
12202                                 PARSEREDIR(); /* passed as params: out, c */
12203                                 lasttoken = TREDIR;
12204                                 return lasttoken;
12205                         }
12206                         /* else: non-number X seen, interpret it
12207                          * as "NNNX>file" = "NNNX >file" */
12208                 }
12209                 pungetc();
12210         }
12211         quoteflag = quotef;
12212         backquotelist = bqlist;
12213         grabstackblock(len);
12214         wordtext = out;
12215         lasttoken = TWORD;
12216         return lasttoken;
12217 /* end of readtoken routine */
12218
12219 /*
12220  * Check to see whether we are at the end of the here document.  When this
12221  * is called, c is set to the first character of the next input line.  If
12222  * we are at the end of the here document, this routine sets the c to PEOF.
12223  */
12224 checkend: {
12225         if (realeofmark(eofmark)) {
12226                 int markloc;
12227                 char *p;
12228
12229 #if ENABLE_ASH_ALIAS
12230                 if (c == PEOA)
12231                         c = pgetc_without_PEOA();
12232 #endif
12233                 if (striptabs) {
12234                         while (c == '\t') {
12235                                 c = pgetc_without_PEOA();
12236                         }
12237                 }
12238
12239                 markloc = out - (char *)stackblock();
12240                 for (p = eofmark; STPUTC(c, out), *p; p++) {
12241                         if (c != *p)
12242                                 goto more_heredoc;
12243
12244                         c = pgetc_without_PEOA();
12245                 }
12246
12247                 if (c == '\n' || c == PEOF) {
12248                         c = PEOF;
12249                         g_parsefile->linno++;
12250                         needprompt = doprompt;
12251                 } else {
12252                         int len_here;
12253
12254  more_heredoc:
12255                         p = (char *)stackblock() + markloc + 1;
12256                         len_here = out - p;
12257
12258                         if (len_here) {
12259                                 len_here -= (c >= PEOF);
12260                                 c = p[-1];
12261
12262                                 if (len_here) {
12263                                         char *str;
12264
12265                                         str = alloca(len_here + 1);
12266                                         *(char *)mempcpy(str, p, len_here) = '\0';
12267
12268                                         pushstring(str, NULL);
12269                                 }
12270                         }
12271                 }
12272
12273                 STADJUST((char *)stackblock() + markloc - out, out);
12274         }
12275         goto checkend_return;
12276 }
12277
12278 /*
12279  * Parse a redirection operator.  The variable "out" points to a string
12280  * specifying the fd to be redirected.  The variable "c" contains the
12281  * first character of the redirection operator.
12282  */
12283 parseredir: {
12284         /* out is already checked to be a valid number or "" */
12285         int fd = (*out == '\0' ? -1 : atoi(out));
12286         union node *np;
12287
12288         np = stzalloc(sizeof(struct nfile));
12289         if (c == '>') {
12290                 np->nfile.fd = 1;
12291                 c = pgetc_eatbnl();
12292                 if (c == '>')
12293                         np->type = NAPPEND;
12294                 else if (c == '|')
12295                         np->type = NCLOBBER;
12296                 else if (c == '&')
12297                         np->type = NTOFD;
12298                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
12299                 else {
12300                         np->type = NTO;
12301                         pungetc();
12302                 }
12303         }
12304 #if BASH_REDIR_OUTPUT
12305         else if (c == 0x100 + '>') { /* this flags &> redirection */
12306                 np->nfile.fd = 1;
12307                 pgetc(); /* this is '>', no need to check */
12308                 np->type = NTO2;
12309         }
12310 #endif
12311         else { /* c == '<' */
12312                 /*np->nfile.fd = 0; - stzalloc did it */
12313                 c = pgetc_eatbnl();
12314                 switch (c) {
12315                 case '<':
12316                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
12317                                 np = stzalloc(sizeof(struct nhere));
12318                                 /*np->nfile.fd = 0; - stzalloc did it */
12319                         }
12320                         np->type = NHERE;
12321                         heredoc = stzalloc(sizeof(struct heredoc));
12322                         heredoc->here = np;
12323                         c = pgetc_eatbnl();
12324                         if (c == '-') {
12325                                 heredoc->striptabs = 1;
12326                         } else {
12327                                 /*heredoc->striptabs = 0; - stzalloc did it */
12328                                 pungetc();
12329                         }
12330                         break;
12331
12332                 case '&':
12333                         np->type = NFROMFD;
12334                         break;
12335
12336                 case '>':
12337                         np->type = NFROMTO;
12338                         break;
12339
12340                 default:
12341                         np->type = NFROM;
12342                         pungetc();
12343                         break;
12344                 }
12345         }
12346         if (fd >= 0)
12347                 np->nfile.fd = fd;
12348         redirnode = np;
12349         goto parseredir_return;
12350 }
12351
12352 /*
12353  * Parse a substitution.  At this point, we have read the dollar sign
12354  * and nothing else.
12355  */
12356
12357 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
12358  * (assuming ascii char codes, as the original implementation did) */
12359 #define is_special(c) \
12360         (((unsigned)(c) - 33 < 32) \
12361                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
12362 parsesub: {
12363         unsigned char subtype;
12364         int typeloc;
12365
12366         c = pgetc_eatbnl();
12367         if ((checkkwd & CHKEOFMARK)
12368          || c > 255 /* PEOA or PEOF */
12369          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
12370         ) {
12371 #if BASH_DOLLAR_SQUOTE
12372                 if (synstack->syntax != DQSYNTAX && c == '\'')
12373                         bash_dollar_squote = 1;
12374                 else
12375 #endif
12376                         USTPUTC('$', out);
12377                 pungetc();
12378         } else if (c == '(') {
12379                 /* $(command) or $((arith)) */
12380                 if (pgetc_eatbnl() == '(') {
12381 #if ENABLE_FEATURE_SH_MATH
12382                         PARSEARITH();
12383 #else
12384                         raise_error_syntax("support for $((arith)) is disabled");
12385 #endif
12386                 } else {
12387                         pungetc();
12388                         PARSEBACKQNEW();
12389                 }
12390         } else {
12391                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
12392                 smalluint newsyn = synstack->syntax;
12393
12394                 USTPUTC(CTLVAR, out);
12395                 typeloc = out - (char *)stackblock();
12396                 STADJUST(1, out);
12397                 subtype = VSNORMAL;
12398                 if (c == '{') {
12399                         c = pgetc_eatbnl();
12400                         subtype = 0;
12401                 }
12402  varname:
12403                 if (is_name(c)) {
12404                         /* $[{[#]]NAME[}] */
12405                         do {
12406                                 STPUTC(c, out);
12407                                 c = pgetc_eatbnl();
12408                         } while (is_in_name(c));
12409                 } else if (isdigit(c)) {
12410                         /* $[{[#]]NUM[}] */
12411                         do {
12412                                 STPUTC(c, out);
12413                                 c = pgetc_eatbnl();
12414                         } while (isdigit(c));
12415                 } else {
12416                         /* $[{[#]]<specialchar>[}] */
12417                         int cc = c;
12418
12419                         c = pgetc_eatbnl();
12420                         if (!subtype && cc == '#') {
12421                                 subtype = VSLENGTH;
12422                                 if (c == '_' || isalnum(c))
12423                                         goto varname;
12424                                 cc = c;
12425                                 c = pgetc_eatbnl();
12426                                 if (cc == '}' || c != '}') {
12427                                         pungetc();
12428                                         subtype = 0;
12429                                         c = cc;
12430                                         cc = '#';
12431                                 }
12432                         }
12433
12434                         if (!is_special(cc)) {
12435                                 if (subtype == VSLENGTH)
12436                                         subtype = 0;
12437                                 goto badsub;
12438                         }
12439
12440                         USTPUTC(cc, out);
12441                 }
12442
12443                 if (c != '}' && subtype == VSLENGTH) {
12444                         /* ${#VAR didn't end with } */
12445                         goto badsub;
12446                 }
12447
12448                 if (subtype == 0) {
12449                         static const char types[] ALIGN1 = "}-+?=";
12450                         /* ${VAR...} but not $VAR or ${#VAR} */
12451                         /* c == first char after VAR */
12452                         int cc = c;
12453
12454                         switch (c) {
12455                         case ':':
12456                                 c = pgetc_eatbnl();
12457 #if BASH_SUBSTR
12458                                 /* This check is only needed to not misinterpret
12459                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12460                                  * constructs.
12461                                  */
12462                                 if (!strchr(types, c)) {
12463                                         subtype = VSSUBSTR;
12464                                         pungetc();
12465                                         break; /* "goto badsub" is bigger (!) */
12466                                 }
12467 #endif
12468                                 subtype = VSNUL;
12469                                 /*FALLTHROUGH*/
12470                         default: {
12471                                 const char *p = strchr(types, c);
12472                                 if (p == NULL)
12473                                         break;
12474                                 subtype |= p - types + VSNORMAL;
12475                                 break;
12476                         }
12477                         case '%':
12478                         case '#':
12479                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12480                                 c = pgetc_eatbnl();
12481                                 if (c == cc)
12482                                         subtype++;
12483                                 else
12484                                         pungetc();
12485
12486                                 newsyn = BASESYNTAX;
12487                                 break;
12488 #if BASH_PATTERN_SUBST
12489                         case '/':
12490                                 /* ${v/[/]pattern/repl} */
12491 //TODO: encode pattern and repl separately.
12492 // Currently cases like: v=1;echo ${v/$((1/1))/ONE}
12493 // are broken (should print "ONE")
12494                                 subtype = VSREPLACE;
12495                                 newsyn = BASESYNTAX;
12496                                 c = pgetc_eatbnl();
12497                                 if (c != '/')
12498                                         goto badsub;
12499                                 subtype++; /* VSREPLACEALL */
12500                                 break;
12501 #endif
12502                         }
12503                 } else {
12504  badsub:
12505                         pungetc();
12506                 }
12507
12508                 if (newsyn == ARISYNTAX)
12509                         newsyn = DQSYNTAX;
12510
12511                 if ((newsyn != synstack->syntax || synstack->innerdq)
12512                  && subtype != VSNORMAL
12513                 ) {
12514                         synstack_push(&synstack,
12515                                 synstack->prev ?: alloca(sizeof(*synstack)),
12516                                 newsyn);
12517
12518                         synstack->varpushed = 1;
12519                         synstack->dblquote = newsyn != BASESYNTAX;
12520                 }
12521
12522                 ((unsigned char *)stackblock())[typeloc] = subtype;
12523                 if (subtype != VSNORMAL) {
12524                         synstack->varnest++;
12525                         if (synstack->dblquote)
12526                                 synstack->dqvarnest++;
12527                 }
12528                 STPUTC('=', out);
12529         }
12530         goto parsesub_return;
12531 }
12532
12533 /*
12534  * Called to parse command substitutions.  Newstyle is set if the command
12535  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12536  * list of commands (passed by reference), and savelen is the number of
12537  * characters on the top of the stack which must be preserved.
12538  */
12539 parsebackq: {
12540         struct nodelist **nlpp;
12541         union node *n;
12542         char *str;
12543         size_t savelen;
12544         smallint saveprompt = 0;
12545
12546         str = NULL;
12547         savelen = out - (char *)stackblock();
12548         if (savelen > 0) {
12549                 /*
12550                  * FIXME: this can allocate very large block on stack and SEGV.
12551                  * Example:
12552                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12553                  * allocates 100kb for every command subst. With about
12554                  * a hundred command substitutions stack overflows.
12555                  * With larger prepended string, SEGV happens sooner.
12556                  */
12557                 str = alloca(savelen);
12558                 memcpy(str, stackblock(), savelen);
12559         }
12560
12561         if (oldstyle) {
12562                 /* We must read until the closing backquote, giving special
12563                  * treatment to some slashes, and then push the string and
12564                  * reread it as input, interpreting it normally.
12565                  */
12566                 char *pout;
12567                 size_t psavelen;
12568                 char *pstr;
12569
12570                 STARTSTACKSTR(pout);
12571                 for (;;) {
12572                         int pc;
12573
12574                         setprompt_if(needprompt, 2);
12575                         pc = pgetc_eatbnl();
12576                         switch (pc) {
12577                         case '`':
12578                                 goto done;
12579
12580                         case '\\':
12581                                 pc = pgetc(); /* or pgetc_eatbnl()? why (example)? */
12582                                 if (pc != '\\' && pc != '`' && pc != '$'
12583                                  && (!synstack->dblquote || pc != '"')
12584                                 ) {
12585                                         STPUTC('\\', pout);
12586                                 }
12587                                 if (pc <= 255 /* not PEOA or PEOF */) {
12588                                         break;
12589                                 }
12590                                 /* fall through */
12591
12592                         case PEOF:
12593                         IF_ASH_ALIAS(case PEOA:)
12594                                 raise_error_syntax("EOF in backquote substitution");
12595
12596                         case '\n':
12597                                 nlnoprompt();
12598                                 break;
12599
12600                         default:
12601                                 break;
12602                         }
12603                         STPUTC(pc, pout);
12604                 }
12605  done:
12606                 STPUTC('\0', pout);
12607                 psavelen = pout - (char *)stackblock();
12608                 if (psavelen > 0) {
12609                         pstr = grabstackstr(pout);
12610                         setinputstring(pstr);
12611                 }
12612         }
12613         nlpp = &bqlist;
12614         while (*nlpp)
12615                 nlpp = &(*nlpp)->next;
12616         *nlpp = stzalloc(sizeof(**nlpp));
12617         /* (*nlpp)->next = NULL; - stzalloc did it */
12618
12619         if (oldstyle) {
12620                 saveprompt = doprompt;
12621                 doprompt = 0;
12622         }
12623
12624         n = list(2);
12625
12626         if (oldstyle)
12627                 doprompt = saveprompt;
12628         else if (readtoken() != TRP)
12629                 raise_error_unexpected_syntax(TRP);
12630
12631         (*nlpp)->n = n;
12632         if (oldstyle) {
12633                 /*
12634                  * Start reading from old file again, ignoring any pushed back
12635                  * tokens left from the backquote parsing
12636                  */
12637                 popfile();
12638                 tokpushback = 0;
12639         }
12640         while (stackblocksize() <= savelen)
12641                 growstackblock();
12642         STARTSTACKSTR(out);
12643         if (str) {
12644                 memcpy(out, str, savelen);
12645                 STADJUST(savelen, out);
12646         }
12647         USTPUTC(CTLBACKQ, out);
12648         if (oldstyle)
12649                 goto parsebackq_oldreturn;
12650         goto parsebackq_newreturn;
12651 }
12652
12653 #if ENABLE_FEATURE_SH_MATH
12654 /*
12655  * Parse an arithmetic expansion (indicate start of one and set state)
12656  */
12657 parsearith: {
12658
12659         synstack_push(&synstack,
12660                         synstack->prev ?: alloca(sizeof(*synstack)),
12661                         ARISYNTAX);
12662         synstack->dblquote = 1;
12663         USTPUTC(CTLARI, out);
12664         goto parsearith_return;
12665 }
12666 #endif
12667 } /* end of readtoken */
12668
12669 /*
12670  * Read the next input token.
12671  * If the token is a word, we set backquotelist to the list of cmds in
12672  *      backquotes.  We set quoteflag to true if any part of the word was
12673  *      quoted.
12674  * If the token is TREDIR, then we set redirnode to a structure containing
12675  *      the redirection.
12676  *
12677  * [Change comment:  here documents and internal procedures]
12678  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12679  *  word parsing code into a separate routine.  In this case, readtoken
12680  *  doesn't need to have any internal procedures, but parseword does.
12681  *  We could also make parseoperator in essence the main routine, and
12682  *  have parseword (readtoken1?) handle both words and redirection.]
12683  */
12684 #define NEW_xxreadtoken
12685 #ifdef NEW_xxreadtoken
12686 /* singles must be first! */
12687 static const char xxreadtoken_chars[7] ALIGN1 = {
12688         '\n', '(', ')', /* singles */
12689         '&', '|', ';',  /* doubles */
12690         0
12691 };
12692
12693 #define xxreadtoken_singles 3
12694 #define xxreadtoken_doubles 3
12695
12696 static const char xxreadtoken_tokens[] ALIGN1 = {
12697         TNL, TLP, TRP,          /* only single occurrence allowed */
12698         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12699         TEOF,                   /* corresponds to trailing nul */
12700         TAND, TOR, TENDCASE     /* if double occurrence */
12701 };
12702
12703 static int
12704 xxreadtoken(void)
12705 {
12706         int c;
12707
12708         if (tokpushback) {
12709                 tokpushback = 0;
12710                 return lasttoken;
12711         }
12712         setprompt_if(needprompt, 2);
12713         for (;;) {                      /* until token or start of word found */
12714                 c = pgetc_eatbnl();
12715                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12716                         continue;
12717
12718                 if (c == '#') {
12719                         while ((c = pgetc()) != '\n' && c != PEOF)
12720                                 continue;
12721                         pungetc();
12722                 } else if (c == '\\') {
12723                         break; /* return readtoken1(...) */
12724                 } else {
12725                         const char *p;
12726
12727                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12728                         if (c != PEOF) {
12729                                 if (c == '\n') {
12730                                         nlnoprompt();
12731                                 }
12732
12733                                 p = strchr(xxreadtoken_chars, c);
12734                                 if (p == NULL)
12735                                         break; /* return readtoken1(...) */
12736
12737                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12738                                         int cc = pgetc_eatbnl();
12739                                         if (cc == c) {    /* double occurrence? */
12740                                                 p += xxreadtoken_doubles + 1;
12741                                         } else {
12742                                                 pungetc();
12743 #if BASH_REDIR_OUTPUT
12744                                                 if (c == '&' && cc == '>') /* &> */
12745                                                         break; /* return readtoken1(...) */
12746 #endif
12747                                         }
12748                                 }
12749                         }
12750                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12751                         return lasttoken;
12752                 }
12753         } /* for (;;) */
12754
12755         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12756 }
12757 #else /* old xxreadtoken */
12758 #define RETURN(token)   return lasttoken = token
12759 static int
12760 xxreadtoken(void)
12761 {
12762         int c;
12763
12764         if (tokpushback) {
12765                 tokpushback = 0;
12766                 return lasttoken;
12767         }
12768         setprompt_if(needprompt, 2);
12769         for (;;) {      /* until token or start of word found */
12770                 c = pgetc_eatbnl();
12771                 switch (c) {
12772                 case ' ': case '\t':
12773                 IF_ASH_ALIAS(case PEOA:)
12774                         continue;
12775                 case '#':
12776                         while ((c = pgetc()) != '\n' && c != PEOF)
12777                                 continue;
12778                         pungetc();
12779                         continue;
12780                 case '\n':
12781                         nlnoprompt();
12782                         RETURN(TNL);
12783                 case PEOF:
12784                         RETURN(TEOF);
12785                 case '&':
12786                         if (pgetc_eatbnl() == '&')
12787                                 RETURN(TAND);
12788                         pungetc();
12789                         RETURN(TBACKGND);
12790                 case '|':
12791                         if (pgetc_eatbnl() == '|')
12792                                 RETURN(TOR);
12793                         pungetc();
12794                         RETURN(TPIPE);
12795                 case ';':
12796                         if (pgetc_eatbnl() == ';')
12797                                 RETURN(TENDCASE);
12798                         pungetc();
12799                         RETURN(TSEMI);
12800                 case '(':
12801                         RETURN(TLP);
12802                 case ')':
12803                         RETURN(TRP);
12804                 }
12805                 break;
12806         }
12807         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12808 #undef RETURN
12809 }
12810 #endif /* old xxreadtoken */
12811
12812 static int
12813 readtoken(void)
12814 {
12815         int t;
12816         int kwd = checkkwd;
12817 #if DEBUG
12818         smallint alreadyseen = tokpushback;
12819 #endif
12820
12821 #if ENABLE_ASH_ALIAS
12822  top:
12823 #endif
12824
12825         t = xxreadtoken();
12826
12827         /*
12828          * eat newlines
12829          */
12830         if (kwd & CHKNL) {
12831                 while (t == TNL) {
12832                         parseheredoc();
12833                         t = xxreadtoken();
12834                 }
12835         }
12836
12837         if (t != TWORD || quoteflag) {
12838                 goto out;
12839         }
12840
12841         /*
12842          * check for keywords
12843          */
12844         if (kwd & CHKKWD) {
12845                 const char *const *pp;
12846
12847                 pp = findkwd(wordtext);
12848                 if (pp) {
12849                         lasttoken = t = pp - tokname_array;
12850                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12851                         goto out;
12852                 }
12853         }
12854
12855         if (checkkwd & CHKALIAS) {
12856 #if ENABLE_ASH_ALIAS
12857                 struct alias *ap;
12858                 ap = lookupalias(wordtext, 1);
12859                 if (ap != NULL) {
12860                         if (*ap->val) {
12861                                 pushstring(ap->val, ap);
12862                         }
12863                         goto top;
12864                 }
12865 #endif
12866         }
12867  out:
12868         checkkwd = 0;
12869 #if DEBUG
12870         if (!alreadyseen)
12871                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12872         else
12873                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12874 #endif
12875         return t;
12876 }
12877
12878 static int
12879 peektoken(void)
12880 {
12881         int t;
12882
12883         t = readtoken();
12884         tokpushback = 1;
12885         return t;
12886 }
12887
12888 /*
12889  * Read and parse a command.  Returns NODE_EOF on end of file.
12890  * (NULL is a valid parse tree indicating a blank line.)
12891  */
12892 static union node *
12893 parsecmd(int interact)
12894 {
12895         tokpushback = 0;
12896         checkkwd = 0;
12897         heredoclist = 0;
12898         doprompt = interact;
12899         setprompt_if(doprompt, doprompt);
12900         needprompt = 0;
12901         return list(1);
12902 }
12903
12904 /*
12905  * Input any here documents.
12906  */
12907 static void
12908 parseheredoc(void)
12909 {
12910         struct heredoc *here;
12911         union node *n;
12912
12913         here = heredoclist;
12914         heredoclist = NULL;
12915
12916         while (here) {
12917                 setprompt_if(needprompt, 2);
12918                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12919                                 here->eofmark, here->striptabs);
12920                 n = stzalloc(sizeof(struct narg));
12921                 n->narg.type = NARG;
12922                 /*n->narg.next = NULL; - stzalloc did it */
12923                 n->narg.text = wordtext;
12924                 n->narg.backquote = backquotelist;
12925                 here->here->nhere.doc = n;
12926                 here = here->next;
12927         }
12928 }
12929
12930
12931 static const char *
12932 expandstr(const char *ps, int syntax_type)
12933 {
12934         union node n;
12935         int saveprompt;
12936
12937         /* XXX Fix (char *) cast. */
12938         setinputstring((char *)ps);
12939
12940         saveprompt = doprompt;
12941         doprompt = 0;
12942
12943         /* readtoken1() might die horribly.
12944          * Try a prompt with syntactically wrong command:
12945          * PS1='$(date "+%H:%M:%S) > '
12946          */
12947         {
12948                 volatile int saveint;
12949                 struct jmploc *volatile savehandler = exception_handler;
12950                 struct jmploc jmploc;
12951                 SAVE_INT(saveint);
12952                 if (setjmp(jmploc.loc) == 0) {
12953                         exception_handler = &jmploc;
12954                         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12955                 }
12956                 exception_handler = savehandler;
12957                 RESTORE_INT(saveint);
12958         }
12959
12960         doprompt = saveprompt;
12961
12962         popfile();
12963
12964         n.narg.type = NARG;
12965         n.narg.next = NULL;
12966         n.narg.text = wordtext;
12967         n.narg.backquote = backquotelist;
12968
12969         expandarg(&n, NULL, EXP_QUOTED);
12970         return stackblock();
12971 }
12972
12973 static inline int
12974 parser_eof(void)
12975 {
12976         return tokpushback && lasttoken == TEOF;
12977 }
12978
12979 /*
12980  * Execute a command or commands contained in a string.
12981  */
12982 static int
12983 evalstring(char *s, int flags)
12984 {
12985         struct jmploc *volatile savehandler;
12986         struct jmploc jmploc;
12987         int ex;
12988
12989         union node *n;
12990         struct stackmark smark;
12991         int status;
12992
12993         s = sstrdup(s);
12994         setinputstring(s);
12995         setstackmark(&smark);
12996
12997         status = 0;
12998         /* On exception inside execution loop, we must popfile().
12999          * Try interactively:
13000          *      readonly a=a
13001          *      command eval "a=b"  # throws "is read only" error
13002          * "command BLTIN" is not supposed to abort (even in non-interactive use).
13003          * But if we skip popfile(), we hit EOF in eval's string, and exit.
13004          */
13005         savehandler = exception_handler;
13006         ex = setjmp(jmploc.loc);
13007         if (ex)
13008                 goto out;
13009         exception_handler = &jmploc;
13010
13011         while ((n = parsecmd(0)) != NODE_EOF) {
13012                 int i;
13013
13014                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
13015                 if (n)
13016                         status = i;
13017                 popstackmark(&smark);
13018                 if (evalskip)
13019                         break;
13020         }
13021  out:
13022         popstackmark(&smark);
13023         popfile();
13024         stunalloc(s);
13025
13026         exception_handler = savehandler;
13027         if (ex)
13028                 longjmp(exception_handler->loc, ex);
13029
13030         return status;
13031 }
13032
13033 /*
13034  * The eval command.
13035  */
13036 static int FAST_FUNC
13037 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
13038 {
13039         char *p;
13040         char *concat;
13041
13042         if (argv[1]) {
13043                 p = argv[1];
13044                 argv += 2;
13045                 if (argv[0]) {
13046                         STARTSTACKSTR(concat);
13047                         for (;;) {
13048                                 concat = stack_putstr(p, concat);
13049                                 p = *argv++;
13050                                 if (p == NULL)
13051                                         break;
13052                                 STPUTC(' ', concat);
13053                         }
13054                         STPUTC('\0', concat);
13055                         p = grabstackstr(concat);
13056                 }
13057                 return evalstring(p, flags & EV_TESTED);
13058         }
13059         return 0;
13060 }
13061
13062 /*
13063  * Read and execute commands.
13064  * "Top" is nonzero for the top level command loop;
13065  * it turns on prompting if the shell is interactive.
13066  */
13067 static int
13068 cmdloop(int top)
13069 {
13070         union node *n;
13071         struct stackmark smark;
13072         int inter;
13073         int status = 0;
13074         int numeof = 0;
13075
13076         TRACE(("cmdloop(%d) called\n", top));
13077         for (;;) {
13078                 int skip;
13079
13080                 setstackmark(&smark);
13081 #if JOBS
13082                 if (doing_jobctl)
13083                         showjobs(SHOW_CHANGED|SHOW_STDERR);
13084 #endif
13085                 inter = 0;
13086                 if (iflag && top) {
13087                         inter++;
13088                         chkmail();
13089                 }
13090                 n = parsecmd(inter);
13091 #if DEBUG
13092                 if (DEBUG > 2 && debug && (n != NODE_EOF))
13093                         showtree(n);
13094 #endif
13095                 if (n == NODE_EOF) {
13096                         if (!top || numeof >= 50)
13097                                 break;
13098                         if (!stoppedjobs()) {
13099                                 if (!Iflag)
13100                                         break;
13101                                 out2str("\nUse \"exit\" to leave shell.\n");
13102                         }
13103                         numeof++;
13104                 } else if (nflag == 0) {
13105                         int i;
13106
13107                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
13108                         job_warning >>= 1;
13109                         numeof = 0;
13110                         i = evaltree(n, 0);
13111                         if (n)
13112                                 status = i;
13113                 }
13114                 popstackmark(&smark);
13115                 skip = evalskip;
13116
13117                 if (skip) {
13118                         evalskip &= ~SKIPFUNC;
13119                         break;
13120                 }
13121         }
13122         return status;
13123 }
13124
13125 /*
13126  * Take commands from a file.  To be compatible we should do a path
13127  * search for the file, which is necessary to find sub-commands.
13128  */
13129 static char *
13130 find_dot_file(char *name)
13131 {
13132         char *fullname;
13133         const char *path = pathval();
13134         struct stat statb;
13135
13136         /* don't try this for absolute or relative paths */
13137         if (strchr(name, '/'))
13138                 return name;
13139
13140         while ((fullname = path_advance(&path, name)) != NULL) {
13141                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
13142                         /*
13143                          * Don't bother freeing here, since it will
13144                          * be freed by the caller.
13145                          */
13146                         return fullname;
13147                 }
13148                 if (fullname != name)
13149                         stunalloc(fullname);
13150         }
13151         /* not found in PATH */
13152
13153 #if ENABLE_ASH_BASH_SOURCE_CURDIR
13154         return name;
13155 #else
13156         ash_msg_and_raise_error("%s: not found", name);
13157         /* NOTREACHED */
13158 #endif
13159 }
13160
13161 static int FAST_FUNC
13162 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
13163 {
13164         /* "false; . empty_file; echo $?" should print 0, not 1: */
13165         int status = 0;
13166         char *fullname;
13167         char **argv;
13168         char *args_need_save;
13169         volatile struct shparam saveparam;
13170
13171 //???
13172 //      struct strlist *sp;
13173 //      for (sp = cmdenviron; sp; sp = sp->next)
13174 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
13175
13176         nextopt(nullstr); /* handle possible "--" */
13177         argv = argptr;
13178
13179         if (!argv[0]) {
13180                 /* bash says: "bash: .: filename argument required" */
13181                 return 2; /* bash compat */
13182         }
13183
13184         /* This aborts if file isn't found, which is POSIXly correct.
13185          * bash returns exitcode 1 instead.
13186          */
13187         fullname = find_dot_file(argv[0]);
13188         argv++;
13189         args_need_save = argv[0];
13190         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
13191                 int argc;
13192                 saveparam = shellparam;
13193                 shellparam.malloced = 0;
13194                 argc = 1;
13195                 while (argv[argc])
13196                         argc++;
13197                 shellparam.nparam = argc;
13198                 shellparam.p = argv;
13199         };
13200
13201         /* This aborts if file can't be opened, which is POSIXly correct.
13202          * bash returns exitcode 1 instead.
13203          */
13204         setinputfile(fullname, INPUT_PUSH_FILE);
13205         commandname = fullname;
13206         status = cmdloop(0);
13207         popfile();
13208
13209         if (args_need_save) {
13210                 freeparam(&shellparam);
13211                 shellparam = saveparam;
13212         };
13213
13214         return status;
13215 }
13216
13217 static int FAST_FUNC
13218 exitcmd(int argc UNUSED_PARAM, char **argv)
13219 {
13220         if (stoppedjobs())
13221                 return 0;
13222         if (argv[1])
13223                 exitstatus = number(argv[1]);
13224         raise_exception(EXEXIT);
13225         /* NOTREACHED */
13226 }
13227
13228 /*
13229  * Read a file containing shell functions.
13230  */
13231 static void
13232 readcmdfile(char *name)
13233 {
13234         setinputfile(name, INPUT_PUSH_FILE);
13235         cmdloop(0);
13236         popfile();
13237 }
13238
13239
13240 /* ============ find_command inplementation */
13241
13242 /*
13243  * Resolve a command name.  If you change this routine, you may have to
13244  * change the shellexec routine as well.
13245  */
13246 static void
13247 find_command(char *name, struct cmdentry *entry, int act, const char *path)
13248 {
13249         struct tblentry *cmdp;
13250         int idx;
13251         int prev;
13252         char *fullname;
13253         struct stat statb;
13254         int e;
13255         int updatetbl;
13256         struct builtincmd *bcmd;
13257
13258         /* If name contains a slash, don't use PATH or hash table */
13259         if (strchr(name, '/') != NULL) {
13260                 entry->u.index = -1;
13261                 if (act & DO_ABS) {
13262                         while (stat(name, &statb) < 0) {
13263 #ifdef SYSV
13264                                 if (errno == EINTR)
13265                                         continue;
13266 #endif
13267                                 entry->cmdtype = CMDUNKNOWN;
13268                                 return;
13269                         }
13270                 }
13271                 entry->cmdtype = CMDNORMAL;
13272                 return;
13273         }
13274
13275 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
13276
13277         updatetbl = (path == pathval());
13278         if (!updatetbl) {
13279                 act |= DO_ALTPATH;
13280                 if (strstr(path, "%builtin") != NULL)
13281                         act |= DO_ALTBLTIN;
13282         }
13283
13284         /* If name is in the table, check answer will be ok */
13285         cmdp = cmdlookup(name, 0);
13286         if (cmdp != NULL) {
13287                 int bit;
13288
13289                 switch (cmdp->cmdtype) {
13290                 default:
13291 #if DEBUG
13292                         abort();
13293 #endif
13294                 case CMDNORMAL:
13295                         bit = DO_ALTPATH;
13296                         break;
13297                 case CMDFUNCTION:
13298                         bit = DO_NOFUNC;
13299                         break;
13300                 case CMDBUILTIN:
13301                         bit = DO_ALTBLTIN;
13302                         break;
13303                 }
13304                 if (act & bit) {
13305                         updatetbl = 0;
13306                         cmdp = NULL;
13307                 } else if (cmdp->rehash == 0)
13308                         /* if not invalidated by cd, we're done */
13309                         goto success;
13310         }
13311
13312         /* If %builtin not in path, check for builtin next */
13313         bcmd = find_builtin(name);
13314         if (bcmd) {
13315                 if (IS_BUILTIN_REGULAR(bcmd))
13316                         goto builtin_success;
13317                 if (act & DO_ALTPATH) {
13318                         if (!(act & DO_ALTBLTIN))
13319                                 goto builtin_success;
13320                 } else if (builtinloc <= 0) {
13321                         goto builtin_success;
13322                 }
13323         }
13324
13325 #if ENABLE_FEATURE_SH_STANDALONE
13326         {
13327                 int applet_no = find_applet_by_name(name);
13328                 if (applet_no >= 0) {
13329                         entry->cmdtype = CMDNORMAL;
13330                         entry->u.index = -2 - applet_no;
13331                         return;
13332                 }
13333         }
13334 #endif
13335
13336         /* We have to search path. */
13337         prev = -1;              /* where to start */
13338         if (cmdp && cmdp->rehash) {     /* doing a rehash */
13339                 if (cmdp->cmdtype == CMDBUILTIN)
13340                         prev = builtinloc;
13341                 else
13342                         prev = cmdp->param.index;
13343         }
13344
13345         e = ENOENT;
13346         idx = -1;
13347  loop:
13348         while ((fullname = path_advance(&path, name)) != NULL) {
13349                 stunalloc(fullname);
13350                 /* NB: code below will still use fullname
13351                  * despite it being "unallocated" */
13352                 idx++;
13353                 if (pathopt) {
13354                         if (prefix(pathopt, "builtin")) {
13355                                 if (bcmd)
13356                                         goto builtin_success;
13357                                 continue;
13358                         }
13359                         if ((act & DO_NOFUNC)
13360                          || !prefix(pathopt, "func")
13361                         ) {     /* ignore unimplemented options */
13362                                 continue;
13363                         }
13364                 }
13365                 /* if rehash, don't redo absolute path names */
13366                 if (fullname[0] == '/' && idx <= prev) {
13367                         if (idx < prev)
13368                                 continue;
13369                         TRACE(("searchexec \"%s\": no change\n", name));
13370                         goto success;
13371                 }
13372                 while (stat(fullname, &statb) < 0) {
13373 #ifdef SYSV
13374                         if (errno == EINTR)
13375                                 continue;
13376 #endif
13377                         if (errno != ENOENT && errno != ENOTDIR)
13378                                 e = errno;
13379                         goto loop;
13380                 }
13381                 e = EACCES;     /* if we fail, this will be the error */
13382                 if (!S_ISREG(statb.st_mode))
13383                         continue;
13384                 if (pathopt) {          /* this is a %func directory */
13385                         stalloc(strlen(fullname) + 1);
13386                         /* NB: stalloc will return space pointed by fullname
13387                          * (because we don't have any intervening allocations
13388                          * between stunalloc above and this stalloc) */
13389                         readcmdfile(fullname);
13390                         cmdp = cmdlookup(name, 0);
13391                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
13392                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
13393                         stunalloc(fullname);
13394                         goto success;
13395                 }
13396                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
13397                 if (!updatetbl) {
13398                         entry->cmdtype = CMDNORMAL;
13399                         entry->u.index = idx;
13400                         return;
13401                 }
13402                 INT_OFF;
13403                 cmdp = cmdlookup(name, 1);
13404                 cmdp->cmdtype = CMDNORMAL;
13405                 cmdp->param.index = idx;
13406                 INT_ON;
13407                 goto success;
13408         }
13409
13410         /* We failed.  If there was an entry for this command, delete it */
13411         if (cmdp && updatetbl)
13412                 delete_cmd_entry();
13413         if (act & DO_ERR) {
13414 #if ENABLE_ASH_BASH_NOT_FOUND_HOOK
13415                 struct tblentry *hookp = cmdlookup("command_not_found_handle", 0);
13416                 if (hookp && hookp->cmdtype == CMDFUNCTION) {
13417                         char *argv[3];
13418                         argv[0] = (char*) "command_not_found_handle";
13419                         argv[1] = name;
13420                         argv[2] = NULL;
13421                         evalfun(hookp->param.func, 2, argv, 0);
13422                         entry->cmdtype = CMDUNKNOWN;
13423                         return;
13424                 }
13425 #endif
13426                 ash_msg("%s: %s", name, errmsg(e, "not found"));
13427         }
13428         entry->cmdtype = CMDUNKNOWN;
13429         return;
13430
13431  builtin_success:
13432         if (!updatetbl) {
13433                 entry->cmdtype = CMDBUILTIN;
13434                 entry->u.cmd = bcmd;
13435                 return;
13436         }
13437         INT_OFF;
13438         cmdp = cmdlookup(name, 1);
13439         cmdp->cmdtype = CMDBUILTIN;
13440         cmdp->param.cmd = bcmd;
13441         INT_ON;
13442  success:
13443         cmdp->rehash = 0;
13444         entry->cmdtype = cmdp->cmdtype;
13445         entry->u = cmdp->param;
13446 }
13447
13448
13449 /*
13450  * The trap builtin.
13451  */
13452 static int FAST_FUNC
13453 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13454 {
13455         char *action;
13456         char **ap;
13457         int signo, exitcode;
13458
13459         nextopt(nullstr);
13460         ap = argptr;
13461         if (!*ap) {
13462                 for (signo = 0; signo < NSIG; signo++) {
13463                         char *tr = trap_ptr[signo];
13464                         if (tr) {
13465                                 /* note: bash adds "SIG", but only if invoked
13466                                  * as "bash". If called as "sh", or if set -o posix,
13467                                  * then it prints short signal names.
13468                                  * We are printing short names: */
13469                                 out1fmt("trap -- %s %s\n",
13470                                                 single_quote(tr),
13471                                                 get_signame(signo));
13472                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13473                  * In this case, we will exit very soon, no need to free(). */
13474                                 /* if (trap_ptr != trap && tp[0]) */
13475                                 /*      free(tr); */
13476                         }
13477                 }
13478                 /*
13479                 if (trap_ptr != trap) {
13480                         free(trap_ptr);
13481                         trap_ptr = trap;
13482                 }
13483                 */
13484                 return 0;
13485         }
13486
13487         /* Why the second check?
13488          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13489          * In this case, NUM is signal no, not an action.
13490          */
13491         action = NULL;
13492         if (ap[1] && !is_number(ap[0]))
13493                 action = *ap++;
13494
13495         exitcode = 0;
13496         while (*ap) {
13497                 signo = get_signum(*ap);
13498                 if (signo < 0) {
13499                         /* Mimic bash message exactly */
13500                         ash_msg("%s: invalid signal specification", *ap);
13501                         exitcode = 1;
13502                         goto next;
13503                 }
13504                 INT_OFF;
13505                 if (action) {
13506                         if (LONE_DASH(action))
13507                                 action = NULL;
13508                         else {
13509                                 if (action[0]) /* not NULL and not "" and not "-" */
13510                                         may_have_traps = 1;
13511                                 action = ckstrdup(action);
13512                         }
13513                 }
13514                 free(trap[signo]);
13515                 trap[signo] = action;
13516                 if (signo != 0)
13517                         setsignal(signo);
13518                 INT_ON;
13519  next:
13520                 ap++;
13521         }
13522         return exitcode;
13523 }
13524
13525
13526 /* ============ Builtins */
13527
13528 #if ENABLE_ASH_HELP
13529 static int FAST_FUNC
13530 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13531 {
13532         unsigned col;
13533         unsigned i;
13534
13535         out1fmt(
13536                 "Built-in commands:\n"
13537                 "------------------\n");
13538         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13539                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13540                                         builtintab[i].name + 1);
13541                 if (col > 60) {
13542                         out1fmt("\n");
13543                         col = 0;
13544                 }
13545         }
13546 # if ENABLE_FEATURE_SH_STANDALONE
13547         {
13548                 const char *a = applet_names;
13549                 while (*a) {
13550                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13551                         if (col > 60) {
13552                                 out1fmt("\n");
13553                                 col = 0;
13554                         }
13555                         while (*a++ != '\0')
13556                                 continue;
13557                 }
13558         }
13559 # endif
13560         newline_and_flush(stdout);
13561         return EXIT_SUCCESS;
13562 }
13563 #endif
13564
13565 #if MAX_HISTORY
13566 static int FAST_FUNC
13567 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13568 {
13569         show_history(line_input_state);
13570         return EXIT_SUCCESS;
13571 }
13572 #endif
13573
13574 /*
13575  * The export and readonly commands.
13576  */
13577 static int FAST_FUNC
13578 exportcmd(int argc UNUSED_PARAM, char **argv)
13579 {
13580         struct var *vp;
13581         char *name;
13582         const char *p;
13583         char **aptr;
13584         char opt;
13585         int flag;
13586         int flag_off;
13587
13588         /* "readonly" in bash accepts, but ignores -n.
13589          * We do the same: it saves a conditional in nextopt's param.
13590          */
13591         flag_off = 0;
13592         while ((opt = nextopt("np")) != '\0') {
13593                 if (opt == 'n')
13594                         flag_off = VEXPORT;
13595         }
13596         flag = VEXPORT;
13597         if (argv[0][0] == 'r') {
13598                 flag = VREADONLY;
13599                 flag_off = 0; /* readonly ignores -n */
13600         }
13601         flag_off = ~flag_off;
13602
13603         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13604         {
13605                 aptr = argptr;
13606                 name = *aptr;
13607                 if (name) {
13608                         do {
13609                                 p = strchr(name, '=');
13610                                 if (p != NULL) {
13611                                         p++;
13612                                 } else {
13613                                         vp = *findvar(hashvar(name), name);
13614                                         if (vp) {
13615                                                 vp->flags = ((vp->flags | flag) & flag_off);
13616                                                 continue;
13617                                         }
13618                                 }
13619                                 setvar(name, p, (flag & flag_off));
13620                         } while ((name = *++aptr) != NULL);
13621                         return 0;
13622                 }
13623         }
13624
13625         /* No arguments. Show the list of exported or readonly vars.
13626          * -n is ignored.
13627          */
13628         showvars(argv[0], flag, 0);
13629         return 0;
13630 }
13631
13632 /*
13633  * Delete a function if it exists.
13634  */
13635 static void
13636 unsetfunc(const char *name)
13637 {
13638         struct tblentry *cmdp;
13639
13640         cmdp = cmdlookup(name, 0);
13641         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13642                 delete_cmd_entry();
13643 }
13644
13645 /*
13646  * The unset builtin command.  We unset the function before we unset the
13647  * variable to allow a function to be unset when there is a readonly variable
13648  * with the same name.
13649  */
13650 static int FAST_FUNC
13651 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13652 {
13653         char **ap;
13654         int i;
13655         int flag = 0;
13656
13657         while ((i = nextopt("vf")) != 0) {
13658                 flag = i;
13659         }
13660
13661         for (ap = argptr; *ap; ap++) {
13662                 if (flag != 'f') {
13663                         unsetvar(*ap);
13664                         continue;
13665                 }
13666                 if (flag != 'v')
13667                         unsetfunc(*ap);
13668         }
13669         return 0;
13670 }
13671
13672 static const unsigned char timescmd_str[] ALIGN1 = {
13673         ' ',  offsetof(struct tms, tms_utime),
13674         '\n', offsetof(struct tms, tms_stime),
13675         ' ',  offsetof(struct tms, tms_cutime),
13676         '\n', offsetof(struct tms, tms_cstime),
13677         0
13678 };
13679 static int FAST_FUNC
13680 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13681 {
13682         unsigned clk_tck;
13683         const unsigned char *p;
13684         struct tms buf;
13685
13686         clk_tck = bb_clk_tck();
13687
13688         times(&buf);
13689         p = timescmd_str;
13690         do {
13691                 unsigned sec, frac;
13692                 unsigned long t;
13693                 t = *(clock_t *)(((char *) &buf) + p[1]);
13694                 sec = t / clk_tck;
13695                 frac = t % clk_tck;
13696                 out1fmt("%um%u.%03us%c",
13697                         sec / 60, sec % 60,
13698                         (frac * 1000) / clk_tck,
13699                         p[0]);
13700                 p += 2;
13701         } while (*p);
13702
13703         return 0;
13704 }
13705
13706 #if ENABLE_FEATURE_SH_MATH
13707 /*
13708  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13709  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13710  *
13711  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13712  */
13713 static int FAST_FUNC
13714 letcmd(int argc UNUSED_PARAM, char **argv)
13715 {
13716         arith_t i;
13717
13718         argv++;
13719         if (!*argv)
13720                 ash_msg_and_raise_error("expression expected");
13721         do {
13722                 i = ash_arith(*argv);
13723         } while (*++argv);
13724
13725         return !i;
13726 }
13727 #endif
13728
13729 /*
13730  * The read builtin. Options:
13731  *      -r              Do not interpret '\' specially
13732  *      -s              Turn off echo (tty only)
13733  *      -n NCHARS       Read NCHARS max
13734  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13735  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13736  *      -u FD           Read from given FD instead of fd 0
13737  *      -d DELIM        End on DELIM char, not newline
13738  * This uses unbuffered input, which may be avoidable in some cases.
13739  * TODO: bash also has:
13740  *      -a ARRAY        Read into array[0],[1],etc
13741  *      -e              Use line editing (tty only)
13742  */
13743 static int FAST_FUNC
13744 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13745 {
13746         char *opt_n = NULL;
13747         char *opt_p = NULL;
13748         char *opt_t = NULL;
13749         char *opt_u = NULL;
13750         char *opt_d = NULL; /* optimized out if !BASH */
13751         int read_flags = 0;
13752         const char *r;
13753         int i;
13754
13755         while ((i = nextopt("p:u:rt:n:sd:")) != '\0') {
13756                 switch (i) {
13757                 case 'p':
13758                         opt_p = optionarg;
13759                         break;
13760                 case 'n':
13761                         opt_n = optionarg;
13762                         break;
13763                 case 's':
13764                         read_flags |= BUILTIN_READ_SILENT;
13765                         break;
13766                 case 't':
13767                         opt_t = optionarg;
13768                         break;
13769                 case 'r':
13770                         read_flags |= BUILTIN_READ_RAW;
13771                         break;
13772                 case 'u':
13773                         opt_u = optionarg;
13774                         break;
13775 #if BASH_READ_D
13776                 case 'd':
13777                         opt_d = optionarg;
13778                         break;
13779 #endif
13780                 default:
13781                         break;
13782                 }
13783         }
13784
13785         /* "read -s" needs to save/restore termios, can't allow ^C
13786          * to jump out of it.
13787          */
13788  again:
13789         INT_OFF;
13790         r = shell_builtin_read(setvar0,
13791                 argptr,
13792                 bltinlookup("IFS"), /* can be NULL */
13793                 read_flags,
13794                 opt_n,
13795                 opt_p,
13796                 opt_t,
13797                 opt_u,
13798                 opt_d
13799         );
13800         INT_ON;
13801
13802         if ((uintptr_t)r == 1 && errno == EINTR) {
13803                 /* To get SIGCHLD: sleep 1 & read x; echo $x
13804                  * Correct behavior is to not exit "read"
13805                  */
13806                 if (pending_sig == 0)
13807                         goto again;
13808         }
13809
13810         if ((uintptr_t)r > 1)
13811                 ash_msg_and_raise_error(r);
13812
13813         return (uintptr_t)r;
13814 }
13815
13816 static int FAST_FUNC
13817 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13818 {
13819         static const char permuser[3] ALIGN1 = "ogu";
13820
13821         mode_t mask;
13822         int symbolic_mode = 0;
13823
13824         while (nextopt("S") != '\0') {
13825                 symbolic_mode = 1;
13826         }
13827
13828         INT_OFF;
13829         mask = umask(0);
13830         umask(mask);
13831         INT_ON;
13832
13833         if (*argptr == NULL) {
13834                 if (symbolic_mode) {
13835                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13836                         char *p = buf;
13837                         int i;
13838
13839                         i = 2;
13840                         for (;;) {
13841                                 *p++ = ',';
13842                                 *p++ = permuser[i];
13843                                 *p++ = '=';
13844                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13845                                 if (!(mask & 0400)) *p++ = 'r';
13846                                 if (!(mask & 0200)) *p++ = 'w';
13847                                 if (!(mask & 0100)) *p++ = 'x';
13848                                 mask <<= 3;
13849                                 if (--i < 0)
13850                                         break;
13851                         }
13852                         *p = '\0';
13853                         puts(buf + 1);
13854                 } else {
13855                         out1fmt("%04o\n", mask);
13856                 }
13857         } else {
13858                 char *modestr = *argptr;
13859                 /* numeric umasks are taken as-is */
13860                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13861                 if (!isdigit(modestr[0]))
13862                         mask ^= 0777;
13863                 mask = bb_parse_mode(modestr, mask);
13864                 if ((unsigned)mask > 0777) {
13865                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13866                 }
13867                 if (!isdigit(modestr[0]))
13868                         mask ^= 0777;
13869                 umask(mask);
13870         }
13871         return 0;
13872 }
13873
13874 static int FAST_FUNC
13875 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13876 {
13877         return shell_builtin_ulimit(argv);
13878 }
13879
13880 /* ============ main() and helpers */
13881
13882 /*
13883  * Called to exit the shell.
13884  */
13885 static void
13886 exitshell(void)
13887 {
13888         struct jmploc loc;
13889         char *p;
13890         int status;
13891
13892 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13893         save_history(line_input_state);
13894 #endif
13895         status = exitstatus;
13896         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13897         if (setjmp(loc.loc)) {
13898                 if (exception_type == EXEXIT)
13899                         status = exitstatus;
13900                 goto out;
13901         }
13902         exception_handler = &loc;
13903         p = trap[0];
13904         if (p) {
13905                 trap[0] = NULL;
13906                 evalskip = 0;
13907                 evalstring(p, 0);
13908                 /*free(p); - we'll exit soon */
13909         }
13910  out:
13911         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13912          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13913          */
13914         setjobctl(0);
13915         flush_stdout_stderr();
13916         _exit(status);
13917         /* NOTREACHED */
13918 }
13919
13920 /* Don't inline: conserve stack of caller from having our locals too */
13921 static NOINLINE void
13922 init(void)
13923 {
13924         /* we will never free this */
13925         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13926         basepf.linno = 1;
13927
13928         sigmode[SIGCHLD - 1] = S_DFL; /* ensure we install handler even if it is SIG_IGNed */
13929         setsignal(SIGCHLD);
13930
13931         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13932          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13933          */
13934         signal(SIGHUP, SIG_DFL);
13935
13936         {
13937                 char **envp;
13938                 const char *p;
13939
13940                 initvar();
13941                 for (envp = environ; envp && *envp; envp++) {
13942 /* Used to have
13943  *                      p = endofname(*envp);
13944  *                      if (p != *envp && *p == '=') {
13945  * here to weed out badly-named variables, but this breaks
13946  * scenarios where people do want them passed to children:
13947  * import os
13948  * os.environ["test-test"]="test"
13949  * if os.fork() == 0:
13950  *   os.execv("ash", [ 'ash', '-c', 'eval $(export -p); echo OK' ])  # fixes this
13951  * os.execv("ash", [ 'ash', '-c', 'env | grep test-test' ])  # breaks this
13952  */
13953                         if (strchr(*envp, '=')) {
13954                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13955                         }
13956                 }
13957
13958                 setvareq((char*)defoptindvar, VTEXTFIXED);
13959
13960                 setvar0("PPID", utoa(getppid()));
13961 #if BASH_SHLVL_VAR
13962                 p = lookupvar("SHLVL");
13963                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13964 #endif
13965 #if BASH_HOSTNAME_VAR
13966                 if (!lookupvar("HOSTNAME")) {
13967                         struct utsname uts;
13968                         uname(&uts);
13969                         setvar0("HOSTNAME", uts.nodename);
13970                 }
13971 #endif
13972                 p = lookupvar("PWD");
13973                 if (p) {
13974                         struct stat st1, st2;
13975                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13976                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13977                         ) {
13978                                 p = NULL;
13979                         }
13980                 }
13981                 setpwd(p, 0);
13982         }
13983 }
13984
13985
13986 //usage:#define ash_trivial_usage
13987 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS] / -s [ARGS]]"
13988 //usage:#define ash_full_usage "\n\n"
13989 //usage:        "Unix shell interpreter"
13990
13991 /*
13992  * Process the shell command line arguments.
13993  */
13994 static int
13995 procargs(char **argv)
13996 {
13997         int i;
13998         const char *xminusc;
13999         char **xargv;
14000         int login_sh;
14001
14002         xargv = argv;
14003         login_sh = xargv[0] && xargv[0][0] == '-';
14004         arg0 = xargv[0];
14005         /* if (xargv[0]) - mmm, this is always true! */
14006                 xargv++;
14007         for (i = 0; i < NOPTS; i++)
14008                 optlist[i] = 2;
14009         argptr = xargv;
14010         if (options(/*cmdline:*/ 1, &login_sh)) {
14011                 /* it already printed err message */
14012                 raise_exception(EXERROR);
14013         }
14014         xargv = argptr;
14015         xminusc = minusc;
14016         if (*xargv == NULL) {
14017                 if (xminusc)
14018                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
14019                 sflag = 1;
14020         }
14021         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
14022                 iflag = 1;
14023         if (mflag == 2)
14024                 mflag = iflag;
14025         for (i = 0; i < NOPTS; i++)
14026                 if (optlist[i] == 2)
14027                         optlist[i] = 0;
14028 #if DEBUG == 2
14029         debug = 1;
14030 #endif
14031         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
14032         if (xminusc) {
14033                 minusc = *xargv++;
14034                 if (*xargv)
14035                         goto setarg0;
14036         } else if (!sflag) {
14037                 setinputfile(*xargv, 0);
14038  setarg0:
14039                 arg0 = *xargv++;
14040                 commandname = arg0;
14041         }
14042
14043         shellparam.p = xargv;
14044 #if ENABLE_ASH_GETOPTS
14045         shellparam.optind = 1;
14046         shellparam.optoff = -1;
14047 #endif
14048         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
14049         while (*xargv) {
14050                 shellparam.nparam++;
14051                 xargv++;
14052         }
14053         optschanged();
14054
14055         return login_sh;
14056 }
14057
14058 /*
14059  * Read /etc/profile, ~/.profile, $ENV.
14060  */
14061 static void
14062 read_profile(const char *name)
14063 {
14064         name = expandstr(name, DQSYNTAX);
14065         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
14066                 return;
14067         cmdloop(0);
14068         popfile();
14069 }
14070
14071 /*
14072  * This routine is called when an error or an interrupt occurs in an
14073  * interactive shell and control is returned to the main command loop.
14074  * (In dash, this function is auto-generated by build machinery).
14075  */
14076 static void
14077 reset(void)
14078 {
14079         /* from eval.c: */
14080         evalskip = 0;
14081         loopnest = 0;
14082
14083         /* from expand.c: */
14084         ifsfree();
14085
14086         /* from input.c: */
14087         g_parsefile->left_in_buffer = 0;
14088         g_parsefile->left_in_line = 0;      /* clear input buffer */
14089         popallfiles();
14090
14091         /* from redir.c: */
14092         unwindredir(NULL);
14093
14094         /* from var.c: */
14095         unwindlocalvars(NULL);
14096 }
14097
14098 #if PROFILE
14099 static short profile_buf[16384];
14100 extern int etext();
14101 #endif
14102
14103 /*
14104  * Main routine.  We initialize things, parse the arguments, execute
14105  * profiles if we're a login shell, and then call cmdloop to execute
14106  * commands.  The setjmp call sets up the location to jump to when an
14107  * exception occurs.  When an exception occurs the variable "state"
14108  * is used to figure out how far we had gotten.
14109  */
14110 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
14111 int ash_main(int argc UNUSED_PARAM, char **argv)
14112 {
14113         volatile smallint state;
14114         struct jmploc jmploc;
14115         struct stackmark smark;
14116         int login_sh;
14117
14118         /* Initialize global data */
14119         INIT_G_misc();
14120         INIT_G_memstack();
14121         INIT_G_var();
14122 #if ENABLE_ASH_ALIAS
14123         INIT_G_alias();
14124 #endif
14125         INIT_G_cmdtable();
14126
14127 #if PROFILE
14128         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
14129 #endif
14130
14131 #if ENABLE_FEATURE_EDITING
14132         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
14133 #endif
14134         state = 0;
14135         if (setjmp(jmploc.loc)) {
14136                 smallint e;
14137                 smallint s;
14138
14139                 reset();
14140
14141                 e = exception_type;
14142                 s = state;
14143                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
14144                         exitshell();
14145                 }
14146                 if (e == EXINT) {
14147                         newline_and_flush(stderr);
14148                 }
14149
14150                 popstackmark(&smark);
14151                 FORCE_INT_ON; /* enable interrupts */
14152                 if (s == 1)
14153                         goto state1;
14154                 if (s == 2)
14155                         goto state2;
14156                 if (s == 3)
14157                         goto state3;
14158                 goto state4;
14159         }
14160         exception_handler = &jmploc;
14161         rootpid = getpid();
14162
14163         init();
14164         setstackmark(&smark);
14165         login_sh = procargs(argv);
14166 #if DEBUG
14167         TRACE(("Shell args: "));
14168         trace_puts_args(argv);
14169 #endif
14170
14171         if (login_sh) {
14172                 const char *hp;
14173
14174                 state = 1;
14175                 read_profile("/etc/profile");
14176  state1:
14177                 state = 2;
14178                 hp = lookupvar("HOME");
14179                 if (hp)
14180                         read_profile("$HOME/.profile");
14181         }
14182  state2:
14183         state = 3;
14184         if (
14185 #ifndef linux
14186          getuid() == geteuid() && getgid() == getegid() &&
14187 #endif
14188          iflag
14189         ) {
14190                 const char *shinit = lookupvar("ENV");
14191                 if (shinit != NULL && *shinit != '\0')
14192                         read_profile(shinit);
14193         }
14194         popstackmark(&smark);
14195  state3:
14196         state = 4;
14197         if (minusc) {
14198                 /* evalstring pushes parsefile stack.
14199                  * Ensure we don't falsely claim that 0 (stdin)
14200                  * is one of stacked source fds.
14201                  * Testcase: ash -c 'exec 1>&0' must not complain. */
14202                 // if (!sflag) g_parsefile->pf_fd = -1;
14203                 // ^^ not necessary since now we special-case fd 0
14204                 // in save_fd_on_redirect()
14205                 evalstring(minusc, sflag ? 0 : EV_EXIT);
14206         }
14207
14208         if (sflag || minusc == NULL) {
14209 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
14210                 if (iflag) {
14211                         const char *hp = lookupvar("HISTFILE");
14212                         if (!hp) {
14213                                 hp = lookupvar("HOME");
14214                                 if (hp) {
14215                                         INT_OFF;
14216                                         hp = concat_path_file(hp, ".ash_history");
14217                                         setvar0("HISTFILE", hp);
14218                                         free((char*)hp);
14219                                         INT_ON;
14220                                         hp = lookupvar("HISTFILE");
14221                                 }
14222                         }
14223                         if (hp)
14224                                 line_input_state->hist_file = hp;
14225 # if ENABLE_FEATURE_SH_HISTFILESIZE
14226                         hp = lookupvar("HISTFILESIZE");
14227                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
14228 # endif
14229                 }
14230 #endif
14231  state4: /* XXX ??? - why isn't this before the "if" statement */
14232                 cmdloop(1);
14233         }
14234 #if PROFILE
14235         monitor(0);
14236 #endif
14237 #ifdef GPROF
14238         {
14239                 extern void _mcleanup(void);
14240                 _mcleanup();
14241         }
14242 #endif
14243         TRACE(("End of main reached\n"));
14244         exitshell();
14245         /* NOTREACHED */
14246 }
14247
14248
14249 /*-
14250  * Copyright (c) 1989, 1991, 1993, 1994
14251  *      The Regents of the University of California.  All rights reserved.
14252  *
14253  * This code is derived from software contributed to Berkeley by
14254  * Kenneth Almquist.
14255  *
14256  * Redistribution and use in source and binary forms, with or without
14257  * modification, are permitted provided that the following conditions
14258  * are met:
14259  * 1. Redistributions of source code must retain the above copyright
14260  *    notice, this list of conditions and the following disclaimer.
14261  * 2. Redistributions in binary form must reproduce the above copyright
14262  *    notice, this list of conditions and the following disclaimer in the
14263  *    documentation and/or other materials provided with the distribution.
14264  * 3. Neither the name of the University nor the names of its contributors
14265  *    may be used to endorse or promote products derived from this software
14266  *    without specific prior written permission.
14267  *
14268  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND
14269  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14270  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
14271  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
14272  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
14273  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
14274  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
14275  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
14276  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
14277  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14278  * SUCH DAMAGE.
14279  */