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