ash: if !ENABLE_ASH_EXPAND_PRMT, disable PSSYNTAX code
[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_JOB_CONTROL
55 //config:       bool "Job control"
56 //config:       default y
57 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
58 //config:
59 //config:config ASH_ALIAS
60 //config:       bool "Alias support"
61 //config:       default y
62 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
63 //config:
64 //config:config ASH_RANDOM_SUPPORT
65 //config:       bool "Pseudorandom generator and $RANDOM variable"
66 //config:       default y
67 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
68 //config:       help
69 //config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
70 //config:       Each read of "$RANDOM" will generate a new pseudorandom value.
71 //config:       You can reset the generator by using a specified start value.
72 //config:       After "unset RANDOM" the generator will switch off and this
73 //config:       variable will no longer have special treatment.
74 //config:
75 //config:config ASH_EXPAND_PRMT
76 //config:       bool "Expand prompt string"
77 //config:       default y
78 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
79 //config:       help
80 //config:       $PS# may contain volatile content, such as backquote commands.
81 //config:       This option recreates the prompt string from the environment
82 //config:       variable each time it is displayed.
83 //config:
84 //config:config ASH_IDLE_TIMEOUT
85 //config:       bool "Idle timeout variable $TMOUT"
86 //config:       default y
87 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
88 //config:       help
89 //config:       Enable bash-like auto-logout after $TMOUT seconds of idle time.
90 //config:
91 //config:config ASH_MAIL
92 //config:       bool "Check for new mail in interactive shell"
93 //config:       default y
94 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
95 //config:       help
96 //config:       Enable "check for new mail" function:
97 //config:       if set, $MAIL file and $MAILPATH list of files
98 //config:       are checked for mtime changes, and "you have mail"
99 //config:       message is printed if change is detected.
100 //config:
101 //config:config ASH_ECHO
102 //config:       bool "echo builtin"
103 //config:       default y
104 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
105 //config:
106 //config:config ASH_PRINTF
107 //config:       bool "printf builtin"
108 //config:       default y
109 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
110 //config:
111 //config:config ASH_TEST
112 //config:       bool "test builtin"
113 //config:       default y
114 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
115 //config:
116 //config:config ASH_HELP
117 //config:       bool "help builtin"
118 //config:       default y
119 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
120 //config:
121 //config:config ASH_GETOPTS
122 //config:       bool "getopts builtin"
123 //config:       default y
124 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
125 //config:
126 //config:config ASH_CMDCMD
127 //config:       bool "command builtin"
128 //config:       default y
129 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
130 //config:       help
131 //config:       Enable support for the 'command' builtin, which allows
132 //config:       you to run the specified command or builtin,
133 //config:       even when there is a function with the same name.
134 //config:
135 //config:endif # ash options
136
137 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
138 //                      APPLET_ODDNAME:name  main location    suid_type     help
139 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
140 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
141
142 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
143 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
144 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
145 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
146
147 /*
148  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
149  * DEBUG=2 to compile in and turn on debugging.
150  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
151  * debugging info is written to ./trace, quit signal generates core dump.
152  */
153 #define DEBUG 0
154 /* Tweak debug output verbosity here */
155 #define DEBUG_TIME 0
156 #define DEBUG_PID 1
157 #define DEBUG_SIG 1
158 #define DEBUG_INTONOFF 0
159
160 #define PROFILE 0
161
162 #define JOBS ENABLE_ASH_JOB_CONTROL
163
164 #include <setjmp.h>
165 #include <fnmatch.h>
166 #include <sys/times.h>
167 #include <sys/utsname.h> /* for setting $HOSTNAME */
168 #include "busybox.h" /* for applet_names */
169
170 /* So far, all bash compat is controlled by one config option */
171 /* Separate defines document which part of code implements what */
172 /* function keyword */
173 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
174 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
175 /* &>file */
176 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
177 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
178 /* $'...' */
179 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
180 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
181 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
182 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
183 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
184 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
185 /* [[ EXPR ]] */
186 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
187 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
188 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
189 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
190 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
191
192 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
193 /* Bionic at least up to version 24 has no glob() */
194 # undef  ENABLE_ASH_INTERNAL_GLOB
195 # define ENABLE_ASH_INTERNAL_GLOB 1
196 #endif
197
198 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
199 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
200 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
201 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
202 # error glob() should unbackslash them and match. uClibc does not unbackslash,
203 # error fails to match dirname, subsequently not expanding <pattern> in it.
204 // Testcase:
205 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
206 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
207 #endif
208
209 #if !ENABLE_ASH_INTERNAL_GLOB
210 # include <glob.h>
211 #endif
212
213 #include "unicode.h"
214 #include "shell_common.h"
215 #if ENABLE_FEATURE_SH_MATH
216 # include "math.h"
217 #else
218 typedef long arith_t;
219 # define ARITH_FMT "%ld"
220 #endif
221 #if ENABLE_ASH_RANDOM_SUPPORT
222 # include "random.h"
223 #else
224 # define CLEAR_RANDOM_T(rnd) ((void)0)
225 #endif
226
227 #include "NUM_APPLETS.h"
228 #if NUM_APPLETS == 1
229 /* STANDALONE does not make sense, and won't compile */
230 # undef CONFIG_FEATURE_SH_STANDALONE
231 # undef ENABLE_FEATURE_SH_STANDALONE
232 # undef IF_FEATURE_SH_STANDALONE
233 # undef IF_NOT_FEATURE_SH_STANDALONE
234 # define ENABLE_FEATURE_SH_STANDALONE 0
235 # define IF_FEATURE_SH_STANDALONE(...)
236 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
237 #endif
238
239 #ifndef PIPE_BUF
240 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
241 #endif
242
243 #if !BB_MMU
244 # error "Do not even bother, ash will not run on NOMMU machine"
245 #endif
246
247
248 /* ============ Hash table sizes. Configurable. */
249
250 #define VTABSIZE 39
251 #define ATABSIZE 39
252 #define CMDTABLESIZE 31         /* should be prime */
253
254
255 /* ============ Shell options */
256
257 static const char *const optletters_optnames[] = {
258         "e"   "errexit",
259         "f"   "noglob",
260         "I"   "ignoreeof",
261         "i"   "interactive",
262         "m"   "monitor",
263         "n"   "noexec",
264         "s"   "stdin",
265         "x"   "xtrace",
266         "v"   "verbose",
267         "C"   "noclobber",
268         "a"   "allexport",
269         "b"   "notify",
270         "u"   "nounset",
271         "\0"  "vi"
272 #if BASH_PIPEFAIL
273         ,"\0"  "pipefail"
274 #endif
275 #if DEBUG
276         ,"\0"  "nolog"
277         ,"\0"  "debug"
278 #endif
279 };
280
281 #define optletters(n)  optletters_optnames[n][0]
282 #define optnames(n)   (optletters_optnames[n] + 1)
283
284 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
285
286
287 /* ============ Misc data */
288
289 #define msg_illnum "Illegal number: %s"
290
291 /*
292  * We enclose jmp_buf in a structure so that we can declare pointers to
293  * jump locations.  The global variable handler contains the location to
294  * jump to when an exception occurs, and the global variable exception_type
295  * contains a code identifying the exception.  To implement nested
296  * exception handlers, the user should save the value of handler on entry
297  * to an inner scope, set handler to point to a jmploc structure for the
298  * inner scope, and restore handler on exit from the scope.
299  */
300 struct jmploc {
301         jmp_buf loc;
302 };
303
304 struct globals_misc {
305         uint8_t exitstatus;     /* exit status of last command */
306         uint8_t back_exitstatus;/* exit status of backquoted command */
307         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
308         int rootpid;            /* pid of main shell */
309         /* shell level: 0 for the main shell, 1 for its children, and so on */
310         int shlvl;
311 #define rootshell (!shlvl)
312         char *minusc;  /* argument to -c option */
313
314         char *curdir; // = nullstr;     /* current working directory */
315         char *physdir; // = nullstr;    /* physical working directory */
316
317         char *arg0; /* value of $0 */
318
319         struct jmploc *exception_handler;
320
321         volatile int suppress_int; /* counter */
322         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
323         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
324         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
325         smallint exception_type; /* kind of exception (0..5) */
326         /* exceptions */
327 #define EXINT 0         /* SIGINT received */
328 #define EXERROR 1       /* a generic error */
329 #define EXEXIT 4        /* exit the shell */
330
331         smallint isloginsh;
332         char nullstr[1];        /* zero length string */
333
334         char optlist[NOPTS];
335 #define eflag optlist[0]
336 #define fflag optlist[1]
337 #define Iflag optlist[2]
338 #define iflag optlist[3]
339 #define mflag optlist[4]
340 #define nflag optlist[5]
341 #define sflag optlist[6]
342 #define xflag optlist[7]
343 #define vflag optlist[8]
344 #define Cflag optlist[9]
345 #define aflag optlist[10]
346 #define bflag optlist[11]
347 #define uflag optlist[12]
348 #define viflag optlist[13]
349 #if BASH_PIPEFAIL
350 # define pipefail optlist[14]
351 #else
352 # define pipefail 0
353 #endif
354 #if DEBUG
355 # define nolog optlist[14 + BASH_PIPEFAIL]
356 # define debug optlist[15 + BASH_PIPEFAIL]
357 #endif
358
359         /* trap handler commands */
360         /*
361          * Sigmode records the current value of the signal handlers for the various
362          * modes.  A value of zero means that the current handler is not known.
363          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
364          */
365         char sigmode[NSIG - 1];
366 #define S_DFL      1            /* default signal handling (SIG_DFL) */
367 #define S_CATCH    2            /* signal is caught */
368 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
369 #define S_HARD_IGN 4            /* signal is ignored permanently */
370
371         /* indicates specified signal received */
372         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
373         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
374         char *trap[NSIG];
375         char **trap_ptr;        /* used only by "trap hack" */
376
377         /* Rarely referenced stuff */
378 #if ENABLE_ASH_RANDOM_SUPPORT
379         random_t random_gen;
380 #endif
381         pid_t backgndpid;        /* pid of last background process */
382 };
383 extern struct globals_misc *const ash_ptr_to_globals_misc;
384 #define G_misc (*ash_ptr_to_globals_misc)
385 #define exitstatus        (G_misc.exitstatus )
386 #define back_exitstatus   (G_misc.back_exitstatus )
387 #define job_warning       (G_misc.job_warning)
388 #define rootpid     (G_misc.rootpid    )
389 #define shlvl       (G_misc.shlvl      )
390 #define minusc      (G_misc.minusc     )
391 #define curdir      (G_misc.curdir     )
392 #define physdir     (G_misc.physdir    )
393 #define arg0        (G_misc.arg0       )
394 #define exception_handler (G_misc.exception_handler)
395 #define exception_type    (G_misc.exception_type   )
396 #define suppress_int      (G_misc.suppress_int     )
397 #define pending_int       (G_misc.pending_int      )
398 #define got_sigchld       (G_misc.got_sigchld      )
399 #define pending_sig       (G_misc.pending_sig      )
400 #define isloginsh   (G_misc.isloginsh  )
401 #define nullstr     (G_misc.nullstr    )
402 #define optlist     (G_misc.optlist    )
403 #define sigmode     (G_misc.sigmode    )
404 #define gotsig      (G_misc.gotsig     )
405 #define may_have_traps    (G_misc.may_have_traps   )
406 #define trap        (G_misc.trap       )
407 #define trap_ptr    (G_misc.trap_ptr   )
408 #define random_gen  (G_misc.random_gen )
409 #define backgndpid  (G_misc.backgndpid )
410 #define INIT_G_misc() do { \
411         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
412         barrier(); \
413         curdir = nullstr; \
414         physdir = nullstr; \
415         trap_ptr = trap; \
416 } while (0)
417
418
419 /* ============ DEBUG */
420 #if DEBUG
421 static void trace_printf(const char *fmt, ...);
422 static void trace_vprintf(const char *fmt, va_list va);
423 # define TRACE(param)    trace_printf param
424 # define TRACEV(param)   trace_vprintf param
425 # define close(fd) do { \
426         int dfd = (fd); \
427         if (close(dfd) < 0) \
428                 bb_error_msg("bug on %d: closing %d(0x%x)", \
429                         __LINE__, dfd, dfd); \
430 } while (0)
431 #else
432 # define TRACE(param)
433 # define TRACEV(param)
434 #endif
435
436
437 /* ============ Utility functions */
438 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
439 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
440
441 static int
442 isdigit_str9(const char *str)
443 {
444         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
445         while (--maxlen && isdigit(*str))
446                 str++;
447         return (*str == '\0');
448 }
449
450 static const char *
451 var_end(const char *var)
452 {
453         while (*var)
454                 if (*var++ == '=')
455                         break;
456         return var;
457 }
458
459
460 /* ============ Interrupts / exceptions */
461
462 static void exitshell(void) NORETURN;
463
464 /*
465  * These macros allow the user to suspend the handling of interrupt signals
466  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
467  * much more efficient and portable.  (But hacking the kernel is so much
468  * more fun than worrying about efficiency and portability. :-))
469  */
470 #if DEBUG_INTONOFF
471 # define INT_OFF do { \
472         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
473         suppress_int++; \
474         barrier(); \
475 } while (0)
476 #else
477 # define INT_OFF do { \
478         suppress_int++; \
479         barrier(); \
480 } while (0)
481 #endif
482
483 /*
484  * Called to raise an exception.  Since C doesn't include exceptions, we
485  * just do a longjmp to the exception handler.  The type of exception is
486  * stored in the global variable "exception_type".
487  */
488 static void raise_exception(int) NORETURN;
489 static void
490 raise_exception(int e)
491 {
492 #if DEBUG
493         if (exception_handler == NULL)
494                 abort();
495 #endif
496         INT_OFF;
497         exception_type = e;
498         longjmp(exception_handler->loc, 1);
499 }
500 #if DEBUG
501 #define raise_exception(e) do { \
502         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
503         raise_exception(e); \
504 } while (0)
505 #endif
506
507 /*
508  * Called when a SIGINT is received.  (If the user specifies
509  * that SIGINT is to be trapped or ignored using the trap builtin, then
510  * this routine is not called.)  Suppressint is nonzero when interrupts
511  * are held using the INT_OFF macro.  (The test for iflag is just
512  * defensive programming.)
513  */
514 static void raise_interrupt(void) NORETURN;
515 static void
516 raise_interrupt(void)
517 {
518         pending_int = 0;
519         /* Signal is not automatically unmasked after it is raised,
520          * do it ourself - unmask all signals */
521         sigprocmask_allsigs(SIG_UNBLOCK);
522         /* pending_sig = 0; - now done in signal_handler() */
523
524         if (!(rootshell && iflag)) {
525                 /* Kill ourself with SIGINT */
526                 signal(SIGINT, SIG_DFL);
527                 raise(SIGINT);
528         }
529         /* bash: ^C even on empty command line sets $? */
530         exitstatus = SIGINT + 128;
531         raise_exception(EXINT);
532         /* NOTREACHED */
533 }
534 #if DEBUG
535 #define raise_interrupt() do { \
536         TRACE(("raising interrupt on line %d\n", __LINE__)); \
537         raise_interrupt(); \
538 } while (0)
539 #endif
540
541 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
542 int_on(void)
543 {
544         barrier();
545         if (--suppress_int == 0 && pending_int) {
546                 raise_interrupt();
547         }
548 }
549 #if DEBUG_INTONOFF
550 # define INT_ON do { \
551         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
552         int_on(); \
553 } while (0)
554 #else
555 # define INT_ON int_on()
556 #endif
557 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
558 force_int_on(void)
559 {
560         barrier();
561         suppress_int = 0;
562         if (pending_int)
563                 raise_interrupt();
564 }
565 #define FORCE_INT_ON force_int_on()
566
567 #define SAVE_INT(v) ((v) = suppress_int)
568
569 #define RESTORE_INT(v) do { \
570         barrier(); \
571         suppress_int = (v); \
572         if (suppress_int == 0 && pending_int) \
573                 raise_interrupt(); \
574 } while (0)
575
576
577 /* ============ Stdout/stderr output */
578
579 static void
580 outstr(const char *p, FILE *file)
581 {
582         INT_OFF;
583         fputs(p, file);
584         INT_ON;
585 }
586
587 static void
588 flush_stdout_stderr(void)
589 {
590         INT_OFF;
591         fflush_all();
592         INT_ON;
593 }
594
595 /* Was called outcslow(c,FILE*), but c was always '\n' */
596 static void
597 newline_and_flush(FILE *dest)
598 {
599         INT_OFF;
600         putc('\n', dest);
601         fflush(dest);
602         INT_ON;
603 }
604
605 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
606 static int
607 out1fmt(const char *fmt, ...)
608 {
609         va_list ap;
610         int r;
611
612         INT_OFF;
613         va_start(ap, fmt);
614         r = vprintf(fmt, ap);
615         va_end(ap);
616         INT_ON;
617         return r;
618 }
619
620 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
621 static int
622 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
623 {
624         va_list ap;
625         int ret;
626
627         INT_OFF;
628         va_start(ap, fmt);
629         ret = vsnprintf(outbuf, length, fmt, ap);
630         va_end(ap);
631         INT_ON;
632         return ret;
633 }
634
635 static void
636 out1str(const char *p)
637 {
638         outstr(p, stdout);
639 }
640
641 static void
642 out2str(const char *p)
643 {
644         outstr(p, stderr);
645         flush_stdout_stderr();
646 }
647
648
649 /* ============ Parser structures */
650
651 /* control characters in argument strings */
652 #define CTL_FIRST CTLESC
653 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
654 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
655 #define CTLENDVAR    ((unsigned char)'\203')
656 #define CTLBACKQ     ((unsigned char)'\204')
657 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
658 #define CTLENDARI    ((unsigned char)'\207')
659 #define CTLQUOTEMARK ((unsigned char)'\210')
660 #define CTL_LAST CTLQUOTEMARK
661
662 /* variable substitution byte (follows CTLVAR) */
663 #define VSTYPE  0x0f            /* type of variable substitution */
664 #define VSNUL   0x10            /* colon--treat the empty string as unset */
665
666 /* values of VSTYPE field */
667 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
668 #define VSMINUS         0x2     /* ${var-text} */
669 #define VSPLUS          0x3     /* ${var+text} */
670 #define VSQUESTION      0x4     /* ${var?message} */
671 #define VSASSIGN        0x5     /* ${var=text} */
672 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
673 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
674 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
675 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
676 #define VSLENGTH        0xa     /* ${#var} */
677 #if BASH_SUBSTR
678 #define VSSUBSTR        0xc     /* ${var:position:length} */
679 #endif
680 #if BASH_PATTERN_SUBST
681 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
682 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
683 #endif
684
685 static const char dolatstr[] ALIGN1 = {
686         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
687 };
688 #define DOLATSTRLEN 6
689
690 #define NCMD      0
691 #define NPIPE     1
692 #define NREDIR    2
693 #define NBACKGND  3
694 #define NSUBSHELL 4
695 #define NAND      5
696 #define NOR       6
697 #define NSEMI     7
698 #define NIF       8
699 #define NWHILE    9
700 #define NUNTIL   10
701 #define NFOR     11
702 #define NCASE    12
703 #define NCLIST   13
704 #define NDEFUN   14
705 #define NARG     15
706 #define NTO      16
707 #if BASH_REDIR_OUTPUT
708 #define NTO2     17
709 #endif
710 #define NCLOBBER 18
711 #define NFROM    19
712 #define NFROMTO  20
713 #define NAPPEND  21
714 #define NTOFD    22
715 #define NFROMFD  23
716 #define NHERE    24
717 #define NXHERE   25
718 #define NNOT     26
719 #define N_NUMBER 27
720
721 union node;
722
723 struct ncmd {
724         smallint type; /* Nxxxx */
725         union node *assign;
726         union node *args;
727         union node *redirect;
728 };
729
730 struct npipe {
731         smallint type;
732         smallint pipe_backgnd;
733         struct nodelist *cmdlist;
734 };
735
736 struct nredir {
737         smallint type;
738         union node *n;
739         union node *redirect;
740 };
741
742 struct nbinary {
743         smallint type;
744         union node *ch1;
745         union node *ch2;
746 };
747
748 struct nif {
749         smallint type;
750         union node *test;
751         union node *ifpart;
752         union node *elsepart;
753 };
754
755 struct nfor {
756         smallint type;
757         union node *args;
758         union node *body;
759         char *var;
760 };
761
762 struct ncase {
763         smallint type;
764         union node *expr;
765         union node *cases;
766 };
767
768 struct nclist {
769         smallint type;
770         union node *next;
771         union node *pattern;
772         union node *body;
773 };
774
775 struct narg {
776         smallint type;
777         union node *next;
778         char *text;
779         struct nodelist *backquote;
780 };
781
782 /* nfile and ndup layout must match!
783  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
784  * that it is actually NTO2 (>&file), and change its type.
785  */
786 struct nfile {
787         smallint type;
788         union node *next;
789         int fd;
790         int _unused_dupfd;
791         union node *fname;
792         char *expfname;
793 };
794
795 struct ndup {
796         smallint type;
797         union node *next;
798         int fd;
799         int dupfd;
800         union node *vname;
801         char *_unused_expfname;
802 };
803
804 struct nhere {
805         smallint type;
806         union node *next;
807         int fd;
808         union node *doc;
809 };
810
811 struct nnot {
812         smallint type;
813         union node *com;
814 };
815
816 union node {
817         smallint type;
818         struct ncmd ncmd;
819         struct npipe npipe;
820         struct nredir nredir;
821         struct nbinary nbinary;
822         struct nif nif;
823         struct nfor nfor;
824         struct ncase ncase;
825         struct nclist nclist;
826         struct narg narg;
827         struct nfile nfile;
828         struct ndup ndup;
829         struct nhere nhere;
830         struct nnot nnot;
831 };
832
833 /*
834  * NODE_EOF is returned by parsecmd when it encounters an end of file.
835  * It must be distinct from NULL.
836  */
837 #define NODE_EOF ((union node *) -1L)
838
839 struct nodelist {
840         struct nodelist *next;
841         union node *n;
842 };
843
844 struct funcnode {
845         int count;
846         union node n;
847 };
848
849 /*
850  * Free a parse tree.
851  */
852 static void
853 freefunc(struct funcnode *f)
854 {
855         if (f && --f->count < 0)
856                 free(f);
857 }
858
859
860 /* ============ Debugging output */
861
862 #if DEBUG
863
864 static FILE *tracefile;
865
866 static void
867 trace_printf(const char *fmt, ...)
868 {
869         va_list va;
870
871         if (debug != 1)
872                 return;
873         if (DEBUG_TIME)
874                 fprintf(tracefile, "%u ", (int) time(NULL));
875         if (DEBUG_PID)
876                 fprintf(tracefile, "[%u] ", (int) getpid());
877         if (DEBUG_SIG)
878                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
879         va_start(va, fmt);
880         vfprintf(tracefile, fmt, va);
881         va_end(va);
882 }
883
884 static void
885 trace_vprintf(const char *fmt, va_list va)
886 {
887         if (debug != 1)
888                 return;
889         vfprintf(tracefile, fmt, va);
890         fprintf(tracefile, "\n");
891 }
892
893 static void
894 trace_puts(const char *s)
895 {
896         if (debug != 1)
897                 return;
898         fputs(s, tracefile);
899 }
900
901 static void
902 trace_puts_quoted(char *s)
903 {
904         char *p;
905         char c;
906
907         if (debug != 1)
908                 return;
909         putc('"', tracefile);
910         for (p = s; *p; p++) {
911                 switch ((unsigned char)*p) {
912                 case '\n': c = 'n'; goto backslash;
913                 case '\t': c = 't'; goto backslash;
914                 case '\r': c = 'r'; goto backslash;
915                 case '\"': c = '\"'; goto backslash;
916                 case '\\': c = '\\'; goto backslash;
917                 case CTLESC: c = 'e'; goto backslash;
918                 case CTLVAR: c = 'v'; goto backslash;
919                 case CTLBACKQ: c = 'q'; goto backslash;
920  backslash:
921                         putc('\\', tracefile);
922                         putc(c, tracefile);
923                         break;
924                 default:
925                         if (*p >= ' ' && *p <= '~')
926                                 putc(*p, tracefile);
927                         else {
928                                 putc('\\', tracefile);
929                                 putc((*p >> 6) & 03, tracefile);
930                                 putc((*p >> 3) & 07, tracefile);
931                                 putc(*p & 07, tracefile);
932                         }
933                         break;
934                 }
935         }
936         putc('"', tracefile);
937 }
938
939 static void
940 trace_puts_args(char **ap)
941 {
942         if (debug != 1)
943                 return;
944         if (!*ap)
945                 return;
946         while (1) {
947                 trace_puts_quoted(*ap);
948                 if (!*++ap) {
949                         putc('\n', tracefile);
950                         break;
951                 }
952                 putc(' ', tracefile);
953         }
954 }
955
956 static void
957 opentrace(void)
958 {
959         char s[100];
960 #ifdef O_APPEND
961         int flags;
962 #endif
963
964         if (debug != 1) {
965                 if (tracefile)
966                         fflush(tracefile);
967                 /* leave open because libedit might be using it */
968                 return;
969         }
970         strcpy(s, "./trace");
971         if (tracefile) {
972                 if (!freopen(s, "a", tracefile)) {
973                         fprintf(stderr, "Can't re-open %s\n", s);
974                         debug = 0;
975                         return;
976                 }
977         } else {
978                 tracefile = fopen(s, "a");
979                 if (tracefile == NULL) {
980                         fprintf(stderr, "Can't open %s\n", s);
981                         debug = 0;
982                         return;
983                 }
984         }
985 #ifdef O_APPEND
986         flags = fcntl(fileno(tracefile), F_GETFL);
987         if (flags >= 0)
988                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
989 #endif
990         setlinebuf(tracefile);
991         fputs("\nTracing started.\n", tracefile);
992 }
993
994 static void
995 indent(int amount, char *pfx, FILE *fp)
996 {
997         int i;
998
999         for (i = 0; i < amount; i++) {
1000                 if (pfx && i == amount - 1)
1001                         fputs(pfx, fp);
1002                 putc('\t', fp);
1003         }
1004 }
1005
1006 /* little circular references here... */
1007 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1008
1009 static void
1010 sharg(union node *arg, FILE *fp)
1011 {
1012         char *p;
1013         struct nodelist *bqlist;
1014         unsigned char subtype;
1015
1016         if (arg->type != NARG) {
1017                 out1fmt("<node type %d>\n", arg->type);
1018                 abort();
1019         }
1020         bqlist = arg->narg.backquote;
1021         for (p = arg->narg.text; *p; p++) {
1022                 switch ((unsigned char)*p) {
1023                 case CTLESC:
1024                         p++;
1025                         putc(*p, fp);
1026                         break;
1027                 case CTLVAR:
1028                         putc('$', fp);
1029                         putc('{', fp);
1030                         subtype = *++p;
1031                         if (subtype == VSLENGTH)
1032                                 putc('#', fp);
1033
1034                         while (*p != '=') {
1035                                 putc(*p, fp);
1036                                 p++;
1037                         }
1038
1039                         if (subtype & VSNUL)
1040                                 putc(':', fp);
1041
1042                         switch (subtype & VSTYPE) {
1043                         case VSNORMAL:
1044                                 putc('}', fp);
1045                                 break;
1046                         case VSMINUS:
1047                                 putc('-', fp);
1048                                 break;
1049                         case VSPLUS:
1050                                 putc('+', fp);
1051                                 break;
1052                         case VSQUESTION:
1053                                 putc('?', fp);
1054                                 break;
1055                         case VSASSIGN:
1056                                 putc('=', fp);
1057                                 break;
1058                         case VSTRIMLEFT:
1059                                 putc('#', fp);
1060                                 break;
1061                         case VSTRIMLEFTMAX:
1062                                 putc('#', fp);
1063                                 putc('#', fp);
1064                                 break;
1065                         case VSTRIMRIGHT:
1066                                 putc('%', fp);
1067                                 break;
1068                         case VSTRIMRIGHTMAX:
1069                                 putc('%', fp);
1070                                 putc('%', fp);
1071                                 break;
1072                         case VSLENGTH:
1073                                 break;
1074                         default:
1075                                 out1fmt("<subtype %d>", subtype);
1076                         }
1077                         break;
1078                 case CTLENDVAR:
1079                         putc('}', fp);
1080                         break;
1081                 case CTLBACKQ:
1082                         putc('$', fp);
1083                         putc('(', fp);
1084                         shtree(bqlist->n, -1, NULL, fp);
1085                         putc(')', fp);
1086                         break;
1087                 default:
1088                         putc(*p, fp);
1089                         break;
1090                 }
1091         }
1092 }
1093
1094 static void
1095 shcmd(union node *cmd, FILE *fp)
1096 {
1097         union node *np;
1098         int first;
1099         const char *s;
1100         int dftfd;
1101
1102         first = 1;
1103         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1104                 if (!first)
1105                         putc(' ', fp);
1106                 sharg(np, fp);
1107                 first = 0;
1108         }
1109         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1110                 if (!first)
1111                         putc(' ', fp);
1112                 dftfd = 0;
1113                 switch (np->nfile.type) {
1114                 case NTO:      s = ">>"+1; dftfd = 1; break;
1115                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1116                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1117 #if BASH_REDIR_OUTPUT
1118                 case NTO2:
1119 #endif
1120                 case NTOFD:    s = ">&"; dftfd = 1; break;
1121                 case NFROM:    s = "<"; break;
1122                 case NFROMFD:  s = "<&"; break;
1123                 case NFROMTO:  s = "<>"; break;
1124                 default:       s = "*error*"; break;
1125                 }
1126                 if (np->nfile.fd != dftfd)
1127                         fprintf(fp, "%d", np->nfile.fd);
1128                 fputs(s, fp);
1129                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1130                         fprintf(fp, "%d", np->ndup.dupfd);
1131                 } else {
1132                         sharg(np->nfile.fname, fp);
1133                 }
1134                 first = 0;
1135         }
1136 }
1137
1138 static void
1139 shtree(union node *n, int ind, char *pfx, FILE *fp)
1140 {
1141         struct nodelist *lp;
1142         const char *s;
1143
1144         if (n == NULL)
1145                 return;
1146
1147         indent(ind, pfx, fp);
1148
1149         if (n == NODE_EOF) {
1150                 fputs("<EOF>", fp);
1151                 return;
1152         }
1153
1154         switch (n->type) {
1155         case NSEMI:
1156                 s = "; ";
1157                 goto binop;
1158         case NAND:
1159                 s = " && ";
1160                 goto binop;
1161         case NOR:
1162                 s = " || ";
1163  binop:
1164                 shtree(n->nbinary.ch1, ind, NULL, fp);
1165                 /* if (ind < 0) */
1166                         fputs(s, fp);
1167                 shtree(n->nbinary.ch2, ind, NULL, fp);
1168                 break;
1169         case NCMD:
1170                 shcmd(n, fp);
1171                 if (ind >= 0)
1172                         putc('\n', fp);
1173                 break;
1174         case NPIPE:
1175                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1176                         shtree(lp->n, 0, NULL, fp);
1177                         if (lp->next)
1178                                 fputs(" | ", fp);
1179                 }
1180                 if (n->npipe.pipe_backgnd)
1181                         fputs(" &", fp);
1182                 if (ind >= 0)
1183                         putc('\n', fp);
1184                 break;
1185         default:
1186                 fprintf(fp, "<node type %d>", n->type);
1187                 if (ind >= 0)
1188                         putc('\n', fp);
1189                 break;
1190         }
1191 }
1192
1193 static void
1194 showtree(union node *n)
1195 {
1196         trace_puts("showtree called\n");
1197         shtree(n, 1, NULL, stderr);
1198 }
1199
1200 #endif /* DEBUG */
1201
1202
1203 /* ============ Parser data */
1204
1205 /*
1206  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1207  */
1208 struct strlist {
1209         struct strlist *next;
1210         char *text;
1211 };
1212
1213 struct alias;
1214
1215 struct strpush {
1216         struct strpush *prev;   /* preceding string on stack */
1217         char *prev_string;
1218         int prev_left_in_line;
1219 #if ENABLE_ASH_ALIAS
1220         struct alias *ap;       /* if push was associated with an alias */
1221 #endif
1222         char *string;           /* remember the string since it may change */
1223
1224         /* Remember last two characters for pungetc. */
1225         int lastc[2];
1226
1227         /* Number of outstanding calls to pungetc. */
1228         int unget;
1229 };
1230
1231 struct parsefile {
1232         struct parsefile *prev; /* preceding file on stack */
1233         int linno;              /* current line */
1234         int pf_fd;              /* file descriptor (or -1 if string) */
1235         int left_in_line;       /* number of chars left in this line */
1236         int left_in_buffer;     /* number of chars left in this buffer past the line */
1237         char *next_to_pgetc;    /* next char in buffer */
1238         char *buf;              /* input buffer */
1239         struct strpush *strpush; /* for pushing strings at this level */
1240         struct strpush basestrpush; /* so pushing one is fast */
1241
1242         /* Remember last two characters for pungetc. */
1243         int lastc[2];
1244
1245         /* Number of outstanding calls to pungetc. */
1246         int unget;
1247 };
1248
1249 static struct parsefile basepf;        /* top level input file */
1250 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1251 static int startlinno;                 /* line # where last token started */
1252 static char *commandname;              /* currently executing command */
1253
1254
1255 /* ============ Message printing */
1256
1257 static void
1258 ash_vmsg(const char *msg, va_list ap)
1259 {
1260         fprintf(stderr, "%s: ", arg0);
1261         if (commandname) {
1262                 if (strcmp(arg0, commandname))
1263                         fprintf(stderr, "%s: ", commandname);
1264                 if (!iflag || g_parsefile->pf_fd > 0)
1265                         fprintf(stderr, "line %d: ", startlinno);
1266         }
1267         vfprintf(stderr, msg, ap);
1268         newline_and_flush(stderr);
1269 }
1270
1271 /*
1272  * Exverror is called to raise the error exception.  If the second argument
1273  * is not NULL then error prints an error message using printf style
1274  * formatting.  It then raises the error exception.
1275  */
1276 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1277 static void
1278 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1279 {
1280 #if DEBUG
1281         if (msg) {
1282                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1283                 TRACEV((msg, ap));
1284         } else
1285                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1286         if (msg)
1287 #endif
1288                 ash_vmsg(msg, ap);
1289
1290         flush_stdout_stderr();
1291         raise_exception(cond);
1292         /* NOTREACHED */
1293 }
1294
1295 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1296 static void
1297 ash_msg_and_raise_error(const char *msg, ...)
1298 {
1299         va_list ap;
1300
1301         exitstatus = 2;
1302
1303         va_start(ap, msg);
1304         ash_vmsg_and_raise(EXERROR, msg, ap);
1305         /* NOTREACHED */
1306         va_end(ap);
1307 }
1308
1309 /*
1310  * Use '%m' to append error string on platforms that support it, '%s' and
1311  * strerror() on those that don't.
1312  *
1313  * 'fmt' must be a string literal.
1314  */
1315 #ifdef HAVE_PRINTF_PERCENTM
1316 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %m", ##__VA_ARGS__)
1317 #else
1318 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %s", ##__VA_ARGS__, strerror(errno))
1319 #endif
1320
1321 static void raise_error_syntax(const char *) NORETURN;
1322 static void
1323 raise_error_syntax(const char *msg)
1324 {
1325         ash_msg_and_raise_error("syntax error: %s", msg);
1326         /* NOTREACHED */
1327 }
1328
1329 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1330 static void
1331 ash_msg_and_raise(int cond, const char *msg, ...)
1332 {
1333         va_list ap;
1334
1335         va_start(ap, msg);
1336         ash_vmsg_and_raise(cond, msg, ap);
1337         /* NOTREACHED */
1338         va_end(ap);
1339 }
1340
1341 /*
1342  * error/warning routines for external builtins
1343  */
1344 static void
1345 ash_msg(const char *fmt, ...)
1346 {
1347         va_list ap;
1348
1349         va_start(ap, fmt);
1350         ash_vmsg(fmt, ap);
1351         va_end(ap);
1352 }
1353
1354 /*
1355  * Return a string describing an error.  The returned string may be a
1356  * pointer to a static buffer that will be overwritten on the next call.
1357  * Action describes the operation that got the error.
1358  */
1359 static const char *
1360 errmsg(int e, const char *em)
1361 {
1362         if (e == ENOENT || e == ENOTDIR) {
1363                 return em;
1364         }
1365         return strerror(e);
1366 }
1367
1368
1369 /* ============ Memory allocation */
1370
1371 #if 0
1372 /* I consider these wrappers nearly useless:
1373  * ok, they return you to nearest exception handler, but
1374  * how much memory do you leak in the process, making
1375  * memory starvation worse?
1376  */
1377 static void *
1378 ckrealloc(void * p, size_t nbytes)
1379 {
1380         p = realloc(p, nbytes);
1381         if (!p)
1382                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1383         return p;
1384 }
1385
1386 static void *
1387 ckmalloc(size_t nbytes)
1388 {
1389         return ckrealloc(NULL, nbytes);
1390 }
1391
1392 static void *
1393 ckzalloc(size_t nbytes)
1394 {
1395         return memset(ckmalloc(nbytes), 0, nbytes);
1396 }
1397
1398 static char *
1399 ckstrdup(const char *s)
1400 {
1401         char *p = strdup(s);
1402         if (!p)
1403                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1404         return p;
1405 }
1406 #else
1407 /* Using bbox equivalents. They exit if out of memory */
1408 # define ckrealloc xrealloc
1409 # define ckmalloc  xmalloc
1410 # define ckzalloc  xzalloc
1411 # define ckstrdup  xstrdup
1412 #endif
1413
1414 /*
1415  * It appears that grabstackstr() will barf with such alignments
1416  * because stalloc() will return a string allocated in a new stackblock.
1417  */
1418 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1419 enum {
1420         /* Most machines require the value returned from malloc to be aligned
1421          * in some way.  The following macro will get this right
1422          * on many machines.  */
1423         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1424         /* Minimum size of a block */
1425         MINSIZE = SHELL_ALIGN(504),
1426 };
1427
1428 struct stack_block {
1429         struct stack_block *prev;
1430         char space[MINSIZE];
1431 };
1432
1433 struct stackmark {
1434         struct stack_block *stackp;
1435         char *stacknxt;
1436         size_t stacknleft;
1437 };
1438
1439
1440 struct globals_memstack {
1441         struct stack_block *g_stackp; // = &stackbase;
1442         char *g_stacknxt; // = stackbase.space;
1443         char *sstrend; // = stackbase.space + MINSIZE;
1444         size_t g_stacknleft; // = MINSIZE;
1445         struct stack_block stackbase;
1446 };
1447 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1448 #define G_memstack (*ash_ptr_to_globals_memstack)
1449 #define g_stackp     (G_memstack.g_stackp    )
1450 #define g_stacknxt   (G_memstack.g_stacknxt  )
1451 #define sstrend      (G_memstack.sstrend     )
1452 #define g_stacknleft (G_memstack.g_stacknleft)
1453 #define stackbase    (G_memstack.stackbase   )
1454 #define INIT_G_memstack() do { \
1455         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1456         barrier(); \
1457         g_stackp = &stackbase; \
1458         g_stacknxt = stackbase.space; \
1459         g_stacknleft = MINSIZE; \
1460         sstrend = stackbase.space + MINSIZE; \
1461 } while (0)
1462
1463
1464 #define stackblock()     ((void *)g_stacknxt)
1465 #define stackblocksize() g_stacknleft
1466
1467 /*
1468  * Parse trees for commands are allocated in lifo order, so we use a stack
1469  * to make this more efficient, and also to avoid all sorts of exception
1470  * handling code to handle interrupts in the middle of a parse.
1471  *
1472  * The size 504 was chosen because the Ultrix malloc handles that size
1473  * well.
1474  */
1475 static void *
1476 stalloc(size_t nbytes)
1477 {
1478         char *p;
1479         size_t aligned;
1480
1481         aligned = SHELL_ALIGN(nbytes);
1482         if (aligned > g_stacknleft) {
1483                 size_t len;
1484                 size_t blocksize;
1485                 struct stack_block *sp;
1486
1487                 blocksize = aligned;
1488                 if (blocksize < MINSIZE)
1489                         blocksize = MINSIZE;
1490                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1491                 if (len < blocksize)
1492                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1493                 INT_OFF;
1494                 sp = ckmalloc(len);
1495                 sp->prev = g_stackp;
1496                 g_stacknxt = sp->space;
1497                 g_stacknleft = blocksize;
1498                 sstrend = g_stacknxt + blocksize;
1499                 g_stackp = sp;
1500                 INT_ON;
1501         }
1502         p = g_stacknxt;
1503         g_stacknxt += aligned;
1504         g_stacknleft -= aligned;
1505         return p;
1506 }
1507
1508 static void *
1509 stzalloc(size_t nbytes)
1510 {
1511         return memset(stalloc(nbytes), 0, nbytes);
1512 }
1513
1514 static void
1515 stunalloc(void *p)
1516 {
1517 #if DEBUG
1518         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1519                 write(STDERR_FILENO, "stunalloc\n", 10);
1520                 abort();
1521         }
1522 #endif
1523         g_stacknleft += g_stacknxt - (char *)p;
1524         g_stacknxt = p;
1525 }
1526
1527 /*
1528  * Like strdup but works with the ash stack.
1529  */
1530 static char *
1531 sstrdup(const char *p)
1532 {
1533         size_t len = strlen(p) + 1;
1534         return memcpy(stalloc(len), p, len);
1535 }
1536
1537 static inline void
1538 grabstackblock(size_t len)
1539 {
1540         stalloc(len);
1541 }
1542
1543 static void
1544 pushstackmark(struct stackmark *mark, size_t len)
1545 {
1546         mark->stackp = g_stackp;
1547         mark->stacknxt = g_stacknxt;
1548         mark->stacknleft = g_stacknleft;
1549         grabstackblock(len);
1550 }
1551
1552 static void
1553 setstackmark(struct stackmark *mark)
1554 {
1555         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1556 }
1557
1558 static void
1559 popstackmark(struct stackmark *mark)
1560 {
1561         struct stack_block *sp;
1562
1563         if (!mark->stackp)
1564                 return;
1565
1566         INT_OFF;
1567         while (g_stackp != mark->stackp) {
1568                 sp = g_stackp;
1569                 g_stackp = sp->prev;
1570                 free(sp);
1571         }
1572         g_stacknxt = mark->stacknxt;
1573         g_stacknleft = mark->stacknleft;
1574         sstrend = mark->stacknxt + mark->stacknleft;
1575         INT_ON;
1576 }
1577
1578 /*
1579  * When the parser reads in a string, it wants to stick the string on the
1580  * stack and only adjust the stack pointer when it knows how big the
1581  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1582  * of space on top of the stack and stackblocklen returns the length of
1583  * this block.  Growstackblock will grow this space by at least one byte,
1584  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1585  * part of the block that has been used.
1586  */
1587 static void
1588 growstackblock(void)
1589 {
1590         size_t newlen;
1591
1592         newlen = g_stacknleft * 2;
1593         if (newlen < g_stacknleft)
1594                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1595         if (newlen < 128)
1596                 newlen += 128;
1597
1598         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1599                 struct stack_block *sp;
1600                 struct stack_block *prevstackp;
1601                 size_t grosslen;
1602
1603                 INT_OFF;
1604                 sp = g_stackp;
1605                 prevstackp = sp->prev;
1606                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1607                 sp = ckrealloc(sp, grosslen);
1608                 sp->prev = prevstackp;
1609                 g_stackp = sp;
1610                 g_stacknxt = sp->space;
1611                 g_stacknleft = newlen;
1612                 sstrend = sp->space + newlen;
1613                 INT_ON;
1614         } else {
1615                 char *oldspace = g_stacknxt;
1616                 size_t oldlen = g_stacknleft;
1617                 char *p = stalloc(newlen);
1618
1619                 /* free the space we just allocated */
1620                 g_stacknxt = memcpy(p, oldspace, oldlen);
1621                 g_stacknleft += newlen;
1622         }
1623 }
1624
1625 /*
1626  * The following routines are somewhat easier to use than the above.
1627  * The user declares a variable of type STACKSTR, which may be declared
1628  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1629  * the user uses the macro STPUTC to add characters to the string.  In
1630  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1631  * grown as necessary.  When the user is done, she can just leave the
1632  * string there and refer to it using stackblock().  Or she can allocate
1633  * the space for it using grabstackstr().  If it is necessary to allow
1634  * someone else to use the stack temporarily and then continue to grow
1635  * the string, the user should use grabstack to allocate the space, and
1636  * then call ungrabstr(p) to return to the previous mode of operation.
1637  *
1638  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1639  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1640  * is space for at least one character.
1641  */
1642 static void *
1643 growstackstr(void)
1644 {
1645         size_t len = stackblocksize();
1646         growstackblock();
1647         return (char *)stackblock() + len;
1648 }
1649
1650 /*
1651  * Called from CHECKSTRSPACE.
1652  */
1653 static char *
1654 makestrspace(size_t newlen, char *p)
1655 {
1656         size_t len = p - g_stacknxt;
1657         size_t size;
1658
1659         for (;;) {
1660                 size_t nleft;
1661
1662                 size = stackblocksize();
1663                 nleft = size - len;
1664                 if (nleft >= newlen)
1665                         break;
1666                 growstackblock();
1667         }
1668         return (char *)stackblock() + len;
1669 }
1670
1671 static char *
1672 stack_nputstr(const char *s, size_t n, char *p)
1673 {
1674         p = makestrspace(n, p);
1675         p = (char *)mempcpy(p, s, n);
1676         return p;
1677 }
1678
1679 static char *
1680 stack_putstr(const char *s, char *p)
1681 {
1682         return stack_nputstr(s, strlen(s), p);
1683 }
1684
1685 static char *
1686 _STPUTC(int c, char *p)
1687 {
1688         if (p == sstrend)
1689                 p = growstackstr();
1690         *p++ = c;
1691         return p;
1692 }
1693
1694 #define STARTSTACKSTR(p)        ((p) = stackblock())
1695 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1696 #define CHECKSTRSPACE(n, p) do { \
1697         char *q = (p); \
1698         size_t l = (n); \
1699         size_t m = sstrend - q; \
1700         if (l > m) \
1701                 (p) = makestrspace(l, q); \
1702 } while (0)
1703 #define USTPUTC(c, p)           (*(p)++ = (c))
1704 #define STACKSTRNUL(p) do { \
1705         if ((p) == sstrend) \
1706                 (p) = growstackstr(); \
1707         *(p) = '\0'; \
1708 } while (0)
1709 #define STUNPUTC(p)             (--(p))
1710 #define STTOPC(p)               ((p)[-1])
1711 #define STADJUST(amount, p)     ((p) += (amount))
1712
1713 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1714 #define ungrabstackstr(s, p)    stunalloc(s)
1715 #define stackstrend()           ((void *)sstrend)
1716
1717
1718 /* ============ String helpers */
1719
1720 /*
1721  * prefix -- see if pfx is a prefix of string.
1722  */
1723 static char *
1724 prefix(const char *string, const char *pfx)
1725 {
1726         while (*pfx) {
1727                 if (*pfx++ != *string++)
1728                         return NULL;
1729         }
1730         return (char *) string;
1731 }
1732
1733 /*
1734  * Check for a valid number.  This should be elsewhere.
1735  */
1736 static int
1737 is_number(const char *p)
1738 {
1739         do {
1740                 if (!isdigit(*p))
1741                         return 0;
1742         } while (*++p != '\0');
1743         return 1;
1744 }
1745
1746 /*
1747  * Convert a string of digits to an integer, printing an error message on
1748  * failure.
1749  */
1750 static int
1751 number(const char *s)
1752 {
1753         if (!is_number(s))
1754                 ash_msg_and_raise_error(msg_illnum, s);
1755         return atoi(s);
1756 }
1757
1758 /*
1759  * Produce a single quoted string suitable as input to the shell.
1760  * The return string is allocated on the stack.
1761  */
1762 static char *
1763 single_quote(const char *s)
1764 {
1765         char *p;
1766
1767         STARTSTACKSTR(p);
1768
1769         do {
1770                 char *q;
1771                 size_t len;
1772
1773                 len = strchrnul(s, '\'') - s;
1774
1775                 q = p = makestrspace(len + 3, p);
1776
1777                 *q++ = '\'';
1778                 q = (char *)mempcpy(q, s, len);
1779                 *q++ = '\'';
1780                 s += len;
1781
1782                 STADJUST(q - p, p);
1783
1784                 if (*s != '\'')
1785                         break;
1786                 len = 0;
1787                 do len++; while (*++s == '\'');
1788
1789                 q = p = makestrspace(len + 3, p);
1790
1791                 *q++ = '"';
1792                 q = (char *)mempcpy(q, s - len, len);
1793                 *q++ = '"';
1794
1795                 STADJUST(q - p, p);
1796         } while (*s);
1797
1798         USTPUTC('\0', p);
1799
1800         return stackblock();
1801 }
1802
1803 /*
1804  * Produce a possibly single quoted string suitable as input to the shell.
1805  * If quoting was done, the return string is allocated on the stack,
1806  * otherwise a pointer to the original string is returned.
1807  */
1808 static const char *
1809 maybe_single_quote(const char *s)
1810 {
1811         const char *p = s;
1812
1813         while (*p) {
1814                 /* Assuming ACSII */
1815                 /* quote ctrl_chars space !"#$%&'()* */
1816                 if (*p < '+')
1817                         goto need_quoting;
1818                 /* quote ;<=>? */
1819                 if (*p >= ';' && *p <= '?')
1820                         goto need_quoting;
1821                 /* quote `[\ */
1822                 if (*p == '`')
1823                         goto need_quoting;
1824                 if (*p == '[')
1825                         goto need_quoting;
1826                 if (*p == '\\')
1827                         goto need_quoting;
1828                 /* quote {|}~ DEL and high bytes */
1829                 if (*p > 'z')
1830                         goto need_quoting;
1831                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1832                 /* TODO: maybe avoid quoting % */
1833                 p++;
1834         }
1835         return s;
1836
1837  need_quoting:
1838         return single_quote(s);
1839 }
1840
1841
1842 /* ============ nextopt */
1843
1844 static char **argptr;                  /* argument list for builtin commands */
1845 static char *optionarg;                /* set by nextopt (like getopt) */
1846 static char *optptr;                   /* used by nextopt */
1847
1848 /*
1849  * XXX - should get rid of. Have all builtins use getopt(3).
1850  * The library getopt must have the BSD extension static variable
1851  * "optreset", otherwise it can't be used within the shell safely.
1852  *
1853  * Standard option processing (a la getopt) for builtin routines.
1854  * The only argument that is passed to nextopt is the option string;
1855  * the other arguments are unnecessary. It returns the character,
1856  * or '\0' on end of input.
1857  */
1858 static int
1859 nextopt(const char *optstring)
1860 {
1861         char *p;
1862         const char *q;
1863         char c;
1864
1865         p = optptr;
1866         if (p == NULL || *p == '\0') {
1867                 /* We ate entire "-param", take next one */
1868                 p = *argptr;
1869                 if (p == NULL)
1870                         return '\0';
1871                 if (*p != '-')
1872                         return '\0';
1873                 if (*++p == '\0') /* just "-" ? */
1874                         return '\0';
1875                 argptr++;
1876                 if (LONE_DASH(p)) /* "--" ? */
1877                         return '\0';
1878                 /* p => next "-param" */
1879         }
1880         /* p => some option char in the middle of a "-param" */
1881         c = *p++;
1882         for (q = optstring; *q != c;) {
1883                 if (*q == '\0')
1884                         ash_msg_and_raise_error("illegal option -%c", c);
1885                 if (*++q == ':')
1886                         q++;
1887         }
1888         if (*++q == ':') {
1889                 if (*p == '\0') {
1890                         p = *argptr++;
1891                         if (p == NULL)
1892                                 ash_msg_and_raise_error("no arg for -%c option", c);
1893                 }
1894                 optionarg = p;
1895                 p = NULL;
1896         }
1897         optptr = p;
1898         return c;
1899 }
1900
1901
1902 /* ============ Shell variables */
1903
1904 /*
1905  * The parsefile structure pointed to by the global variable parsefile
1906  * contains information about the current file being read.
1907  */
1908 struct shparam {
1909         int nparam;             /* # of positional parameters (without $0) */
1910 #if ENABLE_ASH_GETOPTS
1911         int optind;             /* next parameter to be processed by getopts */
1912         int optoff;             /* used by getopts */
1913 #endif
1914         unsigned char malloced; /* if parameter list dynamically allocated */
1915         char **p;               /* parameter list */
1916 };
1917
1918 /*
1919  * Free the list of positional parameters.
1920  */
1921 static void
1922 freeparam(volatile struct shparam *param)
1923 {
1924         if (param->malloced) {
1925                 char **ap, **ap1;
1926                 ap = ap1 = param->p;
1927                 while (*ap)
1928                         free(*ap++);
1929                 free(ap1);
1930         }
1931 }
1932
1933 #if ENABLE_ASH_GETOPTS
1934 static void FAST_FUNC getoptsreset(const char *value);
1935 #endif
1936
1937 struct var {
1938         struct var *next;               /* next entry in hash list */
1939         int flags;                      /* flags are defined above */
1940         const char *var_text;           /* name=value */
1941         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1942                                         /* the variable gets set/unset */
1943 };
1944
1945 struct localvar {
1946         struct localvar *next;          /* next local variable in list */
1947         struct var *vp;                 /* the variable that was made local */
1948         int flags;                      /* saved flags */
1949         const char *text;               /* saved text */
1950 };
1951
1952 /* flags */
1953 #define VEXPORT         0x01    /* variable is exported */
1954 #define VREADONLY       0x02    /* variable cannot be modified */
1955 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1956 #define VTEXTFIXED      0x08    /* text is statically allocated */
1957 #define VSTACK          0x10    /* text is allocated on the stack */
1958 #define VUNSET          0x20    /* the variable is not set */
1959 #define VNOFUNC         0x40    /* don't call the callback function */
1960 #define VNOSET          0x80    /* do not set variable - just readonly test */
1961 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1962 #if ENABLE_ASH_RANDOM_SUPPORT
1963 # define VDYNAMIC       0x200   /* dynamic variable */
1964 #else
1965 # define VDYNAMIC       0
1966 #endif
1967
1968
1969 /* Need to be before varinit_data[] */
1970 #if ENABLE_LOCALE_SUPPORT
1971 static void FAST_FUNC
1972 change_lc_all(const char *value)
1973 {
1974         if (value && *value != '\0')
1975                 setlocale(LC_ALL, value);
1976 }
1977 static void FAST_FUNC
1978 change_lc_ctype(const char *value)
1979 {
1980         if (value && *value != '\0')
1981                 setlocale(LC_CTYPE, value);
1982 }
1983 #endif
1984 #if ENABLE_ASH_MAIL
1985 static void chkmail(void);
1986 static void changemail(const char *var_value) FAST_FUNC;
1987 #else
1988 # define chkmail()  ((void)0)
1989 #endif
1990 static void changepath(const char *) FAST_FUNC;
1991 #if ENABLE_ASH_RANDOM_SUPPORT
1992 static void change_random(const char *) FAST_FUNC;
1993 #endif
1994
1995 static const struct {
1996         int flags;
1997         const char *var_text;
1998         void (*var_func)(const char *) FAST_FUNC;
1999 } varinit_data[] = {
2000         /*
2001          * Note: VEXPORT would not work correctly here for NOFORK applets:
2002          * some environment strings may be constant.
2003          */
2004         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2005 #if ENABLE_ASH_MAIL
2006         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2007         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2008 #endif
2009         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2010         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2011         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2012         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2013 #if ENABLE_ASH_GETOPTS
2014         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2015 #endif
2016 #if ENABLE_ASH_RANDOM_SUPPORT
2017         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2018 #endif
2019 #if ENABLE_LOCALE_SUPPORT
2020         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2021         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2022 #endif
2023 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2024         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2025 #endif
2026 };
2027
2028 struct redirtab;
2029
2030 struct globals_var {
2031         struct shparam shellparam;      /* $@ current positional parameters */
2032         struct redirtab *redirlist;
2033         int preverrout_fd;   /* save fd2 before print debug if xflag is set. */
2034         struct var *vartab[VTABSIZE];
2035         struct var varinit[ARRAY_SIZE(varinit_data)];
2036 };
2037 extern struct globals_var *const ash_ptr_to_globals_var;
2038 #define G_var (*ash_ptr_to_globals_var)
2039 #define shellparam    (G_var.shellparam   )
2040 //#define redirlist     (G_var.redirlist    )
2041 #define preverrout_fd (G_var.preverrout_fd)
2042 #define vartab        (G_var.vartab       )
2043 #define varinit       (G_var.varinit      )
2044 #define INIT_G_var() do { \
2045         unsigned i; \
2046         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2047         barrier(); \
2048         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2049                 varinit[i].flags    = varinit_data[i].flags; \
2050                 varinit[i].var_text = varinit_data[i].var_text; \
2051                 varinit[i].var_func = varinit_data[i].var_func; \
2052         } \
2053 } while (0)
2054
2055 #define vifs      varinit[0]
2056 #if ENABLE_ASH_MAIL
2057 # define vmail    (&vifs)[1]
2058 # define vmpath   (&vmail)[1]
2059 # define vpath    (&vmpath)[1]
2060 #else
2061 # define vpath    (&vifs)[1]
2062 #endif
2063 #define vps1      (&vpath)[1]
2064 #define vps2      (&vps1)[1]
2065 #define vps4      (&vps2)[1]
2066 #if ENABLE_ASH_GETOPTS
2067 # define voptind  (&vps4)[1]
2068 # if ENABLE_ASH_RANDOM_SUPPORT
2069 #  define vrandom (&voptind)[1]
2070 # endif
2071 #else
2072 # if ENABLE_ASH_RANDOM_SUPPORT
2073 #  define vrandom (&vps4)[1]
2074 # endif
2075 #endif
2076
2077 /*
2078  * The following macros access the values of the above variables.
2079  * They have to skip over the name.  They return the null string
2080  * for unset variables.
2081  */
2082 #define ifsval()        (vifs.var_text + 4)
2083 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2084 #if ENABLE_ASH_MAIL
2085 # define mailval()      (vmail.var_text + 5)
2086 # define mpathval()     (vmpath.var_text + 9)
2087 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2088 #endif
2089 #define pathval()       (vpath.var_text + 5)
2090 #define ps1val()        (vps1.var_text + 4)
2091 #define ps2val()        (vps2.var_text + 4)
2092 #define ps4val()        (vps4.var_text + 4)
2093 #if ENABLE_ASH_GETOPTS
2094 # define optindval()    (voptind.var_text + 7)
2095 #endif
2096
2097 #if ENABLE_ASH_GETOPTS
2098 static void FAST_FUNC
2099 getoptsreset(const char *value)
2100 {
2101         shellparam.optind = number(value) ?: 1;
2102         shellparam.optoff = -1;
2103 }
2104 #endif
2105
2106 /*
2107  * Compares two strings up to the first = or '\0'.  The first
2108  * string must be terminated by '='; the second may be terminated by
2109  * either '=' or '\0'.
2110  */
2111 static int
2112 varcmp(const char *p, const char *q)
2113 {
2114         int c, d;
2115
2116         while ((c = *p) == (d = *q)) {
2117                 if (c == '\0' || c == '=')
2118                         goto out;
2119                 p++;
2120                 q++;
2121         }
2122         if (c == '=')
2123                 c = '\0';
2124         if (d == '=')
2125                 d = '\0';
2126  out:
2127         return c - d;
2128 }
2129
2130 /*
2131  * Find the appropriate entry in the hash table from the name.
2132  */
2133 static struct var **
2134 hashvar(const char *p)
2135 {
2136         unsigned hashval;
2137
2138         hashval = ((unsigned char) *p) << 4;
2139         while (*p && *p != '=')
2140                 hashval += (unsigned char) *p++;
2141         return &vartab[hashval % VTABSIZE];
2142 }
2143
2144 static int
2145 vpcmp(const void *a, const void *b)
2146 {
2147         return varcmp(*(const char **)a, *(const char **)b);
2148 }
2149
2150 /*
2151  * This routine initializes the builtin variables.
2152  */
2153 static void
2154 initvar(void)
2155 {
2156         struct var *vp;
2157         struct var *end;
2158         struct var **vpp;
2159
2160         /*
2161          * PS1 depends on uid
2162          */
2163 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2164         vps1.var_text = "PS1=\\w \\$ ";
2165 #else
2166         if (!geteuid())
2167                 vps1.var_text = "PS1=# ";
2168 #endif
2169         vp = varinit;
2170         end = vp + ARRAY_SIZE(varinit);
2171         do {
2172                 vpp = hashvar(vp->var_text);
2173                 vp->next = *vpp;
2174                 *vpp = vp;
2175         } while (++vp < end);
2176 }
2177
2178 static struct var **
2179 findvar(struct var **vpp, const char *name)
2180 {
2181         for (; *vpp; vpp = &(*vpp)->next) {
2182                 if (varcmp((*vpp)->var_text, name) == 0) {
2183                         break;
2184                 }
2185         }
2186         return vpp;
2187 }
2188
2189 /*
2190  * Find the value of a variable.  Returns NULL if not set.
2191  */
2192 static const char* FAST_FUNC
2193 lookupvar(const char *name)
2194 {
2195         struct var *v;
2196
2197         v = *findvar(hashvar(name), name);
2198         if (v) {
2199 #if ENABLE_ASH_RANDOM_SUPPORT
2200         /*
2201          * Dynamic variables are implemented roughly the same way they are
2202          * in bash. Namely, they're "special" so long as they aren't unset.
2203          * As soon as they're unset, they're no longer dynamic, and dynamic
2204          * lookup will no longer happen at that point. -- PFM.
2205          */
2206                 if (v->flags & VDYNAMIC)
2207                         v->var_func(NULL);
2208 #endif
2209                 if (!(v->flags & VUNSET))
2210                         return var_end(v->var_text);
2211         }
2212         return NULL;
2213 }
2214
2215 #if ENABLE_UNICODE_SUPPORT
2216 static void
2217 reinit_unicode_for_ash(void)
2218 {
2219         /* Unicode support should be activated even if LANG is set
2220          * _during_ shell execution, not only if it was set when
2221          * shell was started. Therefore, re-check LANG every time:
2222          */
2223         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2224          || ENABLE_UNICODE_USING_LOCALE
2225         ) {
2226                 const char *s = lookupvar("LC_ALL");
2227                 if (!s) s = lookupvar("LC_CTYPE");
2228                 if (!s) s = lookupvar("LANG");
2229                 reinit_unicode(s);
2230         }
2231 }
2232 #else
2233 # define reinit_unicode_for_ash() ((void)0)
2234 #endif
2235
2236 /*
2237  * Search the environment of a builtin command.
2238  */
2239 static ALWAYS_INLINE const char *
2240 bltinlookup(const char *name)
2241 {
2242         return lookupvar(name);
2243 }
2244
2245 /*
2246  * Same as setvar except that the variable and value are passed in
2247  * the first argument as name=value.  Since the first argument will
2248  * be actually stored in the table, it should not be a string that
2249  * will go away.
2250  * Called with interrupts off.
2251  */
2252 static struct var *
2253 setvareq(char *s, int flags)
2254 {
2255         struct var *vp, **vpp;
2256
2257         vpp = hashvar(s);
2258         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2259         vpp = findvar(vpp, s);
2260         vp = *vpp;
2261         if (vp) {
2262                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2263                         const char *n;
2264
2265                         if (flags & VNOSAVE)
2266                                 free(s);
2267                         n = vp->var_text;
2268                         exitstatus = 1;
2269                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2270                 }
2271
2272                 if (flags & VNOSET)
2273                         goto out;
2274
2275                 if (vp->var_func && !(flags & VNOFUNC))
2276                         vp->var_func(var_end(s));
2277
2278                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2279                         free((char*)vp->var_text);
2280
2281                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2282                         *vpp = vp->next;
2283                         free(vp);
2284  out_free:
2285                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2286                                 free(s);
2287                         goto out;
2288                 }
2289
2290                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2291         } else {
2292                 /* variable s is not found */
2293                 if (flags & VNOSET)
2294                         goto out;
2295                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2296                         goto out_free;
2297                 vp = ckzalloc(sizeof(*vp));
2298                 vp->next = *vpp;
2299                 /*vp->func = NULL; - ckzalloc did it */
2300                 *vpp = vp;
2301         }
2302         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2303                 s = ckstrdup(s);
2304         vp->var_text = s;
2305         vp->flags = flags;
2306
2307  out:
2308         return vp;
2309 }
2310
2311 /*
2312  * Set the value of a variable.  The flags argument is ored with the
2313  * flags of the variable.  If val is NULL, the variable is unset.
2314  */
2315 static struct var *
2316 setvar(const char *name, const char *val, int flags)
2317 {
2318         const char *q;
2319         char *p;
2320         char *nameeq;
2321         size_t namelen;
2322         size_t vallen;
2323         struct var *vp;
2324
2325         q = endofname(name);
2326         p = strchrnul(q, '=');
2327         namelen = p - name;
2328         if (!namelen || p != q)
2329                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2330         vallen = 0;
2331         if (val == NULL) {
2332                 flags |= VUNSET;
2333         } else {
2334                 vallen = strlen(val);
2335         }
2336
2337         INT_OFF;
2338         nameeq = ckmalloc(namelen + vallen + 2);
2339         p = mempcpy(nameeq, name, namelen);
2340         if (val) {
2341                 *p++ = '=';
2342                 p = mempcpy(p, val, vallen);
2343         }
2344         *p = '\0';
2345         vp = setvareq(nameeq, flags | VNOSAVE);
2346         INT_ON;
2347
2348         return vp;
2349 }
2350
2351 static void FAST_FUNC
2352 setvar0(const char *name, const char *val)
2353 {
2354         setvar(name, val, 0);
2355 }
2356
2357 /*
2358  * Unset the specified variable.
2359  */
2360 static void
2361 unsetvar(const char *s)
2362 {
2363         setvar(s, NULL, 0);
2364 }
2365
2366 /*
2367  * Process a linked list of variable assignments.
2368  */
2369 static void
2370 listsetvar(struct strlist *list_set_var, int flags)
2371 {
2372         struct strlist *lp = list_set_var;
2373
2374         if (!lp)
2375                 return;
2376         INT_OFF;
2377         do {
2378                 setvareq(lp->text, flags);
2379                 lp = lp->next;
2380         } while (lp);
2381         INT_ON;
2382 }
2383
2384 /*
2385  * Generate a list of variables satisfying the given conditions.
2386  */
2387 static char **
2388 listvars(int on, int off, char ***end)
2389 {
2390         struct var **vpp;
2391         struct var *vp;
2392         char **ep;
2393         int mask;
2394
2395         STARTSTACKSTR(ep);
2396         vpp = vartab;
2397         mask = on | off;
2398         do {
2399                 for (vp = *vpp; vp; vp = vp->next) {
2400                         if ((vp->flags & mask) == on) {
2401                                 if (ep == stackstrend())
2402                                         ep = growstackstr();
2403                                 *ep++ = (char*)vp->var_text;
2404                         }
2405                 }
2406         } while (++vpp < vartab + VTABSIZE);
2407         if (ep == stackstrend())
2408                 ep = growstackstr();
2409         if (end)
2410                 *end = ep;
2411         *ep++ = NULL;
2412         return grabstackstr(ep);
2413 }
2414
2415
2416 /* ============ Path search helper
2417  *
2418  * The variable path (passed by reference) should be set to the start
2419  * of the path before the first call; path_advance will update
2420  * this value as it proceeds.  Successive calls to path_advance will return
2421  * the possible path expansions in sequence.  If an option (indicated by
2422  * a percent sign) appears in the path entry then the global variable
2423  * pathopt will be set to point to it; otherwise pathopt will be set to
2424  * NULL.
2425  */
2426 static const char *pathopt;     /* set by path_advance */
2427
2428 static char *
2429 path_advance(const char **path, const char *name)
2430 {
2431         const char *p;
2432         char *q;
2433         const char *start;
2434         size_t len;
2435
2436         if (*path == NULL)
2437                 return NULL;
2438         start = *path;
2439         for (p = start; *p && *p != ':' && *p != '%'; p++)
2440                 continue;
2441         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2442         while (stackblocksize() < len)
2443                 growstackblock();
2444         q = stackblock();
2445         if (p != start) {
2446                 q = mempcpy(q, start, p - start);
2447                 *q++ = '/';
2448         }
2449         strcpy(q, name);
2450         pathopt = NULL;
2451         if (*p == '%') {
2452                 pathopt = ++p;
2453                 while (*p && *p != ':')
2454                         p++;
2455         }
2456         if (*p == ':')
2457                 *path = p + 1;
2458         else
2459                 *path = NULL;
2460         return stalloc(len);
2461 }
2462
2463
2464 /* ============ Prompt */
2465
2466 static smallint doprompt;                   /* if set, prompt the user */
2467 static smallint needprompt;                 /* true if interactive and at start of line */
2468
2469 #if ENABLE_FEATURE_EDITING
2470 static line_input_t *line_input_state;
2471 static const char *cmdedit_prompt;
2472 static void
2473 putprompt(const char *s)
2474 {
2475         if (ENABLE_ASH_EXPAND_PRMT) {
2476                 free((char*)cmdedit_prompt);
2477                 cmdedit_prompt = ckstrdup(s);
2478                 return;
2479         }
2480         cmdedit_prompt = s;
2481 }
2482 #else
2483 static void
2484 putprompt(const char *s)
2485 {
2486         out2str(s);
2487 }
2488 #endif
2489
2490 /* expandstr() needs parsing machinery, so it is far away ahead... */
2491 static const char *expandstr(const char *ps, int syntax_type);
2492 /* Values for syntax param */
2493 #define BASESYNTAX 0    /* not in quotes */
2494 #define DQSYNTAX   1    /* in double quotes */
2495 #define SQSYNTAX   2    /* in single quotes */
2496 #define ARISYNTAX  3    /* in arithmetic */
2497 #if ENABLE_ASH_EXPAND_PRMT
2498 # define PSSYNTAX  4    /* prompt. never passed to SIT() */
2499 #endif
2500 /* PSSYNTAX expansion is identical to DQSYNTAX, except keeping '\$' as '\$' */
2501
2502 /*
2503  * called by editline -- any expansions to the prompt should be added here.
2504  */
2505 static void
2506 setprompt_if(smallint do_set, int whichprompt)
2507 {
2508         const char *prompt;
2509         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2510
2511         if (!do_set)
2512                 return;
2513
2514         needprompt = 0;
2515
2516         switch (whichprompt) {
2517         case 1:
2518                 prompt = ps1val();
2519                 break;
2520         case 2:
2521                 prompt = ps2val();
2522                 break;
2523         default:                        /* 0 */
2524                 prompt = nullstr;
2525         }
2526 #if ENABLE_ASH_EXPAND_PRMT
2527         pushstackmark(&smark, stackblocksize());
2528         putprompt(expandstr(prompt, PSSYNTAX));
2529         popstackmark(&smark);
2530 #else
2531         putprompt(prompt);
2532 #endif
2533 }
2534
2535
2536 /* ============ The cd and pwd commands */
2537
2538 #define CD_PHYSICAL 1
2539 #define CD_PRINT 2
2540
2541 static int
2542 cdopt(void)
2543 {
2544         int flags = 0;
2545         int i, j;
2546
2547         j = 'L';
2548         while ((i = nextopt("LP")) != '\0') {
2549                 if (i != j) {
2550                         flags ^= CD_PHYSICAL;
2551                         j = i;
2552                 }
2553         }
2554
2555         return flags;
2556 }
2557
2558 /*
2559  * Update curdir (the name of the current directory) in response to a
2560  * cd command.
2561  */
2562 static const char *
2563 updatepwd(const char *dir)
2564 {
2565         char *new;
2566         char *p;
2567         char *cdcomppath;
2568         const char *lim;
2569
2570         cdcomppath = sstrdup(dir);
2571         STARTSTACKSTR(new);
2572         if (*dir != '/') {
2573                 if (curdir == nullstr)
2574                         return 0;
2575                 new = stack_putstr(curdir, new);
2576         }
2577         new = makestrspace(strlen(dir) + 2, new);
2578         lim = (char *)stackblock() + 1;
2579         if (*dir != '/') {
2580                 if (new[-1] != '/')
2581                         USTPUTC('/', new);
2582                 if (new > lim && *lim == '/')
2583                         lim++;
2584         } else {
2585                 USTPUTC('/', new);
2586                 cdcomppath++;
2587                 if (dir[1] == '/' && dir[2] != '/') {
2588                         USTPUTC('/', new);
2589                         cdcomppath++;
2590                         lim++;
2591                 }
2592         }
2593         p = strtok(cdcomppath, "/");
2594         while (p) {
2595                 switch (*p) {
2596                 case '.':
2597                         if (p[1] == '.' && p[2] == '\0') {
2598                                 while (new > lim) {
2599                                         STUNPUTC(new);
2600                                         if (new[-1] == '/')
2601                                                 break;
2602                                 }
2603                                 break;
2604                         }
2605                         if (p[1] == '\0')
2606                                 break;
2607                         /* fall through */
2608                 default:
2609                         new = stack_putstr(p, new);
2610                         USTPUTC('/', new);
2611                 }
2612                 p = strtok(NULL, "/");
2613         }
2614         if (new > lim)
2615                 STUNPUTC(new);
2616         *new = 0;
2617         return stackblock();
2618 }
2619
2620 /*
2621  * Find out what the current directory is. If we already know the current
2622  * directory, this routine returns immediately.
2623  */
2624 static char *
2625 getpwd(void)
2626 {
2627         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2628         return dir ? dir : nullstr;
2629 }
2630
2631 static void
2632 setpwd(const char *val, int setold)
2633 {
2634         char *oldcur, *dir;
2635
2636         oldcur = dir = curdir;
2637
2638         if (setold) {
2639                 setvar("OLDPWD", oldcur, VEXPORT);
2640         }
2641         INT_OFF;
2642         if (physdir != nullstr) {
2643                 if (physdir != oldcur)
2644                         free(physdir);
2645                 physdir = nullstr;
2646         }
2647         if (oldcur == val || !val) {
2648                 char *s = getpwd();
2649                 physdir = s;
2650                 if (!val)
2651                         dir = s;
2652         } else
2653                 dir = ckstrdup(val);
2654         if (oldcur != dir && oldcur != nullstr) {
2655                 free(oldcur);
2656         }
2657         curdir = dir;
2658         INT_ON;
2659         setvar("PWD", dir, VEXPORT);
2660 }
2661
2662 static void hashcd(void);
2663
2664 /*
2665  * Actually do the chdir.  We also call hashcd to let other routines
2666  * know that the current directory has changed.
2667  */
2668 static int
2669 docd(const char *dest, int flags)
2670 {
2671         const char *dir = NULL;
2672         int err;
2673
2674         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2675
2676         INT_OFF;
2677         if (!(flags & CD_PHYSICAL)) {
2678                 dir = updatepwd(dest);
2679                 if (dir)
2680                         dest = dir;
2681         }
2682         err = chdir(dest);
2683         if (err)
2684                 goto out;
2685         setpwd(dir, 1);
2686         hashcd();
2687  out:
2688         INT_ON;
2689         return err;
2690 }
2691
2692 static int FAST_FUNC
2693 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2694 {
2695         const char *dest;
2696         const char *path;
2697         const char *p;
2698         char c;
2699         struct stat statb;
2700         int flags;
2701
2702         flags = cdopt();
2703         dest = *argptr;
2704         if (!dest)
2705                 dest = bltinlookup("HOME");
2706         else if (LONE_DASH(dest)) {
2707                 dest = bltinlookup("OLDPWD");
2708                 flags |= CD_PRINT;
2709         }
2710         if (!dest)
2711                 dest = nullstr;
2712         if (*dest == '/')
2713                 goto step6;
2714         if (*dest == '.') {
2715                 c = dest[1];
2716  dotdot:
2717                 switch (c) {
2718                 case '\0':
2719                 case '/':
2720                         goto step6;
2721                 case '.':
2722                         c = dest[2];
2723                         if (c != '.')
2724                                 goto dotdot;
2725                 }
2726         }
2727         if (!*dest)
2728                 dest = ".";
2729         path = bltinlookup("CDPATH");
2730         while (path) {
2731                 c = *path;
2732                 p = path_advance(&path, dest);
2733                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2734                         if (c && c != ':')
2735                                 flags |= CD_PRINT;
2736  docd:
2737                         if (!docd(p, flags))
2738                                 goto out;
2739                         goto err;
2740                 }
2741         }
2742
2743  step6:
2744         p = dest;
2745         goto docd;
2746
2747  err:
2748         ash_msg_and_raise_error("can't cd to %s", dest);
2749         /* NOTREACHED */
2750  out:
2751         if (flags & CD_PRINT)
2752                 out1fmt("%s\n", curdir);
2753         return 0;
2754 }
2755
2756 static int FAST_FUNC
2757 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2758 {
2759         int flags;
2760         const char *dir = curdir;
2761
2762         flags = cdopt();
2763         if (flags) {
2764                 if (physdir == nullstr)
2765                         setpwd(dir, 0);
2766                 dir = physdir;
2767         }
2768         out1fmt("%s\n", dir);
2769         return 0;
2770 }
2771
2772
2773 /* ============ ... */
2774
2775
2776 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2777
2778 /* Syntax classes */
2779 #define CWORD     0             /* character is nothing special */
2780 #define CNL       1             /* newline character */
2781 #define CBACK     2             /* a backslash character */
2782 #define CSQUOTE   3             /* single quote */
2783 #define CDQUOTE   4             /* double quote */
2784 #define CENDQUOTE 5             /* a terminating quote */
2785 #define CBQUOTE   6             /* backwards single quote */
2786 #define CVAR      7             /* a dollar sign */
2787 #define CENDVAR   8             /* a '}' character */
2788 #define CLP       9             /* a left paren in arithmetic */
2789 #define CRP      10             /* a right paren in arithmetic */
2790 #define CENDFILE 11             /* end of file */
2791 #define CCTL     12             /* like CWORD, except it must be escaped */
2792 #define CSPCL    13             /* these terminate a word */
2793 #define CIGN     14             /* character should be ignored */
2794
2795 #define PEOF     256
2796 #if ENABLE_ASH_ALIAS
2797 # define PEOA    257
2798 #endif
2799
2800 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2801
2802 #if ENABLE_FEATURE_SH_MATH
2803 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2804 #else
2805 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2806 #endif
2807 static const uint16_t S_I_T[] ALIGN2 = {
2808 #if ENABLE_ASH_ALIAS
2809         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2810 #endif
2811         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2812         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2813         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2814         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2815         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2816         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2817         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2818         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2819         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2820         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2821         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2822 #if !USE_SIT_FUNCTION
2823         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2824         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2825         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2826 #endif
2827 #undef SIT_ITEM
2828 };
2829 /* Constants below must match table above */
2830 enum {
2831 #if ENABLE_ASH_ALIAS
2832         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2833 #endif
2834         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2835         CNL_CNL_CNL_CNL                    , /*  2 */
2836         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2837         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2838         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2839         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2840         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2841         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2842         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2843         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2844         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2845         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2846         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2847         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2848 };
2849
2850 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2851  * caller must ensure proper cast on it if c is *char_ptr!
2852  */
2853 #if USE_SIT_FUNCTION
2854
2855 static int
2856 SIT(int c, int syntax)
2857 {
2858         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2859         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2860         /*
2861          * This causes '/' to be prepended with CTLESC in dquoted string,
2862          * making "./file"* treated incorrectly because we feed
2863          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2864          * The "homegrown" glob implementation is okay with that,
2865          * but glibc one isn't. With '/' always treated as CWORD,
2866          * both work fine.
2867          */
2868 # if ENABLE_ASH_ALIAS
2869         static const uint8_t syntax_index_table[] ALIGN1 = {
2870                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2871                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2872                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2873                 11, 3                           /* "}~" */
2874         };
2875 # else
2876         static const uint8_t syntax_index_table[] ALIGN1 = {
2877                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2878                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2879                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2880                 10, 2                           /* "}~" */
2881         };
2882 # endif
2883         const char *s;
2884         int indx;
2885
2886         if (c == PEOF)
2887                 return CENDFILE;
2888 # if ENABLE_ASH_ALIAS
2889         if (c == PEOA)
2890                 indx = 0;
2891         else
2892 # endif
2893         {
2894                 /* Cast is purely for paranoia here,
2895                  * just in case someone passed signed char to us */
2896                 if ((unsigned char)c >= CTL_FIRST
2897                  && (unsigned char)c <= CTL_LAST
2898                 ) {
2899                         return CCTL;
2900                 }
2901                 s = strchrnul(spec_symbls, c);
2902                 if (*s == '\0')
2903                         return CWORD;
2904                 indx = syntax_index_table[s - spec_symbls];
2905         }
2906         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2907 }
2908
2909 #else   /* !USE_SIT_FUNCTION */
2910
2911 static const uint8_t syntax_index_table[] ALIGN1 = {
2912         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2913         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2914         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2915         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2916         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2917         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2918         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2919         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2920         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2921         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2922         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2923         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2924         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2925         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2926         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2927         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2928         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2929         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2930         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2931         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2932         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2933         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2934         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2935         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2936         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2937         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2938         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2939         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2940         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2941         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2942         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2943         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2944         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2945         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2946         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2947         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2948         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2949         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2950         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2951         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2952         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2953         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2954         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2955         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2956         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2957         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2958         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2959         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2960 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2961         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2962         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2963         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2964         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2965         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2966         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2967         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2968         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2969         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2970         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2971         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2972         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2973         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2974         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2975         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2976         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2977         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2978         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2979         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2980         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2981         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2982         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2983         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2984         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2985         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2986         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2987         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2988         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2989         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2990         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2991         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2992         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2993         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2994         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2995         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2996         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
2997         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
2998         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
2999         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
3000         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
3001         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
3002         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
3003         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
3004         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3005         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3006         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3007         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3008         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3009         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3010         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3011         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3012         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3013         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3014         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3015         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3016         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3017         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3018         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3019         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3020         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3021         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3022         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3023         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3024         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3025         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3026         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3027         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3028         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3029         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3030         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3031         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3032         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3033         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3034         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3035         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3036         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3037         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3038         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3039         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3040         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3041         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3042         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3043         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3044         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3045         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3046         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3047         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3048         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3049         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3050         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3051         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3052         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3053         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3054         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3150         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3151         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3152         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3165         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3166         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3167         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3168         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3169         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3170         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3171 # if ENABLE_ASH_ALIAS
3172         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3173 # endif
3174 };
3175
3176 #if 1
3177 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3178 #else /* debug version, caught one signed char bug */
3179 # define SIT(c, syntax) \
3180         ({ \
3181                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3182                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3183                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3184                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3185                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3186         })
3187 #endif
3188
3189 #endif  /* !USE_SIT_FUNCTION */
3190
3191
3192 /* ============ Alias handling */
3193
3194 #if ENABLE_ASH_ALIAS
3195
3196 #define ALIASINUSE 1
3197 #define ALIASDEAD  2
3198
3199 struct alias {
3200         struct alias *next;
3201         char *name;
3202         char *val;
3203         int flag;
3204 };
3205
3206
3207 static struct alias **atab; // [ATABSIZE];
3208 #define INIT_G_alias() do { \
3209         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3210 } while (0)
3211
3212
3213 static struct alias **
3214 __lookupalias(const char *name)
3215 {
3216         unsigned int hashval;
3217         struct alias **app;
3218         const char *p;
3219         unsigned int ch;
3220
3221         p = name;
3222
3223         ch = (unsigned char)*p;
3224         hashval = ch << 4;
3225         while (ch) {
3226                 hashval += ch;
3227                 ch = (unsigned char)*++p;
3228         }
3229         app = &atab[hashval % ATABSIZE];
3230
3231         for (; *app; app = &(*app)->next) {
3232                 if (strcmp(name, (*app)->name) == 0) {
3233                         break;
3234                 }
3235         }
3236
3237         return app;
3238 }
3239
3240 static struct alias *
3241 lookupalias(const char *name, int check)
3242 {
3243         struct alias *ap = *__lookupalias(name);
3244
3245         if (check && ap && (ap->flag & ALIASINUSE))
3246                 return NULL;
3247         return ap;
3248 }
3249
3250 static struct alias *
3251 freealias(struct alias *ap)
3252 {
3253         struct alias *next;
3254
3255         if (ap->flag & ALIASINUSE) {
3256                 ap->flag |= ALIASDEAD;
3257                 return ap;
3258         }
3259
3260         next = ap->next;
3261         free(ap->name);
3262         free(ap->val);
3263         free(ap);
3264         return next;
3265 }
3266
3267 static void
3268 setalias(const char *name, const char *val)
3269 {
3270         struct alias *ap, **app;
3271
3272         app = __lookupalias(name);
3273         ap = *app;
3274         INT_OFF;
3275         if (ap) {
3276                 if (!(ap->flag & ALIASINUSE)) {
3277                         free(ap->val);
3278                 }
3279                 ap->val = ckstrdup(val);
3280                 ap->flag &= ~ALIASDEAD;
3281         } else {
3282                 /* not found */
3283                 ap = ckzalloc(sizeof(struct alias));
3284                 ap->name = ckstrdup(name);
3285                 ap->val = ckstrdup(val);
3286                 /*ap->flag = 0; - ckzalloc did it */
3287                 /*ap->next = NULL;*/
3288                 *app = ap;
3289         }
3290         INT_ON;
3291 }
3292
3293 static int
3294 unalias(const char *name)
3295 {
3296         struct alias **app;
3297
3298         app = __lookupalias(name);
3299
3300         if (*app) {
3301                 INT_OFF;
3302                 *app = freealias(*app);
3303                 INT_ON;
3304                 return 0;
3305         }
3306
3307         return 1;
3308 }
3309
3310 static void
3311 rmaliases(void)
3312 {
3313         struct alias *ap, **app;
3314         int i;
3315
3316         INT_OFF;
3317         for (i = 0; i < ATABSIZE; i++) {
3318                 app = &atab[i];
3319                 for (ap = *app; ap; ap = *app) {
3320                         *app = freealias(*app);
3321                         if (ap == *app) {
3322                                 app = &ap->next;
3323                         }
3324                 }
3325         }
3326         INT_ON;
3327 }
3328
3329 static void
3330 printalias(const struct alias *ap)
3331 {
3332         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3333 }
3334
3335 /*
3336  * TODO - sort output
3337  */
3338 static int FAST_FUNC
3339 aliascmd(int argc UNUSED_PARAM, char **argv)
3340 {
3341         char *n, *v;
3342         int ret = 0;
3343         struct alias *ap;
3344
3345         if (!argv[1]) {
3346                 int i;
3347
3348                 for (i = 0; i < ATABSIZE; i++) {
3349                         for (ap = atab[i]; ap; ap = ap->next) {
3350                                 printalias(ap);
3351                         }
3352                 }
3353                 return 0;
3354         }
3355         while ((n = *++argv) != NULL) {
3356                 v = strchr(n+1, '=');
3357                 if (v == NULL) { /* n+1: funny ksh stuff */
3358                         ap = *__lookupalias(n);
3359                         if (ap == NULL) {
3360                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3361                                 ret = 1;
3362                         } else
3363                                 printalias(ap);
3364                 } else {
3365                         *v++ = '\0';
3366                         setalias(n, v);
3367                 }
3368         }
3369
3370         return ret;
3371 }
3372
3373 static int FAST_FUNC
3374 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3375 {
3376         int i;
3377
3378         while (nextopt("a") != '\0') {
3379                 rmaliases();
3380                 return 0;
3381         }
3382         for (i = 0; *argptr; argptr++) {
3383                 if (unalias(*argptr)) {
3384                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3385                         i = 1;
3386                 }
3387         }
3388
3389         return i;
3390 }
3391
3392 #endif /* ASH_ALIAS */
3393
3394
3395 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3396 #define FORK_FG    0
3397 #define FORK_BG    1
3398 #define FORK_NOJOB 2
3399
3400 /* mode flags for showjob(s) */
3401 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3402 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3403 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3404 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3405
3406 /*
3407  * A job structure contains information about a job.  A job is either a
3408  * single process or a set of processes contained in a pipeline.  In the
3409  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3410  * array of pids.
3411  */
3412 struct procstat {
3413         pid_t   ps_pid;         /* process id */
3414         int     ps_status;      /* last process status from wait() */
3415         char    *ps_cmd;        /* text of command being run */
3416 };
3417
3418 struct job {
3419         struct procstat ps0;    /* status of process */
3420         struct procstat *ps;    /* status or processes when more than one */
3421 #if JOBS
3422         int stopstatus;         /* status of a stopped job */
3423 #endif
3424         unsigned nprocs;        /* number of processes */
3425
3426 #define JOBRUNNING      0       /* at least one proc running */
3427 #define JOBSTOPPED      1       /* all procs are stopped */
3428 #define JOBDONE         2       /* all procs are completed */
3429         unsigned
3430                 state: 8,
3431 #if JOBS
3432                 sigint: 1,      /* job was killed by SIGINT */
3433                 jobctl: 1,      /* job running under job control */
3434 #endif
3435                 waited: 1,      /* true if this entry has been waited for */
3436                 used: 1,        /* true if this entry is in used */
3437                 changed: 1;     /* true if status has changed */
3438         struct job *prev_job;   /* previous job */
3439 };
3440
3441 static struct job *makejob(/*union node *,*/ int);
3442 static int forkshell(struct job *, union node *, int);
3443 static int waitforjob(struct job *);
3444
3445 #if !JOBS
3446 enum { doing_jobctl = 0 };
3447 #define setjobctl(on) do {} while (0)
3448 #else
3449 static smallint doing_jobctl; //references:8
3450 static void setjobctl(int);
3451 #endif
3452
3453 /*
3454  * Ignore a signal.
3455  */
3456 static void
3457 ignoresig(int signo)
3458 {
3459         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3460         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3461                 /* No, need to do it */
3462                 signal(signo, SIG_IGN);
3463         }
3464         sigmode[signo - 1] = S_HARD_IGN;
3465 }
3466
3467 /*
3468  * Only one usage site - in setsignal()
3469  */
3470 static void
3471 signal_handler(int signo)
3472 {
3473         if (signo == SIGCHLD) {
3474                 got_sigchld = 1;
3475                 if (!trap[SIGCHLD])
3476                         return;
3477         }
3478
3479         gotsig[signo - 1] = 1;
3480         pending_sig = signo;
3481
3482         if (signo == SIGINT && !trap[SIGINT]) {
3483                 if (!suppress_int) {
3484                         pending_sig = 0;
3485                         raise_interrupt(); /* does not return */
3486                 }
3487                 pending_int = 1;
3488         }
3489 }
3490
3491 /*
3492  * Set the signal handler for the specified signal.  The routine figures
3493  * out what it should be set to.
3494  */
3495 static void
3496 setsignal(int signo)
3497 {
3498         char *t;
3499         char cur_act, new_act;
3500         struct sigaction act;
3501
3502         t = trap[signo];
3503         new_act = S_DFL;
3504         if (t != NULL) { /* trap for this sig is set */
3505                 new_act = S_CATCH;
3506                 if (t[0] == '\0') /* trap is "": ignore this sig */
3507                         new_act = S_IGN;
3508         }
3509
3510         if (rootshell && new_act == S_DFL) {
3511                 switch (signo) {
3512                 case SIGINT:
3513                         if (iflag || minusc || sflag == 0)
3514                                 new_act = S_CATCH;
3515                         break;
3516                 case SIGQUIT:
3517 #if DEBUG
3518                         if (debug)
3519                                 break;
3520 #endif
3521                         /* man bash:
3522                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3523                          * commands run by bash have signal handlers
3524                          * set to the values inherited by the shell
3525                          * from its parent". */
3526                         new_act = S_IGN;
3527                         break;
3528                 case SIGTERM:
3529                         if (iflag)
3530                                 new_act = S_IGN;
3531                         break;
3532 #if JOBS
3533                 case SIGTSTP:
3534                 case SIGTTOU:
3535                         if (mflag)
3536                                 new_act = S_IGN;
3537                         break;
3538 #endif
3539                 }
3540         }
3541 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3542 //whereas we have to restore it to what shell got on entry
3543 //from the parent. See comment above
3544
3545         if (signo == SIGCHLD)
3546                 new_act = S_CATCH;
3547
3548         t = &sigmode[signo - 1];
3549         cur_act = *t;
3550         if (cur_act == 0) {
3551                 /* current setting is not yet known */
3552                 if (sigaction(signo, NULL, &act)) {
3553                         /* pretend it worked; maybe we should give a warning,
3554                          * but other shells don't. We don't alter sigmode,
3555                          * so we retry every time.
3556                          * btw, in Linux it never fails. --vda */
3557                         return;
3558                 }
3559                 if (act.sa_handler == SIG_IGN) {
3560                         cur_act = S_HARD_IGN;
3561                         if (mflag
3562                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3563                         ) {
3564                                 cur_act = S_IGN;   /* don't hard ignore these */
3565                         }
3566                 }
3567         }
3568         if (cur_act == S_HARD_IGN || cur_act == new_act)
3569                 return;
3570
3571         act.sa_handler = SIG_DFL;
3572         switch (new_act) {
3573         case S_CATCH:
3574                 act.sa_handler = signal_handler;
3575                 break;
3576         case S_IGN:
3577                 act.sa_handler = SIG_IGN;
3578                 break;
3579         }
3580
3581         /* flags and mask matter only if !DFL and !IGN, but we do it
3582          * for all cases for more deterministic behavior:
3583          */
3584         act.sa_flags = 0;
3585         sigfillset(&act.sa_mask);
3586
3587         sigaction_set(signo, &act);
3588
3589         *t = new_act;
3590 }
3591
3592 /* mode flags for set_curjob */
3593 #define CUR_DELETE 2
3594 #define CUR_RUNNING 1
3595 #define CUR_STOPPED 0
3596
3597 #if JOBS
3598 /* pgrp of shell on invocation */
3599 static int initialpgrp; //references:2
3600 static int ttyfd = -1; //5
3601 #endif
3602 /* array of jobs */
3603 static struct job *jobtab; //5
3604 /* size of array */
3605 static unsigned njobs; //4
3606 /* current job */
3607 static struct job *curjob; //lots
3608 /* number of presumed living untracked jobs */
3609 static int jobless; //4
3610
3611 #if 0
3612 /* Bash has a feature: it restores termios after a successful wait for
3613  * a foreground job which had at least one stopped or sigkilled member.
3614  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3615  * properly restoring tty state. Should we do this too?
3616  * A reproducer: ^Z an interactive python:
3617  *
3618  * # python
3619  * Python 2.7.12 (...)
3620  * >>> ^Z
3621  *      { python leaves tty in -icanon -echo state. We do survive that... }
3622  *  [1]+  Stopped                    python
3623  *      { ...however, next program (python #2) does not survive it well: }
3624  * # python
3625  * Python 2.7.12 (...)
3626  * >>> Traceback (most recent call last):
3627  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3628  *   File "<stdin>", line 1, in <module>
3629  * NameError: name 'qwerty' is not defined
3630  *
3631  * The implementation below is modeled on bash code and seems to work.
3632  * However, I'm not sure we should do this. For one: what if I'd fg
3633  * the stopped python instead? It'll be confused by "restored" tty state.
3634  */
3635 static struct termios shell_tty_info;
3636 static void
3637 get_tty_state(void)
3638 {
3639         if (rootshell && ttyfd >= 0)
3640                 tcgetattr(ttyfd, &shell_tty_info);
3641 }
3642 static void
3643 set_tty_state(void)
3644 {
3645         /* if (rootshell) - caller ensures this */
3646         if (ttyfd >= 0)
3647                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3648 }
3649 static int
3650 job_signal_status(struct job *jp)
3651 {
3652         int status;
3653         unsigned i;
3654         struct procstat *ps = jp->ps;
3655         for (i = 0; i < jp->nprocs; i++) {
3656                 status = ps[i].ps_status;
3657                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3658                         return status;
3659         }
3660         return 0;
3661 }
3662 static void
3663 restore_tty_if_stopped_or_signaled(struct job *jp)
3664 {
3665 //TODO: check what happens if we come from waitforjob() in expbackq()
3666         if (rootshell) {
3667                 int s = job_signal_status(jp);
3668                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3669                         set_tty_state();
3670         }
3671 }
3672 #else
3673 # define get_tty_state() ((void)0)
3674 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3675 #endif
3676
3677 static void
3678 set_curjob(struct job *jp, unsigned mode)
3679 {
3680         struct job *jp1;
3681         struct job **jpp, **curp;
3682
3683         /* first remove from list */
3684         jpp = curp = &curjob;
3685         while (1) {
3686                 jp1 = *jpp;
3687                 if (jp1 == jp)
3688                         break;
3689                 jpp = &jp1->prev_job;
3690         }
3691         *jpp = jp1->prev_job;
3692
3693         /* Then re-insert in correct position */
3694         jpp = curp;
3695         switch (mode) {
3696         default:
3697 #if DEBUG
3698                 abort();
3699 #endif
3700         case CUR_DELETE:
3701                 /* job being deleted */
3702                 break;
3703         case CUR_RUNNING:
3704                 /* newly created job or backgrounded job,
3705                  * put after all stopped jobs.
3706                  */
3707                 while (1) {
3708                         jp1 = *jpp;
3709 #if JOBS
3710                         if (!jp1 || jp1->state != JOBSTOPPED)
3711 #endif
3712                                 break;
3713                         jpp = &jp1->prev_job;
3714                 }
3715                 /* FALLTHROUGH */
3716 #if JOBS
3717         case CUR_STOPPED:
3718 #endif
3719                 /* newly stopped job - becomes curjob */
3720                 jp->prev_job = *jpp;
3721                 *jpp = jp;
3722                 break;
3723         }
3724 }
3725
3726 #if JOBS || DEBUG
3727 static int
3728 jobno(const struct job *jp)
3729 {
3730         return jp - jobtab + 1;
3731 }
3732 #endif
3733
3734 /*
3735  * Convert a job name to a job structure.
3736  */
3737 #if !JOBS
3738 #define getjob(name, getctl) getjob(name)
3739 #endif
3740 static struct job *
3741 getjob(const char *name, int getctl)
3742 {
3743         struct job *jp;
3744         struct job *found;
3745         const char *err_msg = "%s: no such job";
3746         unsigned num;
3747         int c;
3748         const char *p;
3749         char *(*match)(const char *, const char *);
3750
3751         jp = curjob;
3752         p = name;
3753         if (!p)
3754                 goto currentjob;
3755
3756         if (*p != '%')
3757                 goto err;
3758
3759         c = *++p;
3760         if (!c)
3761                 goto currentjob;
3762
3763         if (!p[1]) {
3764                 if (c == '+' || c == '%') {
3765  currentjob:
3766                         err_msg = "No current job";
3767                         goto check;
3768                 }
3769                 if (c == '-') {
3770                         if (jp)
3771                                 jp = jp->prev_job;
3772                         err_msg = "No previous job";
3773  check:
3774                         if (!jp)
3775                                 goto err;
3776                         goto gotit;
3777                 }
3778         }
3779
3780         if (is_number(p)) {
3781                 num = atoi(p);
3782                 if (num > 0 && num <= njobs) {
3783                         jp = jobtab + num - 1;
3784                         if (jp->used)
3785                                 goto gotit;
3786                         goto err;
3787                 }
3788         }
3789
3790         match = prefix;
3791         if (*p == '?') {
3792                 match = strstr;
3793                 p++;
3794         }
3795
3796         found = NULL;
3797         while (jp) {
3798                 if (match(jp->ps[0].ps_cmd, p)) {
3799                         if (found)
3800                                 goto err;
3801                         found = jp;
3802                         err_msg = "%s: ambiguous";
3803                 }
3804                 jp = jp->prev_job;
3805         }
3806         if (!found)
3807                 goto err;
3808         jp = found;
3809
3810  gotit:
3811 #if JOBS
3812         err_msg = "job %s not created under job control";
3813         if (getctl && jp->jobctl == 0)
3814                 goto err;
3815 #endif
3816         return jp;
3817  err:
3818         ash_msg_and_raise_error(err_msg, name);
3819 }
3820
3821 /*
3822  * Mark a job structure as unused.
3823  */
3824 static void
3825 freejob(struct job *jp)
3826 {
3827         struct procstat *ps;
3828         int i;
3829
3830         INT_OFF;
3831         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3832                 if (ps->ps_cmd != nullstr)
3833                         free(ps->ps_cmd);
3834         }
3835         if (jp->ps != &jp->ps0)
3836                 free(jp->ps);
3837         jp->used = 0;
3838         set_curjob(jp, CUR_DELETE);
3839         INT_ON;
3840 }
3841
3842 #if JOBS
3843 static void
3844 xtcsetpgrp(int fd, pid_t pgrp)
3845 {
3846         if (tcsetpgrp(fd, pgrp))
3847                 ash_msg_and_raise_perror("can't set tty process group");
3848 }
3849
3850 /*
3851  * Turn job control on and off.
3852  *
3853  * Note:  This code assumes that the third arg to ioctl is a character
3854  * pointer, which is true on Berkeley systems but not System V.  Since
3855  * System V doesn't have job control yet, this isn't a problem now.
3856  *
3857  * Called with interrupts off.
3858  */
3859 static void
3860 setjobctl(int on)
3861 {
3862         int fd;
3863         int pgrp;
3864
3865         if (on == doing_jobctl || rootshell == 0)
3866                 return;
3867         if (on) {
3868                 int ofd;
3869                 ofd = fd = open(_PATH_TTY, O_RDWR);
3870                 if (fd < 0) {
3871         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3872          * That sometimes helps to acquire controlling tty.
3873          * Obviously, a workaround for bugs when someone
3874          * failed to provide a controlling tty to bash! :) */
3875                         fd = 2;
3876                         while (!isatty(fd))
3877                                 if (--fd < 0)
3878                                         goto out;
3879                 }
3880                 /* fd is a tty at this point */
3881                 fd = fcntl(fd, F_DUPFD, 10);
3882                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3883                         close(ofd);
3884                 if (fd < 0)
3885                         goto out; /* F_DUPFD failed */
3886                 close_on_exec_on(fd);
3887                 while (1) { /* while we are in the background */
3888                         pgrp = tcgetpgrp(fd);
3889                         if (pgrp < 0) {
3890  out:
3891                                 ash_msg("can't access tty; job control turned off");
3892                                 mflag = on = 0;
3893                                 goto close;
3894                         }
3895                         if (pgrp == getpgrp())
3896                                 break;
3897                         killpg(0, SIGTTIN);
3898                 }
3899                 initialpgrp = pgrp;
3900
3901                 setsignal(SIGTSTP);
3902                 setsignal(SIGTTOU);
3903                 setsignal(SIGTTIN);
3904                 pgrp = rootpid;
3905                 setpgid(0, pgrp);
3906                 xtcsetpgrp(fd, pgrp);
3907         } else {
3908                 /* turning job control off */
3909                 fd = ttyfd;
3910                 pgrp = initialpgrp;
3911                 /* was xtcsetpgrp, but this can make exiting ash
3912                  * loop forever if pty is already deleted */
3913                 tcsetpgrp(fd, pgrp);
3914                 setpgid(0, pgrp);
3915                 setsignal(SIGTSTP);
3916                 setsignal(SIGTTOU);
3917                 setsignal(SIGTTIN);
3918  close:
3919                 if (fd >= 0)
3920                         close(fd);
3921                 fd = -1;
3922         }
3923         ttyfd = fd;
3924         doing_jobctl = on;
3925 }
3926
3927 static int FAST_FUNC
3928 killcmd(int argc, char **argv)
3929 {
3930         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3931                 int i = 1;
3932                 do {
3933                         if (argv[i][0] == '%') {
3934                                 /*
3935                                  * "kill %N" - job kill
3936                                  * Converting to pgrp / pid kill
3937                                  */
3938                                 struct job *jp;
3939                                 char *dst;
3940                                 int j, n;
3941
3942                                 jp = getjob(argv[i], 0);
3943                                 /*
3944                                  * In jobs started under job control, we signal
3945                                  * entire process group by kill -PGRP_ID.
3946                                  * This happens, f.e., in interactive shell.
3947                                  *
3948                                  * Otherwise, we signal each child via
3949                                  * kill PID1 PID2 PID3.
3950                                  * Testcases:
3951                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3952                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3953                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3954                                  */
3955                                 n = jp->nprocs; /* can't be 0 (I hope) */
3956                                 if (jp->jobctl)
3957                                         n = 1;
3958                                 dst = alloca(n * sizeof(int)*4);
3959                                 argv[i] = dst;
3960                                 for (j = 0; j < n; j++) {
3961                                         struct procstat *ps = &jp->ps[j];
3962                                         /* Skip non-running and not-stopped members
3963                                          * (i.e. dead members) of the job
3964                                          */
3965                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3966                                                 continue;
3967                                         /*
3968                                          * kill_main has matching code to expect
3969                                          * leading space. Needed to not confuse
3970                                          * negative pids with "kill -SIGNAL_NO" syntax
3971                                          */
3972                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3973                                 }
3974                                 *dst = '\0';
3975                         }
3976                 } while (argv[++i]);
3977         }
3978         return kill_main(argc, argv);
3979 }
3980
3981 static void
3982 showpipe(struct job *jp /*, FILE *out*/)
3983 {
3984         struct procstat *ps;
3985         struct procstat *psend;
3986
3987         psend = jp->ps + jp->nprocs;
3988         for (ps = jp->ps + 1; ps < psend; ps++)
3989                 printf(" | %s", ps->ps_cmd);
3990         newline_and_flush(stdout);
3991         flush_stdout_stderr();
3992 }
3993
3994
3995 static int
3996 restartjob(struct job *jp, int mode)
3997 {
3998         struct procstat *ps;
3999         int i;
4000         int status;
4001         pid_t pgid;
4002
4003         INT_OFF;
4004         if (jp->state == JOBDONE)
4005                 goto out;
4006         jp->state = JOBRUNNING;
4007         pgid = jp->ps[0].ps_pid;
4008         if (mode == FORK_FG) {
4009                 get_tty_state();
4010                 xtcsetpgrp(ttyfd, pgid);
4011         }
4012         killpg(pgid, SIGCONT);
4013         ps = jp->ps;
4014         i = jp->nprocs;
4015         do {
4016                 if (WIFSTOPPED(ps->ps_status)) {
4017                         ps->ps_status = -1;
4018                 }
4019                 ps++;
4020         } while (--i);
4021  out:
4022         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4023         INT_ON;
4024         return status;
4025 }
4026
4027 static int FAST_FUNC
4028 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4029 {
4030         struct job *jp;
4031         int mode;
4032         int retval;
4033
4034         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4035         nextopt(nullstr);
4036         argv = argptr;
4037         do {
4038                 jp = getjob(*argv, 1);
4039                 if (mode == FORK_BG) {
4040                         set_curjob(jp, CUR_RUNNING);
4041                         printf("[%d] ", jobno(jp));
4042                 }
4043                 out1str(jp->ps[0].ps_cmd);
4044                 showpipe(jp /*, stdout*/);
4045                 retval = restartjob(jp, mode);
4046         } while (*argv && *++argv);
4047         return retval;
4048 }
4049 #endif
4050
4051 static int
4052 sprint_status48(char *s, int status, int sigonly)
4053 {
4054         int col;
4055         int st;
4056
4057         col = 0;
4058         if (!WIFEXITED(status)) {
4059 #if JOBS
4060                 if (WIFSTOPPED(status))
4061                         st = WSTOPSIG(status);
4062                 else
4063 #endif
4064                         st = WTERMSIG(status);
4065                 if (sigonly) {
4066                         if (st == SIGINT || st == SIGPIPE)
4067                                 goto out;
4068 #if JOBS
4069                         if (WIFSTOPPED(status))
4070                                 goto out;
4071 #endif
4072                 }
4073                 st &= 0x7f;
4074 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4075                 col = fmtstr(s, 32, strsignal(st));
4076                 if (WCOREDUMP(status)) {
4077                         strcpy(s + col, " (core dumped)");
4078                         col += sizeof(" (core dumped)")-1;
4079                 }
4080         } else if (!sigonly) {
4081                 st = WEXITSTATUS(status);
4082                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4083         }
4084  out:
4085         return col;
4086 }
4087
4088 static int
4089 wait_block_or_sig(int *status)
4090 {
4091         int pid;
4092
4093         do {
4094                 sigset_t mask;
4095
4096                 /* Poll all children for changes in their state */
4097                 got_sigchld = 0;
4098                 /* if job control is active, accept stopped processes too */
4099                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4100                 if (pid != 0)
4101                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4102
4103                 /* Children exist, but none are ready. Sleep until interesting signal */
4104 #if 1
4105                 sigfillset(&mask);
4106                 sigprocmask(SIG_SETMASK, &mask, &mask);
4107                 while (!got_sigchld && !pending_sig)
4108                         sigsuspend(&mask);
4109                 sigprocmask(SIG_SETMASK, &mask, NULL);
4110 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4111                 while (!got_sigchld && !pending_sig)
4112                         pause();
4113 #endif
4114
4115                 /* If it was SIGCHLD, poll children again */
4116         } while (got_sigchld);
4117
4118         return pid;
4119 }
4120
4121 #define DOWAIT_NONBLOCK 0
4122 #define DOWAIT_BLOCK    1
4123 #define DOWAIT_BLOCK_OR_SIG 2
4124
4125 static int
4126 dowait(int block, struct job *job)
4127 {
4128         int pid;
4129         int status;
4130         struct job *jp;
4131         struct job *thisjob = NULL;
4132
4133         TRACE(("dowait(0x%x) called\n", block));
4134
4135         /* It's wrong to call waitpid() outside of INT_OFF region:
4136          * signal can arrive just after syscall return and handler can
4137          * longjmp away, losing stop/exit notification processing.
4138          * Thus, for "jobs" builtin, and for waiting for a fg job,
4139          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4140          *
4141          * However, for "wait" builtin it is wrong to simply call waitpid()
4142          * in INT_OFF region: "wait" needs to wait for any running job
4143          * to change state, but should exit on any trap too.
4144          * In INT_OFF region, a signal just before syscall entry can set
4145          * pending_sig variables, but we can't check them, and we would
4146          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4147          *
4148          * Because of this, we run inside INT_OFF, but use a special routine
4149          * which combines waitpid() and sigsuspend().
4150          * This is the reason why we need to have a handler for SIGCHLD:
4151          * SIG_DFL handler does not wake sigsuspend().
4152          */
4153         INT_OFF;
4154         if (block == DOWAIT_BLOCK_OR_SIG) {
4155                 pid = wait_block_or_sig(&status);
4156         } else {
4157                 int wait_flags = 0;
4158                 if (block == DOWAIT_NONBLOCK)
4159                         wait_flags = WNOHANG;
4160                 /* if job control is active, accept stopped processes too */
4161                 if (doing_jobctl)
4162                         wait_flags |= WUNTRACED;
4163                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4164                 pid = waitpid(-1, &status, wait_flags);
4165         }
4166         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4167                                 pid, status, errno, strerror(errno)));
4168         if (pid <= 0)
4169                 goto out;
4170
4171         thisjob = NULL;
4172         for (jp = curjob; jp; jp = jp->prev_job) {
4173                 int jobstate;
4174                 struct procstat *ps;
4175                 struct procstat *psend;
4176                 if (jp->state == JOBDONE)
4177                         continue;
4178                 jobstate = JOBDONE;
4179                 ps = jp->ps;
4180                 psend = ps + jp->nprocs;
4181                 do {
4182                         if (ps->ps_pid == pid) {
4183                                 TRACE(("Job %d: changing status of proc %d "
4184                                         "from 0x%x to 0x%x\n",
4185                                         jobno(jp), pid, ps->ps_status, status));
4186                                 ps->ps_status = status;
4187                                 thisjob = jp;
4188                         }
4189                         if (ps->ps_status == -1)
4190                                 jobstate = JOBRUNNING;
4191 #if JOBS
4192                         if (jobstate == JOBRUNNING)
4193                                 continue;
4194                         if (WIFSTOPPED(ps->ps_status)) {
4195                                 jp->stopstatus = ps->ps_status;
4196                                 jobstate = JOBSTOPPED;
4197                         }
4198 #endif
4199                 } while (++ps < psend);
4200                 if (!thisjob)
4201                         continue;
4202
4203                 /* Found the job where one of its processes changed its state.
4204                  * Is there at least one live and running process in this job? */
4205                 if (jobstate != JOBRUNNING) {
4206                         /* No. All live processes in the job are stopped
4207                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4208                          */
4209                         thisjob->changed = 1;
4210                         if (thisjob->state != jobstate) {
4211                                 TRACE(("Job %d: changing state from %d to %d\n",
4212                                         jobno(thisjob), thisjob->state, jobstate));
4213                                 thisjob->state = jobstate;
4214 #if JOBS
4215                                 if (jobstate == JOBSTOPPED)
4216                                         set_curjob(thisjob, CUR_STOPPED);
4217 #endif
4218                         }
4219                 }
4220                 goto out;
4221         }
4222         /* The process wasn't found in job list */
4223 #if JOBS
4224         if (!WIFSTOPPED(status))
4225                 jobless--;
4226 #endif
4227  out:
4228         INT_ON;
4229
4230         if (thisjob && thisjob == job) {
4231                 char s[48 + 1];
4232                 int len;
4233
4234                 len = sprint_status48(s, status, 1);
4235                 if (len) {
4236                         s[len] = '\n';
4237                         s[len + 1] = '\0';
4238                         out2str(s);
4239                 }
4240         }
4241         return pid;
4242 }
4243
4244 #if JOBS
4245 static void
4246 showjob(struct job *jp, int mode)
4247 {
4248         struct procstat *ps;
4249         struct procstat *psend;
4250         int col;
4251         int indent_col;
4252         char s[16 + 16 + 48];
4253         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4254
4255         ps = jp->ps;
4256
4257         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4258                 /* just output process (group) id of pipeline */
4259                 fprintf(out, "%d\n", ps->ps_pid);
4260                 return;
4261         }
4262
4263         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4264         indent_col = col;
4265
4266         if (jp == curjob)
4267                 s[col - 3] = '+';
4268         else if (curjob && jp == curjob->prev_job)
4269                 s[col - 3] = '-';
4270
4271         if (mode & SHOW_PIDS)
4272                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4273
4274         psend = ps + jp->nprocs;
4275
4276         if (jp->state == JOBRUNNING) {
4277                 strcpy(s + col, "Running");
4278                 col += sizeof("Running") - 1;
4279         } else {
4280                 int status = psend[-1].ps_status;
4281                 if (jp->state == JOBSTOPPED)
4282                         status = jp->stopstatus;
4283                 col += sprint_status48(s + col, status, 0);
4284         }
4285         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4286
4287         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4288          * or prints several "PID             | <cmdN>" lines,
4289          * depending on SHOW_PIDS bit.
4290          * We do not print status of individual processes
4291          * between PID and <cmdN>. bash does it, but not very well:
4292          * first line shows overall job status, not process status,
4293          * making it impossible to know 1st process status.
4294          */
4295         goto start;
4296         do {
4297                 /* for each process */
4298                 s[0] = '\0';
4299                 col = 33;
4300                 if (mode & SHOW_PIDS)
4301                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4302  start:
4303                 fprintf(out, "%s%*c%s%s",
4304                                 s,
4305                                 33 - col >= 0 ? 33 - col : 0, ' ',
4306                                 ps == jp->ps ? "" : "| ",
4307                                 ps->ps_cmd
4308                 );
4309         } while (++ps != psend);
4310         newline_and_flush(out);
4311
4312         jp->changed = 0;
4313
4314         if (jp->state == JOBDONE) {
4315                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4316                 freejob(jp);
4317         }
4318 }
4319
4320 /*
4321  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4322  * statuses have changed since the last call to showjobs.
4323  */
4324 static void
4325 showjobs(int mode)
4326 {
4327         struct job *jp;
4328
4329         TRACE(("showjobs(0x%x) called\n", mode));
4330
4331         /* Handle all finished jobs */
4332         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4333                 continue;
4334
4335         for (jp = curjob; jp; jp = jp->prev_job) {
4336                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4337                         showjob(jp, mode);
4338                 }
4339         }
4340 }
4341
4342 static int FAST_FUNC
4343 jobscmd(int argc UNUSED_PARAM, char **argv)
4344 {
4345         int mode, m;
4346
4347         mode = 0;
4348         while ((m = nextopt("lp")) != '\0') {
4349                 if (m == 'l')
4350                         mode |= SHOW_PIDS;
4351                 else
4352                         mode |= SHOW_ONLY_PGID;
4353         }
4354
4355         argv = argptr;
4356         if (*argv) {
4357                 do
4358                         showjob(getjob(*argv, 0), mode);
4359                 while (*++argv);
4360         } else {
4361                 showjobs(mode);
4362         }
4363
4364         return 0;
4365 }
4366 #endif /* JOBS */
4367
4368 /* Called only on finished or stopped jobs (no members are running) */
4369 static int
4370 getstatus(struct job *job)
4371 {
4372         int status;
4373         int retval;
4374         struct procstat *ps;
4375
4376         /* Fetch last member's status */
4377         ps = job->ps + job->nprocs - 1;
4378         status = ps->ps_status;
4379         if (pipefail) {
4380                 /* "set -o pipefail" mode: use last _nonzero_ status */
4381                 while (status == 0 && --ps >= job->ps)
4382                         status = ps->ps_status;
4383         }
4384
4385         retval = WEXITSTATUS(status);
4386         if (!WIFEXITED(status)) {
4387 #if JOBS
4388                 retval = WSTOPSIG(status);
4389                 if (!WIFSTOPPED(status))
4390 #endif
4391                 {
4392                         /* XXX: limits number of signals */
4393                         retval = WTERMSIG(status);
4394 #if JOBS
4395                         if (retval == SIGINT)
4396                                 job->sigint = 1;
4397 #endif
4398                 }
4399                 retval += 128;
4400         }
4401         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4402                 jobno(job), job->nprocs, status, retval));
4403         return retval;
4404 }
4405
4406 static int FAST_FUNC
4407 waitcmd(int argc UNUSED_PARAM, char **argv)
4408 {
4409         struct job *job;
4410         int retval;
4411         struct job *jp;
4412
4413         nextopt(nullstr);
4414         retval = 0;
4415
4416         argv = argptr;
4417         if (!*argv) {
4418                 /* wait for all jobs */
4419                 for (;;) {
4420                         jp = curjob;
4421                         while (1) {
4422                                 if (!jp) /* no running procs */
4423                                         goto ret;
4424                                 if (jp->state == JOBRUNNING)
4425                                         break;
4426                                 jp->waited = 1;
4427                                 jp = jp->prev_job;
4428                         }
4429         /* man bash:
4430          * "When bash is waiting for an asynchronous command via
4431          * the wait builtin, the reception of a signal for which a trap
4432          * has been set will cause the wait builtin to return immediately
4433          * with an exit status greater than 128, immediately after which
4434          * the trap is executed."
4435          */
4436                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4437         /* if child sends us a signal *and immediately exits*,
4438          * dowait() returns pid > 0. Check this case,
4439          * not "if (dowait() < 0)"!
4440          */
4441                         if (pending_sig)
4442                                 goto sigout;
4443                 }
4444         }
4445
4446         retval = 127;
4447         do {
4448                 if (**argv != '%') {
4449                         pid_t pid = number(*argv);
4450                         job = curjob;
4451                         while (1) {
4452                                 if (!job)
4453                                         goto repeat;
4454                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4455                                         break;
4456                                 job = job->prev_job;
4457                         }
4458                 } else {
4459                         job = getjob(*argv, 0);
4460                 }
4461                 /* loop until process terminated or stopped */
4462                 while (job->state == JOBRUNNING) {
4463                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4464                         if (pending_sig)
4465                                 goto sigout;
4466                 }
4467                 job->waited = 1;
4468                 retval = getstatus(job);
4469  repeat: ;
4470         } while (*++argv);
4471
4472  ret:
4473         return retval;
4474  sigout:
4475         retval = 128 + pending_sig;
4476         return retval;
4477 }
4478
4479 static struct job *
4480 growjobtab(void)
4481 {
4482         size_t len;
4483         ptrdiff_t offset;
4484         struct job *jp, *jq;
4485
4486         len = njobs * sizeof(*jp);
4487         jq = jobtab;
4488         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4489
4490         offset = (char *)jp - (char *)jq;
4491         if (offset) {
4492                 /* Relocate pointers */
4493                 size_t l = len;
4494
4495                 jq = (struct job *)((char *)jq + l);
4496                 while (l) {
4497                         l -= sizeof(*jp);
4498                         jq--;
4499 #define joff(p) ((struct job *)((char *)(p) + l))
4500 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4501                         if (joff(jp)->ps == &jq->ps0)
4502                                 jmove(joff(jp)->ps);
4503                         if (joff(jp)->prev_job)
4504                                 jmove(joff(jp)->prev_job);
4505                 }
4506                 if (curjob)
4507                         jmove(curjob);
4508 #undef joff
4509 #undef jmove
4510         }
4511
4512         njobs += 4;
4513         jobtab = jp;
4514         jp = (struct job *)((char *)jp + len);
4515         jq = jp + 3;
4516         do {
4517                 jq->used = 0;
4518         } while (--jq >= jp);
4519         return jp;
4520 }
4521
4522 /*
4523  * Return a new job structure.
4524  * Called with interrupts off.
4525  */
4526 static struct job *
4527 makejob(/*union node *node,*/ int nprocs)
4528 {
4529         int i;
4530         struct job *jp;
4531
4532         for (i = njobs, jp = jobtab; ; jp++) {
4533                 if (--i < 0) {
4534                         jp = growjobtab();
4535                         break;
4536                 }
4537                 if (jp->used == 0)
4538                         break;
4539                 if (jp->state != JOBDONE || !jp->waited)
4540                         continue;
4541 #if JOBS
4542                 if (doing_jobctl)
4543                         continue;
4544 #endif
4545                 freejob(jp);
4546                 break;
4547         }
4548         memset(jp, 0, sizeof(*jp));
4549 #if JOBS
4550         /* jp->jobctl is a bitfield.
4551          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4552         if (doing_jobctl)
4553                 jp->jobctl = 1;
4554 #endif
4555         jp->prev_job = curjob;
4556         curjob = jp;
4557         jp->used = 1;
4558         jp->ps = &jp->ps0;
4559         if (nprocs > 1) {
4560                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4561         }
4562         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4563                                 jobno(jp)));
4564         return jp;
4565 }
4566
4567 #if JOBS
4568 /*
4569  * Return a string identifying a command (to be printed by the
4570  * jobs command).
4571  */
4572 static char *cmdnextc;
4573
4574 static void
4575 cmdputs(const char *s)
4576 {
4577         static const char vstype[VSTYPE + 1][3] = {
4578                 "", "}", "-", "+", "?", "=",
4579                 "%", "%%", "#", "##"
4580                 IF_BASH_SUBSTR(, ":")
4581                 IF_BASH_PATTERN_SUBST(, "/", "//")
4582         };
4583
4584         const char *p, *str;
4585         char cc[2];
4586         char *nextc;
4587         unsigned char c;
4588         unsigned char subtype = 0;
4589         int quoted = 0;
4590
4591         cc[1] = '\0';
4592         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4593         p = s;
4594         while ((c = *p++) != '\0') {
4595                 str = NULL;
4596                 switch (c) {
4597                 case CTLESC:
4598                         c = *p++;
4599                         break;
4600                 case CTLVAR:
4601                         subtype = *p++;
4602                         if ((subtype & VSTYPE) == VSLENGTH)
4603                                 str = "${#";
4604                         else
4605                                 str = "${";
4606                         goto dostr;
4607                 case CTLENDVAR:
4608                         str = "\"}" + !(quoted & 1);
4609                         quoted >>= 1;
4610                         subtype = 0;
4611                         goto dostr;
4612                 case CTLBACKQ:
4613                         str = "$(...)";
4614                         goto dostr;
4615 #if ENABLE_FEATURE_SH_MATH
4616                 case CTLARI:
4617                         str = "$((";
4618                         goto dostr;
4619                 case CTLENDARI:
4620                         str = "))";
4621                         goto dostr;
4622 #endif
4623                 case CTLQUOTEMARK:
4624                         quoted ^= 1;
4625                         c = '"';
4626                         break;
4627                 case '=':
4628                         if (subtype == 0)
4629                                 break;
4630                         if ((subtype & VSTYPE) != VSNORMAL)
4631                                 quoted <<= 1;
4632                         str = vstype[subtype & VSTYPE];
4633                         if (subtype & VSNUL)
4634                                 c = ':';
4635                         else
4636                                 goto checkstr;
4637                         break;
4638                 case '\'':
4639                 case '\\':
4640                 case '"':
4641                 case '$':
4642                         /* These can only happen inside quotes */
4643                         cc[0] = c;
4644                         str = cc;
4645                         c = '\\';
4646                         break;
4647                 default:
4648                         break;
4649                 }
4650                 USTPUTC(c, nextc);
4651  checkstr:
4652                 if (!str)
4653                         continue;
4654  dostr:
4655                 while ((c = *str++) != '\0') {
4656                         USTPUTC(c, nextc);
4657                 }
4658         } /* while *p++ not NUL */
4659
4660         if (quoted & 1) {
4661                 USTPUTC('"', nextc);
4662         }
4663         *nextc = 0;
4664         cmdnextc = nextc;
4665 }
4666
4667 /* cmdtxt() and cmdlist() call each other */
4668 static void cmdtxt(union node *n);
4669
4670 static void
4671 cmdlist(union node *np, int sep)
4672 {
4673         for (; np; np = np->narg.next) {
4674                 if (!sep)
4675                         cmdputs(" ");
4676                 cmdtxt(np);
4677                 if (sep && np->narg.next)
4678                         cmdputs(" ");
4679         }
4680 }
4681
4682 static void
4683 cmdtxt(union node *n)
4684 {
4685         union node *np;
4686         struct nodelist *lp;
4687         const char *p;
4688
4689         if (!n)
4690                 return;
4691         switch (n->type) {
4692         default:
4693 #if DEBUG
4694                 abort();
4695 #endif
4696         case NPIPE:
4697                 lp = n->npipe.cmdlist;
4698                 for (;;) {
4699                         cmdtxt(lp->n);
4700                         lp = lp->next;
4701                         if (!lp)
4702                                 break;
4703                         cmdputs(" | ");
4704                 }
4705                 break;
4706         case NSEMI:
4707                 p = "; ";
4708                 goto binop;
4709         case NAND:
4710                 p = " && ";
4711                 goto binop;
4712         case NOR:
4713                 p = " || ";
4714  binop:
4715                 cmdtxt(n->nbinary.ch1);
4716                 cmdputs(p);
4717                 n = n->nbinary.ch2;
4718                 goto donode;
4719         case NREDIR:
4720         case NBACKGND:
4721                 n = n->nredir.n;
4722                 goto donode;
4723         case NNOT:
4724                 cmdputs("!");
4725                 n = n->nnot.com;
4726  donode:
4727                 cmdtxt(n);
4728                 break;
4729         case NIF:
4730                 cmdputs("if ");
4731                 cmdtxt(n->nif.test);
4732                 cmdputs("; then ");
4733                 if (n->nif.elsepart) {
4734                         cmdtxt(n->nif.ifpart);
4735                         cmdputs("; else ");
4736                         n = n->nif.elsepart;
4737                 } else {
4738                         n = n->nif.ifpart;
4739                 }
4740                 p = "; fi";
4741                 goto dotail;
4742         case NSUBSHELL:
4743                 cmdputs("(");
4744                 n = n->nredir.n;
4745                 p = ")";
4746                 goto dotail;
4747         case NWHILE:
4748                 p = "while ";
4749                 goto until;
4750         case NUNTIL:
4751                 p = "until ";
4752  until:
4753                 cmdputs(p);
4754                 cmdtxt(n->nbinary.ch1);
4755                 n = n->nbinary.ch2;
4756                 p = "; done";
4757  dodo:
4758                 cmdputs("; do ");
4759  dotail:
4760                 cmdtxt(n);
4761                 goto dotail2;
4762         case NFOR:
4763                 cmdputs("for ");
4764                 cmdputs(n->nfor.var);
4765                 cmdputs(" in ");
4766                 cmdlist(n->nfor.args, 1);
4767                 n = n->nfor.body;
4768                 p = "; done";
4769                 goto dodo;
4770         case NDEFUN:
4771                 cmdputs(n->narg.text);
4772                 p = "() { ... }";
4773                 goto dotail2;
4774         case NCMD:
4775                 cmdlist(n->ncmd.args, 1);
4776                 cmdlist(n->ncmd.redirect, 0);
4777                 break;
4778         case NARG:
4779                 p = n->narg.text;
4780  dotail2:
4781                 cmdputs(p);
4782                 break;
4783         case NHERE:
4784         case NXHERE:
4785                 p = "<<...";
4786                 goto dotail2;
4787         case NCASE:
4788                 cmdputs("case ");
4789                 cmdputs(n->ncase.expr->narg.text);
4790                 cmdputs(" in ");
4791                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4792                         cmdtxt(np->nclist.pattern);
4793                         cmdputs(") ");
4794                         cmdtxt(np->nclist.body);
4795                         cmdputs(";; ");
4796                 }
4797                 p = "esac";
4798                 goto dotail2;
4799         case NTO:
4800                 p = ">";
4801                 goto redir;
4802         case NCLOBBER:
4803                 p = ">|";
4804                 goto redir;
4805         case NAPPEND:
4806                 p = ">>";
4807                 goto redir;
4808 #if BASH_REDIR_OUTPUT
4809         case NTO2:
4810 #endif
4811         case NTOFD:
4812                 p = ">&";
4813                 goto redir;
4814         case NFROM:
4815                 p = "<";
4816                 goto redir;
4817         case NFROMFD:
4818                 p = "<&";
4819                 goto redir;
4820         case NFROMTO:
4821                 p = "<>";
4822  redir:
4823                 cmdputs(utoa(n->nfile.fd));
4824                 cmdputs(p);
4825                 if (n->type == NTOFD || n->type == NFROMFD) {
4826                         cmdputs(utoa(n->ndup.dupfd));
4827                         break;
4828                 }
4829                 n = n->nfile.fname;
4830                 goto donode;
4831         }
4832 }
4833
4834 static char *
4835 commandtext(union node *n)
4836 {
4837         char *name;
4838
4839         STARTSTACKSTR(cmdnextc);
4840         cmdtxt(n);
4841         name = stackblock();
4842         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4843         return ckstrdup(name);
4844 }
4845 #endif /* JOBS */
4846
4847 /*
4848  * Fork off a subshell.  If we are doing job control, give the subshell its
4849  * own process group.  Jp is a job structure that the job is to be added to.
4850  * N is the command that will be evaluated by the child.  Both jp and n may
4851  * be NULL.  The mode parameter can be one of the following:
4852  *      FORK_FG - Fork off a foreground process.
4853  *      FORK_BG - Fork off a background process.
4854  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4855  *                   process group even if job control is on.
4856  *
4857  * When job control is turned off, background processes have their standard
4858  * input redirected to /dev/null (except for the second and later processes
4859  * in a pipeline).
4860  *
4861  * Called with interrupts off.
4862  */
4863 /*
4864  * Clear traps on a fork.
4865  */
4866 static void
4867 clear_traps(void)
4868 {
4869         char **tp;
4870
4871         INT_OFF;
4872         for (tp = trap; tp < &trap[NSIG]; tp++) {
4873                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4874                         if (trap_ptr == trap)
4875                                 free(*tp);
4876                         /* else: it "belongs" to trap_ptr vector, don't free */
4877                         *tp = NULL;
4878                         if ((tp - trap) != 0)
4879                                 setsignal(tp - trap);
4880                 }
4881         }
4882         may_have_traps = 0;
4883         INT_ON;
4884 }
4885
4886 /* Lives far away from here, needed for forkchild */
4887 static void closescript(void);
4888
4889 /* Called after fork(), in child */
4890 /* jp and n are NULL when called by openhere() for heredoc support */
4891 static NOINLINE void
4892 forkchild(struct job *jp, union node *n, int mode)
4893 {
4894         int oldlvl;
4895
4896         TRACE(("Child shell %d\n", getpid()));
4897         oldlvl = shlvl;
4898         shlvl++;
4899
4900         /* man bash: "Non-builtin commands run by bash have signal handlers
4901          * set to the values inherited by the shell from its parent".
4902          * Do we do it correctly? */
4903
4904         closescript();
4905
4906         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4907          && n && n->type == NCMD        /* is it single cmd? */
4908         /* && n->ncmd.args->type == NARG - always true? */
4909          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4910          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4911         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4912         ) {
4913                 TRACE(("Trap hack\n"));
4914                 /* Awful hack for `trap` or $(trap).
4915                  *
4916                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4917                  * contains an example where "trap" is executed in a subshell:
4918                  *
4919                  * save_traps=$(trap)
4920                  * ...
4921                  * eval "$save_traps"
4922                  *
4923                  * Standard does not say that "trap" in subshell shall print
4924                  * parent shell's traps. It only says that its output
4925                  * must have suitable form, but then, in the above example
4926                  * (which is not supposed to be normative), it implies that.
4927                  *
4928                  * bash (and probably other shell) does implement it
4929                  * (traps are reset to defaults, but "trap" still shows them),
4930                  * but as a result, "trap" logic is hopelessly messed up:
4931                  *
4932                  * # trap
4933                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4934                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4935                  * # true | trap   <--- trap is in subshell - no output (ditto)
4936                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4937                  * trap -- 'echo Ho' SIGWINCH
4938                  * # echo `(trap)`         <--- in subshell in subshell - output
4939                  * trap -- 'echo Ho' SIGWINCH
4940                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4941                  * trap -- 'echo Ho' SIGWINCH
4942                  *
4943                  * The rules when to forget and when to not forget traps
4944                  * get really complex and nonsensical.
4945                  *
4946                  * Our solution: ONLY bare $(trap) or `trap` is special.
4947                  */
4948                 /* Save trap handler strings for trap builtin to print */
4949                 trap_ptr = xmemdup(trap, sizeof(trap));
4950                 /* Fall through into clearing traps */
4951         }
4952         clear_traps();
4953 #if JOBS
4954         /* do job control only in root shell */
4955         doing_jobctl = 0;
4956         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4957                 pid_t pgrp;
4958
4959                 if (jp->nprocs == 0)
4960                         pgrp = getpid();
4961                 else
4962                         pgrp = jp->ps[0].ps_pid;
4963                 /* this can fail because we are doing it in the parent also */
4964                 setpgid(0, pgrp);
4965                 if (mode == FORK_FG)
4966                         xtcsetpgrp(ttyfd, pgrp);
4967                 setsignal(SIGTSTP);
4968                 setsignal(SIGTTOU);
4969         } else
4970 #endif
4971         if (mode == FORK_BG) {
4972                 /* man bash: "When job control is not in effect,
4973                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4974                 ignoresig(SIGINT);
4975                 ignoresig(SIGQUIT);
4976                 if (jp->nprocs == 0) {
4977                         close(0);
4978                         if (open(bb_dev_null, O_RDONLY) != 0)
4979                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4980                 }
4981         }
4982         if (oldlvl == 0) {
4983                 if (iflag) { /* why if iflag only? */
4984                         setsignal(SIGINT);
4985                         setsignal(SIGTERM);
4986                 }
4987                 /* man bash:
4988                  * "In all cases, bash ignores SIGQUIT. Non-builtin
4989                  * commands run by bash have signal handlers
4990                  * set to the values inherited by the shell
4991                  * from its parent".
4992                  * Take care of the second rule: */
4993                 setsignal(SIGQUIT);
4994         }
4995 #if JOBS
4996         if (n && n->type == NCMD
4997          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
4998         ) {
4999                 TRACE(("Job hack\n"));
5000                 /* "jobs": we do not want to clear job list for it,
5001                  * instead we remove only _its_ own_ job from job list.
5002                  * This makes "jobs .... | cat" more useful.
5003                  */
5004                 freejob(curjob);
5005                 return;
5006         }
5007 #endif
5008         for (jp = curjob; jp; jp = jp->prev_job)
5009                 freejob(jp);
5010         jobless = 0;
5011 }
5012
5013 /* Called after fork(), in parent */
5014 #if !JOBS
5015 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5016 #endif
5017 static void
5018 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5019 {
5020         TRACE(("In parent shell: child = %d\n", pid));
5021         if (!jp) {
5022                 /* jp is NULL when called by openhere() for heredoc support */
5023                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5024                         continue;
5025                 jobless++;
5026                 return;
5027         }
5028 #if JOBS
5029         if (mode != FORK_NOJOB && jp->jobctl) {
5030                 int pgrp;
5031
5032                 if (jp->nprocs == 0)
5033                         pgrp = pid;
5034                 else
5035                         pgrp = jp->ps[0].ps_pid;
5036                 /* This can fail because we are doing it in the child also */
5037                 setpgid(pid, pgrp);
5038         }
5039 #endif
5040         if (mode == FORK_BG) {
5041                 backgndpid = pid;               /* set $! */
5042                 set_curjob(jp, CUR_RUNNING);
5043         }
5044         if (jp) {
5045                 struct procstat *ps = &jp->ps[jp->nprocs++];
5046                 ps->ps_pid = pid;
5047                 ps->ps_status = -1;
5048                 ps->ps_cmd = nullstr;
5049 #if JOBS
5050                 if (doing_jobctl && n)
5051                         ps->ps_cmd = commandtext(n);
5052 #endif
5053         }
5054 }
5055
5056 /* jp and n are NULL when called by openhere() for heredoc support */
5057 static int
5058 forkshell(struct job *jp, union node *n, int mode)
5059 {
5060         int pid;
5061
5062         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5063         pid = fork();
5064         if (pid < 0) {
5065                 TRACE(("Fork failed, errno=%d", errno));
5066                 if (jp)
5067                         freejob(jp);
5068                 ash_msg_and_raise_error("can't fork");
5069         }
5070         if (pid == 0) {
5071                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5072                 forkchild(jp, n, mode);
5073         } else {
5074                 forkparent(jp, n, mode, pid);
5075         }
5076         return pid;
5077 }
5078
5079 /*
5080  * Wait for job to finish.
5081  *
5082  * Under job control we have the problem that while a child process
5083  * is running interrupts generated by the user are sent to the child
5084  * but not to the shell.  This means that an infinite loop started by
5085  * an interactive user may be hard to kill.  With job control turned off,
5086  * an interactive user may place an interactive program inside a loop.
5087  * If the interactive program catches interrupts, the user doesn't want
5088  * these interrupts to also abort the loop.  The approach we take here
5089  * is to have the shell ignore interrupt signals while waiting for a
5090  * foreground process to terminate, and then send itself an interrupt
5091  * signal if the child process was terminated by an interrupt signal.
5092  * Unfortunately, some programs want to do a bit of cleanup and then
5093  * exit on interrupt; unless these processes terminate themselves by
5094  * sending a signal to themselves (instead of calling exit) they will
5095  * confuse this approach.
5096  *
5097  * Called with interrupts off.
5098  */
5099 static int
5100 waitforjob(struct job *jp)
5101 {
5102         int st;
5103
5104         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5105
5106         INT_OFF;
5107         while (jp->state == JOBRUNNING) {
5108                 /* In non-interactive shells, we _can_ get
5109                  * a keyboard signal here and be EINTRed,
5110                  * but we just loop back, waiting for command to complete.
5111                  *
5112                  * man bash:
5113                  * "If bash is waiting for a command to complete and receives
5114                  * a signal for which a trap has been set, the trap
5115                  * will not be executed until the command completes."
5116                  *
5117                  * Reality is that even if trap is not set, bash
5118                  * will not act on the signal until command completes.
5119                  * Try this. sleep5intoff.c:
5120                  * #include <signal.h>
5121                  * #include <unistd.h>
5122                  * int main() {
5123                  *         sigset_t set;
5124                  *         sigemptyset(&set);
5125                  *         sigaddset(&set, SIGINT);
5126                  *         sigaddset(&set, SIGQUIT);
5127                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5128                  *         sleep(5);
5129                  *         return 0;
5130                  * }
5131                  * $ bash -c './sleep5intoff; echo hi'
5132                  * ^C^C^C^C <--- pressing ^C once a second
5133                  * $ _
5134                  * $ bash -c './sleep5intoff; echo hi'
5135                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5136                  * $ _
5137                  */
5138                 dowait(DOWAIT_BLOCK, jp);
5139         }
5140         INT_ON;
5141
5142         st = getstatus(jp);
5143 #if JOBS
5144         if (jp->jobctl) {
5145                 xtcsetpgrp(ttyfd, rootpid);
5146                 restore_tty_if_stopped_or_signaled(jp);
5147
5148                 /*
5149                  * This is truly gross.
5150                  * If we're doing job control, then we did a TIOCSPGRP which
5151                  * caused us (the shell) to no longer be in the controlling
5152                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5153                  * intuit from the subprocess exit status whether a SIGINT
5154                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5155                  */
5156                 if (jp->sigint) /* TODO: do the same with all signals */
5157                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5158         }
5159         if (jp->state == JOBDONE)
5160 #endif
5161                 freejob(jp);
5162         return st;
5163 }
5164
5165 /*
5166  * return 1 if there are stopped jobs, otherwise 0
5167  */
5168 static int
5169 stoppedjobs(void)
5170 {
5171         struct job *jp;
5172         int retval;
5173
5174         retval = 0;
5175         if (job_warning)
5176                 goto out;
5177         jp = curjob;
5178         if (jp && jp->state == JOBSTOPPED) {
5179                 out2str("You have stopped jobs.\n");
5180                 job_warning = 2;
5181                 retval++;
5182         }
5183  out:
5184         return retval;
5185 }
5186
5187
5188 /*
5189  * Code for dealing with input/output redirection.
5190  */
5191
5192 #undef EMPTY
5193 #undef CLOSED
5194 #define EMPTY -2                /* marks an unused slot in redirtab */
5195 #define CLOSED -3               /* marks a slot of previously-closed fd */
5196
5197 /*
5198  * Handle here documents.  Normally we fork off a process to write the
5199  * data to a pipe.  If the document is short, we can stuff the data in
5200  * the pipe without forking.
5201  */
5202 /* openhere needs this forward reference */
5203 static void expandhere(union node *arg, int fd);
5204 static int
5205 openhere(union node *redir)
5206 {
5207         int pip[2];
5208         size_t len = 0;
5209
5210         if (pipe(pip) < 0)
5211                 ash_msg_and_raise_error("pipe call failed");
5212         if (redir->type == NHERE) {
5213                 len = strlen(redir->nhere.doc->narg.text);
5214                 if (len <= PIPE_BUF) {
5215                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5216                         goto out;
5217                 }
5218         }
5219         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5220                 /* child */
5221                 close(pip[0]);
5222                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5223                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5224                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5225                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5226                 signal(SIGPIPE, SIG_DFL);
5227                 if (redir->type == NHERE)
5228                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5229                 else /* NXHERE */
5230                         expandhere(redir->nhere.doc, pip[1]);
5231                 _exit(EXIT_SUCCESS);
5232         }
5233  out:
5234         close(pip[1]);
5235         return pip[0];
5236 }
5237
5238 static int
5239 openredirect(union node *redir)
5240 {
5241         struct stat sb;
5242         char *fname;
5243         int f;
5244
5245         switch (redir->nfile.type) {
5246 /* Can't happen, our single caller does this itself */
5247 //      case NTOFD:
5248 //      case NFROMFD:
5249 //              return -1;
5250         case NHERE:
5251         case NXHERE:
5252                 return openhere(redir);
5253         }
5254
5255         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5256          * allocated space. Do it only when we know it is safe.
5257          */
5258         fname = redir->nfile.expfname;
5259
5260         switch (redir->nfile.type) {
5261         default:
5262 #if DEBUG
5263                 abort();
5264 #endif
5265         case NFROM:
5266                 f = open(fname, O_RDONLY);
5267                 if (f < 0)
5268                         goto eopen;
5269                 break;
5270         case NFROMTO:
5271                 f = open(fname, O_RDWR|O_CREAT, 0666);
5272                 if (f < 0)
5273                         goto ecreate;
5274                 break;
5275         case NTO:
5276 #if BASH_REDIR_OUTPUT
5277         case NTO2:
5278 #endif
5279                 /* Take care of noclobber mode. */
5280                 if (Cflag) {
5281                         if (stat(fname, &sb) < 0) {
5282                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5283                                 if (f < 0)
5284                                         goto ecreate;
5285                         } else if (!S_ISREG(sb.st_mode)) {
5286                                 f = open(fname, O_WRONLY, 0666);
5287                                 if (f < 0)
5288                                         goto ecreate;
5289                                 if (fstat(f, &sb) < 0 && S_ISREG(sb.st_mode)) {
5290                                         close(f);
5291                                         errno = EEXIST;
5292                                         goto ecreate;
5293                                 }
5294                         } else {
5295                                 errno = EEXIST;
5296                                 goto ecreate;
5297                         }
5298                         break;
5299                 }
5300                 /* FALLTHROUGH */
5301         case NCLOBBER:
5302                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5303                 if (f < 0)
5304                         goto ecreate;
5305                 break;
5306         case NAPPEND:
5307                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5308                 if (f < 0)
5309                         goto ecreate;
5310                 break;
5311         }
5312
5313         return f;
5314  ecreate:
5315         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5316  eopen:
5317         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5318 }
5319
5320 /*
5321  * Copy a file descriptor to be >= 10. Throws exception on error.
5322  */
5323 static int
5324 savefd(int from)
5325 {
5326         int newfd;
5327         int err;
5328
5329         newfd = fcntl(from, F_DUPFD, 10);
5330         err = newfd < 0 ? errno : 0;
5331         if (err != EBADF) {
5332                 if (err)
5333                         ash_msg_and_raise_perror("%d", from);
5334                 close(from);
5335                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5336         }
5337
5338         return newfd;
5339 }
5340 static int
5341 dup2_or_raise(int from, int to)
5342 {
5343         int newfd;
5344
5345         newfd = (from != to) ? dup2(from, to) : to;
5346         if (newfd < 0) {
5347                 /* Happens when source fd is not open: try "echo >&99" */
5348                 ash_msg_and_raise_perror("%d", from);
5349         }
5350         return newfd;
5351 }
5352
5353 /* Struct def and variable are moved down to the first usage site */
5354 struct two_fd_t {
5355         int orig, copy;
5356 };
5357 struct redirtab {
5358         struct redirtab *next;
5359         int pair_count;
5360         struct two_fd_t two_fd[];
5361 };
5362 #define redirlist (G_var.redirlist)
5363 enum {
5364         COPYFD_RESTORE = (int)~(INT_MAX),
5365 };
5366
5367 static int
5368 need_to_remember(struct redirtab *rp, int fd)
5369 {
5370         int i;
5371
5372         if (!rp) /* remembering was not requested */
5373                 return 0;
5374
5375         for (i = 0; i < rp->pair_count; i++) {
5376                 if (rp->two_fd[i].orig == fd) {
5377                         /* already remembered */
5378                         return 0;
5379                 }
5380         }
5381         return 1;
5382 }
5383
5384 /* "hidden" fd is a fd used to read scripts, or a copy of such */
5385 static int
5386 is_hidden_fd(struct redirtab *rp, int fd)
5387 {
5388         int i;
5389         struct parsefile *pf;
5390
5391         if (fd == -1)
5392                 return 0;
5393         /* Check open scripts' fds */
5394         pf = g_parsefile;
5395         while (pf) {
5396                 /* We skip pf_fd == 0 case because of the following case:
5397                  * $ ash  # running ash interactively
5398                  * $ . ./script.sh
5399                  * and in script.sh: "exec 9>&0".
5400                  * Even though top-level pf_fd _is_ 0,
5401                  * it's still ok to use it: "read" builtin uses it,
5402                  * why should we cripple "exec" builtin?
5403                  */
5404                 if (pf->pf_fd > 0 && fd == pf->pf_fd) {
5405                         return 1;
5406                 }
5407                 pf = pf->prev;
5408         }
5409
5410         if (!rp)
5411                 return 0;
5412         /* Check saved fds of redirects */
5413         fd |= COPYFD_RESTORE;
5414         for (i = 0; i < rp->pair_count; i++) {
5415                 if (rp->two_fd[i].copy == fd) {
5416                         return 1;
5417                 }
5418         }
5419         return 0;
5420 }
5421
5422 /*
5423  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5424  * old file descriptors are stashed away so that the redirection can be
5425  * undone by calling popredir.
5426  */
5427 /* flags passed to redirect */
5428 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5429 #define REDIR_SAVEFD2 03        /* set preverrout */
5430 static void
5431 redirect(union node *redir, int flags)
5432 {
5433         struct redirtab *sv;
5434         int sv_pos;
5435         int i;
5436         int fd;
5437         int newfd;
5438         int copied_fd2 = -1;
5439
5440         if (!redir)
5441                 return;
5442         sv = NULL;
5443         INT_OFF;
5444         if (flags & REDIR_PUSH)
5445                 sv = redirlist;
5446         sv_pos = 0;
5447         do {
5448                 int right_fd = -1;
5449                 fd = redir->nfile.fd;
5450                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5451                         right_fd = redir->ndup.dupfd;
5452                         //bb_error_msg("doing %d > %d", fd, right_fd);
5453                         /* redirect from/to same file descriptor? */
5454                         if (right_fd == fd)
5455                                 continue;
5456                         /* "echo >&10" and 10 is a fd opened to a sh script? */
5457                         if (is_hidden_fd(sv, right_fd)) {
5458                                 errno = EBADF; /* as if it is closed */
5459                                 ash_msg_and_raise_perror("%d", right_fd);
5460                         }
5461                         newfd = -1;
5462                 } else {
5463                         newfd = openredirect(redir); /* always >= 0 */
5464                         if (fd == newfd) {
5465                                 /* Descriptor wasn't open before redirect.
5466                                  * Mark it for close in the future */
5467                                 if (need_to_remember(sv, fd)) {
5468                                         goto remember_to_close;
5469                                 }
5470                                 continue;
5471                         }
5472                 }
5473 #if BASH_REDIR_OUTPUT
5474  redirect_more:
5475 #endif
5476                 if (need_to_remember(sv, fd)) {
5477                         /* Copy old descriptor */
5478                         /* Careful to not accidentally "save"
5479                          * to the same fd as right side fd in N>&M */
5480                         int minfd = right_fd < 10 ? 10 : right_fd + 1;
5481 #if defined(F_DUPFD_CLOEXEC)
5482                         i = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
5483 #else
5484                         i = fcntl(fd, F_DUPFD, minfd);
5485 #endif
5486                         if (i == -1) {
5487                                 i = errno;
5488                                 if (i != EBADF) {
5489                                         /* Strange error (e.g. "too many files" EMFILE?) */
5490                                         if (newfd >= 0)
5491                                                 close(newfd);
5492                                         errno = i;
5493                                         ash_msg_and_raise_perror("%d", fd);
5494                                         /* NOTREACHED */
5495                                 }
5496                                 /* EBADF: it is not open - good, remember to close it */
5497  remember_to_close:
5498                                 i = CLOSED;
5499                         } else { /* fd is open, save its copy */
5500 #if !defined(F_DUPFD_CLOEXEC)
5501                                 fcntl(i, F_SETFD, FD_CLOEXEC);
5502 #endif
5503                                 /* "exec fd>&-" should not close fds
5504                                  * which point to script file(s).
5505                                  * Force them to be restored afterwards */
5506                                 if (is_hidden_fd(sv, fd))
5507                                         i |= COPYFD_RESTORE;
5508                         }
5509                         if (fd == 2)
5510                                 copied_fd2 = i;
5511                         sv->two_fd[sv_pos].orig = fd;
5512                         sv->two_fd[sv_pos].copy = i;
5513                         sv_pos++;
5514                 }
5515                 if (newfd < 0) {
5516                         /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5517                         if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5518                                 /* Don't want to trigger debugging */
5519                                 if (fd != -1)
5520                                         close(fd);
5521                         } else {
5522                                 dup2_or_raise(redir->ndup.dupfd, fd);
5523                         }
5524                 } else if (fd != newfd) { /* move newfd to fd */
5525                         dup2_or_raise(newfd, fd);
5526 #if BASH_REDIR_OUTPUT
5527                         if (!(redir->nfile.type == NTO2 && fd == 2))
5528 #endif
5529                                 close(newfd);
5530                 }
5531 #if BASH_REDIR_OUTPUT
5532                 if (redir->nfile.type == NTO2 && fd == 1) {
5533                         /* We already redirected it to fd 1, now copy it to 2 */
5534                         newfd = 1;
5535                         fd = 2;
5536                         goto redirect_more;
5537                 }
5538 #endif
5539         } while ((redir = redir->nfile.next) != NULL);
5540
5541         INT_ON;
5542         if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5543                 preverrout_fd = copied_fd2;
5544 }
5545
5546 static int
5547 redirectsafe(union node *redir, int flags)
5548 {
5549         int err;
5550         volatile int saveint;
5551         struct jmploc *volatile savehandler = exception_handler;
5552         struct jmploc jmploc;
5553
5554         SAVE_INT(saveint);
5555         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5556         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5557         if (!err) {
5558                 exception_handler = &jmploc;
5559                 redirect(redir, flags);
5560         }
5561         exception_handler = savehandler;
5562         if (err && exception_type != EXERROR)
5563                 longjmp(exception_handler->loc, 1);
5564         RESTORE_INT(saveint);
5565         return err;
5566 }
5567
5568 static struct redirtab*
5569 pushredir(union node *redir)
5570 {
5571         struct redirtab *sv;
5572         int i;
5573
5574         if (!redir)
5575                 return redirlist;
5576
5577         i = 0;
5578         do {
5579                 i++;
5580 #if BASH_REDIR_OUTPUT
5581                 if (redir->nfile.type == NTO2)
5582                         i++;
5583 #endif
5584                 redir = redir->nfile.next;
5585         } while (redir);
5586
5587         sv = ckzalloc(sizeof(*sv) + i * sizeof(sv->two_fd[0]));
5588         sv->pair_count = i;
5589         while (--i >= 0)
5590                 sv->two_fd[i].orig = sv->two_fd[i].copy = EMPTY;
5591         sv->next = redirlist;
5592         redirlist = sv;
5593         return sv->next;
5594 }
5595
5596 /*
5597  * Undo the effects of the last redirection.
5598  */
5599 static void
5600 popredir(int drop, int restore)
5601 {
5602         struct redirtab *rp;
5603         int i;
5604
5605         if (redirlist == NULL)
5606                 return;
5607         INT_OFF;
5608         rp = redirlist;
5609         for (i = 0; i < rp->pair_count; i++) {
5610                 int fd = rp->two_fd[i].orig;
5611                 int copy = rp->two_fd[i].copy;
5612                 if (copy == CLOSED) {
5613                         if (!drop)
5614                                 close(fd);
5615                         continue;
5616                 }
5617                 if (copy != EMPTY) {
5618                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5619                                 copy &= ~COPYFD_RESTORE;
5620                                 /*close(fd);*/
5621                                 dup2_or_raise(copy, fd);
5622                         }
5623                         close(copy & ~COPYFD_RESTORE);
5624                 }
5625         }
5626         redirlist = rp->next;
5627         free(rp);
5628         INT_ON;
5629 }
5630
5631 static void
5632 unwindredir(struct redirtab *stop)
5633 {
5634         while (redirlist != stop)
5635                 popredir(/*drop:*/ 0, /*restore:*/ 0);
5636 }
5637
5638
5639 /* ============ Routines to expand arguments to commands
5640  *
5641  * We have to deal with backquotes, shell variables, and file metacharacters.
5642  */
5643
5644 #if ENABLE_FEATURE_SH_MATH
5645 static arith_t
5646 ash_arith(const char *s)
5647 {
5648         arith_state_t math_state;
5649         arith_t result;
5650
5651         math_state.lookupvar = lookupvar;
5652         math_state.setvar    = setvar0;
5653         //math_state.endofname = endofname;
5654
5655         INT_OFF;
5656         result = arith(&math_state, s);
5657         if (math_state.errmsg)
5658                 ash_msg_and_raise_error(math_state.errmsg);
5659         INT_ON;
5660
5661         return result;
5662 }
5663 #endif
5664
5665 /*
5666  * expandarg flags
5667  */
5668 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5669 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5670 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5671 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5672 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5673  * POSIX says for this case:
5674  *  Pathname expansion shall not be performed on the word by a
5675  *  non-interactive shell; an interactive shell may perform it, but shall
5676  *  do so only when the expansion would result in one word.
5677  * Currently, our code complies to the above rule by never globbing
5678  * redirection filenames.
5679  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5680  * (this means that on a typical Linux distro, bash almost always
5681  * performs globbing, and thus diverges from what we do).
5682  */
5683 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5684 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5685 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5686 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5687 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5688 /*
5689  * rmescape() flags
5690  */
5691 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5692 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5693 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5694 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5695 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5696
5697 /* Add CTLESC when necessary. */
5698 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT)
5699 /* Do not skip NUL characters. */
5700 #define QUOTES_KEEPNUL EXP_TILDE
5701
5702 /*
5703  * Structure specifying which parts of the string should be searched
5704  * for IFS characters.
5705  */
5706 struct ifsregion {
5707         struct ifsregion *next; /* next region in list */
5708         int begoff;             /* offset of start of region */
5709         int endoff;             /* offset of end of region */
5710         int nulonly;            /* search for nul bytes only */
5711 };
5712
5713 struct arglist {
5714         struct strlist *list;
5715         struct strlist **lastp;
5716 };
5717
5718 /* output of current string */
5719 static char *expdest;
5720 /* list of back quote expressions */
5721 static struct nodelist *argbackq;
5722 /* first struct in list of ifs regions */
5723 static struct ifsregion ifsfirst;
5724 /* last struct in list */
5725 static struct ifsregion *ifslastp;
5726 /* holds expanded arg list */
5727 static struct arglist exparg;
5728
5729 /*
5730  * Our own itoa().
5731  * cvtnum() is used even if math support is off (to prepare $? values and such).
5732  */
5733 static int
5734 cvtnum(arith_t num)
5735 {
5736         int len;
5737
5738         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5739         len = sizeof(arith_t) * 3;
5740         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5741         if (sizeof(arith_t) < 4) len += 2;
5742
5743         expdest = makestrspace(len, expdest);
5744         len = fmtstr(expdest, len, ARITH_FMT, num);
5745         STADJUST(len, expdest);
5746         return len;
5747 }
5748
5749 /*
5750  * Break the argument string into pieces based upon IFS and add the
5751  * strings to the argument list.  The regions of the string to be
5752  * searched for IFS characters have been stored by recordregion.
5753  */
5754 static void
5755 ifsbreakup(char *string, struct arglist *arglist)
5756 {
5757         struct ifsregion *ifsp;
5758         struct strlist *sp;
5759         char *start;
5760         char *p;
5761         char *q;
5762         const char *ifs, *realifs;
5763         int ifsspc;
5764         int nulonly;
5765
5766         start = string;
5767         if (ifslastp != NULL) {
5768                 ifsspc = 0;
5769                 nulonly = 0;
5770                 realifs = ifsset() ? ifsval() : defifs;
5771                 ifsp = &ifsfirst;
5772                 do {
5773                         p = string + ifsp->begoff;
5774                         nulonly = ifsp->nulonly;
5775                         ifs = nulonly ? nullstr : realifs;
5776                         ifsspc = 0;
5777                         while (p < string + ifsp->endoff) {
5778                                 q = p;
5779                                 if ((unsigned char)*p == CTLESC)
5780                                         p++;
5781                                 if (!strchr(ifs, *p)) {
5782                                         p++;
5783                                         continue;
5784                                 }
5785                                 if (!nulonly)
5786                                         ifsspc = (strchr(defifs, *p) != NULL);
5787                                 /* Ignore IFS whitespace at start */
5788                                 if (q == start && ifsspc) {
5789                                         p++;
5790                                         start = p;
5791                                         continue;
5792                                 }
5793                                 *q = '\0';
5794                                 sp = stzalloc(sizeof(*sp));
5795                                 sp->text = start;
5796                                 *arglist->lastp = sp;
5797                                 arglist->lastp = &sp->next;
5798                                 p++;
5799                                 if (!nulonly) {
5800                                         for (;;) {
5801                                                 if (p >= string + ifsp->endoff) {
5802                                                         break;
5803                                                 }
5804                                                 q = p;
5805                                                 if ((unsigned char)*p == CTLESC)
5806                                                         p++;
5807                                                 if (strchr(ifs, *p) == NULL) {
5808                                                         p = q;
5809                                                         break;
5810                                                 }
5811                                                 if (strchr(defifs, *p) == NULL) {
5812                                                         if (ifsspc) {
5813                                                                 p++;
5814                                                                 ifsspc = 0;
5815                                                         } else {
5816                                                                 p = q;
5817                                                                 break;
5818                                                         }
5819                                                 } else
5820                                                         p++;
5821                                         }
5822                                 }
5823                                 start = p;
5824                         } /* while */
5825                         ifsp = ifsp->next;
5826                 } while (ifsp != NULL);
5827                 if (nulonly)
5828                         goto add;
5829         }
5830
5831         if (!*start)
5832                 return;
5833
5834  add:
5835         sp = stzalloc(sizeof(*sp));
5836         sp->text = start;
5837         *arglist->lastp = sp;
5838         arglist->lastp = &sp->next;
5839 }
5840
5841 static void
5842 ifsfree(void)
5843 {
5844         struct ifsregion *p = ifsfirst.next;
5845
5846         if (!p)
5847                 goto out;
5848
5849         INT_OFF;
5850         do {
5851                 struct ifsregion *ifsp;
5852                 ifsp = p->next;
5853                 free(p);
5854                 p = ifsp;
5855         } while (p);
5856         ifsfirst.next = NULL;
5857         INT_ON;
5858  out:
5859         ifslastp = NULL;
5860 }
5861
5862 static size_t
5863 esclen(const char *start, const char *p)
5864 {
5865         size_t esc = 0;
5866
5867         while (p > start && (unsigned char)*--p == CTLESC) {
5868                 esc++;
5869         }
5870         return esc;
5871 }
5872
5873 /*
5874  * Remove any CTLESC characters from a string.
5875  */
5876 static char *
5877 rmescapes(char *str, int flag)
5878 {
5879         static const char qchars[] ALIGN1 = {
5880                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5881
5882         char *p, *q, *r;
5883         unsigned inquotes;
5884         unsigned protect_against_glob;
5885         unsigned globbing;
5886         IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5887
5888         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5889         if (!p)
5890                 return str;
5891
5892         q = p;
5893         r = str;
5894         if (flag & RMESCAPE_ALLOC) {
5895                 size_t len = p - str;
5896                 size_t fulllen = len + strlen(p) + 1;
5897
5898                 if (flag & RMESCAPE_GROW) {
5899                         int strloc = str - (char *)stackblock();
5900                         r = makestrspace(fulllen, expdest);
5901                         /* p and str may be invalidated by makestrspace */
5902                         str = (char *)stackblock() + strloc;
5903                         p = str + len;
5904                 } else if (flag & RMESCAPE_HEAP) {
5905                         r = ckmalloc(fulllen);
5906                 } else {
5907                         r = stalloc(fulllen);
5908                 }
5909                 q = r;
5910                 if (len > 0) {
5911                         q = (char *)mempcpy(q, str, len);
5912                 }
5913         }
5914
5915         inquotes = 0;
5916         globbing = flag & RMESCAPE_GLOB;
5917         protect_against_glob = globbing;
5918         while (*p) {
5919                 if ((unsigned char)*p == CTLQUOTEMARK) {
5920 // Note: both inquotes and protect_against_glob only affect whether
5921 // CTLESC,<ch> gets converted to <ch> or to \<ch>
5922                         inquotes = ~inquotes;
5923                         p++;
5924                         protect_against_glob = globbing;
5925                         continue;
5926                 }
5927                 if ((unsigned char)*p == CTLESC) {
5928                         p++;
5929 #if DEBUG
5930                         if (*p == '\0')
5931                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
5932 #endif
5933                         if (protect_against_glob) {
5934                                 /*
5935                                  * We used to trust glob() and fnmatch() to eat
5936                                  * superfluous escapes (\z where z has no
5937                                  * special meaning anyway). But this causes
5938                                  * bugs such as string of one greek letter rho
5939                                  * (unicode-encoded as two bytes "cf,81")
5940                                  * getting encoded as "cf,CTLESC,81"
5941                                  * and here, converted to "cf,\,81" -
5942                                  * which does not go well with some flavors
5943                                  * of fnmatch() in unicode locales
5944                                  * (for example, glibc <= 2.22).
5945                                  *
5946                                  * Lets add "\" only on the chars which need it.
5947                                  * Testcases for less obvious chars are shown.
5948                                  */
5949                                 if (*p == '*'
5950                                  || *p == '?'
5951                                  || *p == '['
5952                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
5953                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
5954                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
5955                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
5956                                 /* Some libc support [^negate], that's why "^" also needs love */
5957                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
5958                                 ) {
5959                                         *q++ = '\\';
5960                                 }
5961                         }
5962                 } else if (*p == '\\' && !inquotes) {
5963                         /* naked back slash */
5964                         protect_against_glob = 0;
5965                         goto copy;
5966                 }
5967 #if BASH_PATTERN_SUBST
5968                 else if (*p == '/' && slash) {
5969                         /* stop handling globbing and mark location of slash */
5970                         globbing = slash = 0;
5971                         *p = CTLESC;
5972                 }
5973 #endif
5974                 protect_against_glob = globbing;
5975  copy:
5976                 *q++ = *p++;
5977         }
5978         *q = '\0';
5979         if (flag & RMESCAPE_GROW) {
5980                 expdest = r;
5981                 STADJUST(q - r + 1, expdest);
5982         }
5983         return r;
5984 }
5985 #define pmatch(a, b) !fnmatch((a), (b), 0)
5986
5987 /*
5988  * Prepare a pattern for a expmeta (internal glob(3)) call.
5989  *
5990  * Returns an stalloced string.
5991  */
5992 static char *
5993 preglob(const char *pattern, int flag)
5994 {
5995         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
5996 }
5997
5998 /*
5999  * Put a string on the stack.
6000  */
6001 static void
6002 memtodest(const char *p, size_t len, int syntax, int quotes)
6003 {
6004         char *q;
6005
6006         if (!len)
6007                 return;
6008
6009         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
6010
6011         do {
6012                 unsigned char c = *p++;
6013                 if (c) {
6014                         if (quotes & QUOTES_ESC) {
6015                                 int n = SIT(c, syntax);
6016                                 if (n == CCTL
6017                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
6018                                      && n == CBACK
6019                                     )
6020                                 ) {
6021                                         USTPUTC(CTLESC, q);
6022                                 }
6023                         }
6024                 } else if (!(quotes & QUOTES_KEEPNUL))
6025                         continue;
6026                 USTPUTC(c, q);
6027         } while (--len);
6028
6029         expdest = q;
6030 }
6031
6032 static size_t
6033 strtodest(const char *p, int syntax, int quotes)
6034 {
6035         size_t len = strlen(p);
6036         memtodest(p, len, syntax, quotes);
6037         return len;
6038 }
6039
6040 /*
6041  * Record the fact that we have to scan this region of the
6042  * string for IFS characters.
6043  */
6044 static void
6045 recordregion(int start, int end, int nulonly)
6046 {
6047         struct ifsregion *ifsp;
6048
6049         if (ifslastp == NULL) {
6050                 ifsp = &ifsfirst;
6051         } else {
6052                 INT_OFF;
6053                 ifsp = ckzalloc(sizeof(*ifsp));
6054                 /*ifsp->next = NULL; - ckzalloc did it */
6055                 ifslastp->next = ifsp;
6056                 INT_ON;
6057         }
6058         ifslastp = ifsp;
6059         ifslastp->begoff = start;
6060         ifslastp->endoff = end;
6061         ifslastp->nulonly = nulonly;
6062 }
6063
6064 static void
6065 removerecordregions(int endoff)
6066 {
6067         if (ifslastp == NULL)
6068                 return;
6069
6070         if (ifsfirst.endoff > endoff) {
6071                 while (ifsfirst.next) {
6072                         struct ifsregion *ifsp;
6073                         INT_OFF;
6074                         ifsp = ifsfirst.next->next;
6075                         free(ifsfirst.next);
6076                         ifsfirst.next = ifsp;
6077                         INT_ON;
6078                 }
6079                 if (ifsfirst.begoff > endoff) {
6080                         ifslastp = NULL;
6081                 } else {
6082                         ifslastp = &ifsfirst;
6083                         ifsfirst.endoff = endoff;
6084                 }
6085                 return;
6086         }
6087
6088         ifslastp = &ifsfirst;
6089         while (ifslastp->next && ifslastp->next->begoff < endoff)
6090                 ifslastp = ifslastp->next;
6091         while (ifslastp->next) {
6092                 struct ifsregion *ifsp;
6093                 INT_OFF;
6094                 ifsp = ifslastp->next->next;
6095                 free(ifslastp->next);
6096                 ifslastp->next = ifsp;
6097                 INT_ON;
6098         }
6099         if (ifslastp->endoff > endoff)
6100                 ifslastp->endoff = endoff;
6101 }
6102
6103 static char *
6104 exptilde(char *startp, char *p, int flags)
6105 {
6106         unsigned char c;
6107         char *name;
6108         struct passwd *pw;
6109         const char *home;
6110         int quotes = flags & QUOTES_ESC;
6111
6112         name = p + 1;
6113
6114         while ((c = *++p) != '\0') {
6115                 switch (c) {
6116                 case CTLESC:
6117                         return startp;
6118                 case CTLQUOTEMARK:
6119                         return startp;
6120                 case ':':
6121                         if (flags & EXP_VARTILDE)
6122                                 goto done;
6123                         break;
6124                 case '/':
6125                 case CTLENDVAR:
6126                         goto done;
6127                 }
6128         }
6129  done:
6130         *p = '\0';
6131         if (*name == '\0') {
6132                 home = lookupvar("HOME");
6133         } else {
6134                 pw = getpwnam(name);
6135                 if (pw == NULL)
6136                         goto lose;
6137                 home = pw->pw_dir;
6138         }
6139         if (!home || !*home)
6140                 goto lose;
6141         *p = c;
6142         strtodest(home, SQSYNTAX, quotes);
6143         return p;
6144  lose:
6145         *p = c;
6146         return startp;
6147 }
6148
6149 /*
6150  * Execute a command inside back quotes.  If it's a builtin command, we
6151  * want to save its output in a block obtained from malloc.  Otherwise
6152  * we fork off a subprocess and get the output of the command via a pipe.
6153  * Should be called with interrupts off.
6154  */
6155 struct backcmd {                /* result of evalbackcmd */
6156         int fd;                 /* file descriptor to read from */
6157         int nleft;              /* number of chars in buffer */
6158         char *buf;              /* buffer */
6159         struct job *jp;         /* job structure for command */
6160 };
6161
6162 /* These forward decls are needed to use "eval" code for backticks handling: */
6163 /* flags in argument to evaltree */
6164 #define EV_EXIT    01           /* exit after evaluating tree */
6165 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6166 static int evaltree(union node *, int);
6167
6168 /* An evaltree() which is known to never return.
6169  * Used to use an alias:
6170  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6171  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6172  */
6173 static ALWAYS_INLINE NORETURN void
6174 evaltreenr(union node *n, int flags)
6175 {
6176         evaltree(n, flags);
6177         bb_unreachable(abort());
6178         /* NOTREACHED */
6179 }
6180
6181 static void FAST_FUNC
6182 evalbackcmd(union node *n, struct backcmd *result)
6183 {
6184         int pip[2];
6185         struct job *jp;
6186
6187         result->fd = -1;
6188         result->buf = NULL;
6189         result->nleft = 0;
6190         result->jp = NULL;
6191         if (n == NULL) {
6192                 goto out;
6193         }
6194
6195         if (pipe(pip) < 0)
6196                 ash_msg_and_raise_error("pipe call failed");
6197         jp = makejob(/*n,*/ 1);
6198         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6199                 /* child */
6200                 FORCE_INT_ON;
6201                 close(pip[0]);
6202                 if (pip[1] != 1) {
6203                         /*close(1);*/
6204                         dup2_or_raise(pip[1], 1);
6205                         close(pip[1]);
6206                 }
6207 /* TODO: eflag clearing makes the following not abort:
6208  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6209  * which is what bash does (unless it is in POSIX mode).
6210  * dash deleted "eflag = 0" line in the commit
6211  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6212  *  [EVAL] Don't clear eflag in evalbackcmd
6213  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6214  */
6215                 eflag = 0;
6216                 ifsfree();
6217                 evaltreenr(n, EV_EXIT);
6218                 /* NOTREACHED */
6219         }
6220         /* parent */
6221         close(pip[1]);
6222         result->fd = pip[0];
6223         result->jp = jp;
6224
6225  out:
6226         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6227                 result->fd, result->buf, result->nleft, result->jp));
6228 }
6229
6230 /*
6231  * Expand stuff in backwards quotes.
6232  */
6233 static void
6234 expbackq(union node *cmd, int flag)
6235 {
6236         struct backcmd in;
6237         int i;
6238         char buf[128];
6239         char *p;
6240         char *dest;
6241         int startloc;
6242         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6243         struct stackmark smark;
6244
6245         INT_OFF;
6246         startloc = expdest - (char *)stackblock();
6247         pushstackmark(&smark, startloc);
6248         evalbackcmd(cmd, &in);
6249         popstackmark(&smark);
6250
6251         p = in.buf;
6252         i = in.nleft;
6253         if (i == 0)
6254                 goto read;
6255         for (;;) {
6256                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6257  read:
6258                 if (in.fd < 0)
6259                         break;
6260                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6261                 TRACE(("expbackq: read returns %d\n", i));
6262                 if (i <= 0)
6263                         break;
6264                 p = buf;
6265         }
6266
6267         free(in.buf);
6268         if (in.fd >= 0) {
6269                 close(in.fd);
6270                 back_exitstatus = waitforjob(in.jp);
6271         }
6272         INT_ON;
6273
6274         /* Eat all trailing newlines */
6275         dest = expdest;
6276         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6277                 STUNPUTC(dest);
6278         expdest = dest;
6279
6280         if (!(flag & EXP_QUOTED))
6281                 recordregion(startloc, dest - (char *)stackblock(), 0);
6282         TRACE(("evalbackq: size:%d:'%.*s'\n",
6283                 (int)((dest - (char *)stackblock()) - startloc),
6284                 (int)((dest - (char *)stackblock()) - startloc),
6285                 stackblock() + startloc));
6286 }
6287
6288 #if ENABLE_FEATURE_SH_MATH
6289 /*
6290  * Expand arithmetic expression.  Backup to start of expression,
6291  * evaluate, place result in (backed up) result, adjust string position.
6292  */
6293 static void
6294 expari(int flag)
6295 {
6296         char *p, *start;
6297         int begoff;
6298         int len;
6299
6300         /* ifsfree(); */
6301
6302         /*
6303          * This routine is slightly over-complicated for
6304          * efficiency.  Next we scan backwards looking for the
6305          * start of arithmetic.
6306          */
6307         start = stackblock();
6308         p = expdest - 1;
6309         *p = '\0';
6310         p--;
6311         while (1) {
6312                 int esc;
6313
6314                 while ((unsigned char)*p != CTLARI) {
6315                         p--;
6316 #if DEBUG
6317                         if (p < start) {
6318                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6319                         }
6320 #endif
6321                 }
6322
6323                 esc = esclen(start, p);
6324                 if (!(esc % 2)) {
6325                         break;
6326                 }
6327
6328                 p -= esc + 1;
6329         }
6330
6331         begoff = p - start;
6332
6333         removerecordregions(begoff);
6334
6335         expdest = p;
6336
6337         if (flag & QUOTES_ESC)
6338                 rmescapes(p + 1, 0);
6339
6340         len = cvtnum(ash_arith(p + 1));
6341
6342         if (!(flag & EXP_QUOTED))
6343                 recordregion(begoff, begoff + len, 0);
6344 }
6345 #endif
6346
6347 /* argstr needs it */
6348 static char *evalvar(char *p, int flags);
6349
6350 /*
6351  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6352  * characters to allow for further processing.  Otherwise treat
6353  * $@ like $* since no splitting will be performed.
6354  */
6355 static void
6356 argstr(char *p, int flags)
6357 {
6358         static const char spclchars[] ALIGN1 = {
6359                 '=',
6360                 ':',
6361                 CTLQUOTEMARK,
6362                 CTLENDVAR,
6363                 CTLESC,
6364                 CTLVAR,
6365                 CTLBACKQ,
6366 #if ENABLE_FEATURE_SH_MATH
6367                 CTLENDARI,
6368 #endif
6369                 '\0'
6370         };
6371         const char *reject = spclchars;
6372         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6373         int inquotes;
6374         size_t length;
6375         int startloc;
6376
6377         if (!(flags & EXP_VARTILDE)) {
6378                 reject += 2;
6379         } else if (flags & EXP_VARTILDE2) {
6380                 reject++;
6381         }
6382         inquotes = 0;
6383         length = 0;
6384         if (flags & EXP_TILDE) {
6385                 char *q;
6386
6387                 flags &= ~EXP_TILDE;
6388  tilde:
6389                 q = p;
6390                 if (*q == '~')
6391                         p = exptilde(p, q, flags);
6392         }
6393  start:
6394         startloc = expdest - (char *)stackblock();
6395         for (;;) {
6396                 unsigned char c;
6397
6398                 length += strcspn(p + length, reject);
6399                 c = p[length];
6400                 if (c) {
6401                         if (!(c & 0x80)
6402                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6403                         ) {
6404                                 /* c == '=' || c == ':' || c == CTLENDARI */
6405                                 length++;
6406                         }
6407                 }
6408                 if (length > 0) {
6409                         int newloc;
6410                         expdest = stack_nputstr(p, length, expdest);
6411                         newloc = expdest - (char *)stackblock();
6412                         if (breakall && !inquotes && newloc > startloc) {
6413                                 recordregion(startloc, newloc, 0);
6414                         }
6415                         startloc = newloc;
6416                 }
6417                 p += length + 1;
6418                 length = 0;
6419
6420                 switch (c) {
6421                 case '\0':
6422                         goto breakloop;
6423                 case '=':
6424                         if (flags & EXP_VARTILDE2) {
6425                                 p--;
6426                                 continue;
6427                         }
6428                         flags |= EXP_VARTILDE2;
6429                         reject++;
6430                         /* fall through */
6431                 case ':':
6432                         /*
6433                          * sort of a hack - expand tildes in variable
6434                          * assignments (after the first '=' and after ':'s).
6435                          */
6436                         if (*--p == '~') {
6437                                 goto tilde;
6438                         }
6439                         continue;
6440                 }
6441
6442                 switch (c) {
6443                 case CTLENDVAR: /* ??? */
6444                         goto breakloop;
6445                 case CTLQUOTEMARK:
6446                         inquotes ^= EXP_QUOTED;
6447                         /* "$@" syntax adherence hack */
6448                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6449                                 p = evalvar(p + 1, flags | inquotes) + 1;
6450                                 goto start;
6451                         }
6452  addquote:
6453                         if (flags & QUOTES_ESC) {
6454                                 p--;
6455                                 length++;
6456                                 startloc++;
6457                         }
6458                         break;
6459                 case CTLESC:
6460                         startloc++;
6461                         length++;
6462
6463                         /*
6464                          * Quoted parameter expansion pattern: remove quote
6465                          * unless inside inner quotes or we have a literal
6466                          * backslash.
6467                          */
6468                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6469                             EXP_QPAT && *p != '\\')
6470                                 break;
6471
6472                         goto addquote;
6473                 case CTLVAR:
6474                         TRACE(("argstr: evalvar('%s')\n", p));
6475                         p = evalvar(p, flags | inquotes);
6476                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6477                         goto start;
6478                 case CTLBACKQ:
6479                         expbackq(argbackq->n, flags | inquotes);
6480                         argbackq = argbackq->next;
6481                         goto start;
6482 #if ENABLE_FEATURE_SH_MATH
6483                 case CTLENDARI:
6484                         p--;
6485                         expari(flags | inquotes);
6486                         goto start;
6487 #endif
6488                 }
6489         }
6490  breakloop: ;
6491 }
6492
6493 static char *
6494 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6495                 char *pattern, int quotes, int zero)
6496 {
6497         char *loc, *loc2;
6498         char c;
6499
6500         loc = startp;
6501         loc2 = rmesc;
6502         do {
6503                 int match;
6504                 const char *s = loc2;
6505
6506                 c = *loc2;
6507                 if (zero) {
6508                         *loc2 = '\0';
6509                         s = rmesc;
6510                 }
6511                 match = pmatch(pattern, s);
6512
6513                 *loc2 = c;
6514                 if (match)
6515                         return loc;
6516                 if (quotes && (unsigned char)*loc == CTLESC)
6517                         loc++;
6518                 loc++;
6519                 loc2++;
6520         } while (c);
6521         return NULL;
6522 }
6523
6524 static char *
6525 scanright(char *startp, char *rmesc, char *rmescend,
6526                 char *pattern, int quotes, int match_at_start)
6527 {
6528 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6529         int try2optimize = match_at_start;
6530 #endif
6531         int esc = 0;
6532         char *loc;
6533         char *loc2;
6534
6535         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6536          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6537          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6538          * Logic:
6539          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6540          * and on each iteration they go back two/one char until they reach the beginning.
6541          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6542          */
6543         /* TODO: document in what other circumstances we are called. */
6544
6545         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6546                 int match;
6547                 char c = *loc2;
6548                 const char *s = loc2;
6549                 if (match_at_start) {
6550                         *loc2 = '\0';
6551                         s = rmesc;
6552                 }
6553                 match = pmatch(pattern, s);
6554                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6555                 *loc2 = c;
6556                 if (match)
6557                         return loc;
6558 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6559                 if (try2optimize) {
6560                         /* Maybe we can optimize this:
6561                          * if pattern ends with unescaped *, we can avoid checking
6562                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6563                          * it won't match truncated "raw_value_of_" strings too.
6564                          */
6565                         unsigned plen = strlen(pattern);
6566                         /* Does it end with "*"? */
6567                         if (plen != 0 && pattern[--plen] == '*') {
6568                                 /* "xxxx*" is not escaped */
6569                                 /* "xxx\*" is escaped */
6570                                 /* "xx\\*" is not escaped */
6571                                 /* "x\\\*" is escaped */
6572                                 int slashes = 0;
6573                                 while (plen != 0 && pattern[--plen] == '\\')
6574                                         slashes++;
6575                                 if (!(slashes & 1))
6576                                         break; /* ends with unescaped "*" */
6577                         }
6578                         try2optimize = 0;
6579                 }
6580 #endif
6581                 loc--;
6582                 if (quotes) {
6583                         if (--esc < 0) {
6584                                 esc = esclen(startp, loc);
6585                         }
6586                         if (esc % 2) {
6587                                 esc--;
6588                                 loc--;
6589                         }
6590                 }
6591         }
6592         return NULL;
6593 }
6594
6595 static void varunset(const char *, const char *, const char *, int) NORETURN;
6596 static void
6597 varunset(const char *end, const char *var, const char *umsg, int varflags)
6598 {
6599         const char *msg;
6600         const char *tail;
6601
6602         tail = nullstr;
6603         msg = "parameter not set";
6604         if (umsg) {
6605                 if ((unsigned char)*end == CTLENDVAR) {
6606                         if (varflags & VSNUL)
6607                                 tail = " or null";
6608                 } else {
6609                         msg = umsg;
6610                 }
6611         }
6612         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6613 }
6614
6615 static const char *
6616 subevalvar(char *p, char *varname, int strloc, int subtype,
6617                 int startloc, int varflags, int flag)
6618 {
6619         struct nodelist *saveargbackq = argbackq;
6620         int quotes = flag & QUOTES_ESC;
6621         char *startp;
6622         char *loc;
6623         char *rmesc, *rmescend;
6624         char *str;
6625         int amount, resetloc;
6626         IF_BASH_PATTERN_SUBST(int workloc;)
6627         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6628         int zero;
6629         char *(*scan)(char*, char*, char*, char*, int, int);
6630
6631         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6632         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6633
6634         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6635                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0)
6636         );
6637         STPUTC('\0', expdest);
6638         argbackq = saveargbackq;
6639         startp = (char *)stackblock() + startloc;
6640
6641         switch (subtype) {
6642         case VSASSIGN:
6643                 setvar0(varname, startp);
6644                 amount = startp - expdest;
6645                 STADJUST(amount, expdest);
6646                 return startp;
6647
6648         case VSQUESTION:
6649                 varunset(p, varname, startp, varflags);
6650                 /* NOTREACHED */
6651
6652 #if BASH_SUBSTR
6653         case VSSUBSTR: {
6654                 int pos, len, orig_len;
6655                 char *colon;
6656
6657                 loc = str = stackblock() + strloc;
6658
6659 # if !ENABLE_FEATURE_SH_MATH
6660 #  define ash_arith number
6661 # endif
6662                 /* Read POS in ${var:POS:LEN} */
6663                 colon = strchr(loc, ':');
6664                 if (colon) *colon = '\0';
6665                 pos = ash_arith(loc);
6666                 if (colon) *colon = ':';
6667
6668                 /* Read LEN in ${var:POS:LEN} */
6669                 len = str - startp - 1;
6670                 /* *loc != '\0', guaranteed by parser */
6671                 if (quotes) {
6672                         char *ptr;
6673
6674                         /* Adjust the length by the number of escapes */
6675                         for (ptr = startp; ptr < (str - 1); ptr++) {
6676                                 if ((unsigned char)*ptr == CTLESC) {
6677                                         len--;
6678                                         ptr++;
6679                                 }
6680                         }
6681                 }
6682                 orig_len = len;
6683                 if (*loc++ == ':') {
6684                         /* ${var::LEN} */
6685                         len = ash_arith(loc);
6686                 } else {
6687                         /* Skip POS in ${var:POS:LEN} */
6688                         len = orig_len;
6689                         while (*loc && *loc != ':') {
6690                                 loc++;
6691                         }
6692                         if (*loc++ == ':') {
6693                                 len = ash_arith(loc);
6694                         }
6695                 }
6696 #  undef ash_arith
6697
6698                 if (pos < 0) {
6699                         /* ${VAR:$((-n)):l} starts n chars from the end */
6700                         pos = orig_len + pos;
6701                 }
6702                 if ((unsigned)pos >= orig_len) {
6703                         /* apart from obvious ${VAR:999999:l},
6704                          * covers ${VAR:$((-9999999)):l} - result is ""
6705                          * (bash compat)
6706                          */
6707                         pos = 0;
6708                         len = 0;
6709                 }
6710                 if (len < 0) {
6711                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6712                         len = (orig_len - pos) + len;
6713                 }
6714                 if ((unsigned)len > (orig_len - pos))
6715                         len = orig_len - pos;
6716
6717                 for (str = startp; pos; str++, pos--) {
6718                         if (quotes && (unsigned char)*str == CTLESC)
6719                                 str++;
6720                 }
6721                 for (loc = startp; len; len--) {
6722                         if (quotes && (unsigned char)*str == CTLESC)
6723                                 *loc++ = *str++;
6724                         *loc++ = *str++;
6725                 }
6726                 *loc = '\0';
6727                 amount = loc - expdest;
6728                 STADJUST(amount, expdest);
6729                 return loc;
6730         }
6731 #endif /* BASH_SUBSTR */
6732         }
6733
6734         resetloc = expdest - (char *)stackblock();
6735
6736 #if BASH_PATTERN_SUBST
6737         /* We'll comeback here if we grow the stack while handling
6738          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6739          * stack will need rebasing, and we'll need to remove our work
6740          * areas each time
6741          */
6742  restart:
6743 #endif
6744
6745         amount = expdest - ((char *)stackblock() + resetloc);
6746         STADJUST(-amount, expdest);
6747         startp = (char *)stackblock() + startloc;
6748
6749         rmesc = startp;
6750         rmescend = (char *)stackblock() + strloc;
6751         if (quotes) {
6752                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6753                 if (rmesc != startp) {
6754                         rmescend = expdest;
6755                         startp = (char *)stackblock() + startloc;
6756                 }
6757         }
6758         rmescend--;
6759         str = (char *)stackblock() + strloc;
6760         /*
6761          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6762          * The result is a_\_z_c (not a\_\_z_c)!
6763          *
6764          * The search pattern and replace string treat backslashes differently!
6765          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6766          * and string.  It's only used on the first call.
6767          */
6768         preglob(str, IF_BASH_PATTERN_SUBST(
6769                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6770                         RMESCAPE_SLASH : ) 0);
6771
6772 #if BASH_PATTERN_SUBST
6773         workloc = expdest - (char *)stackblock();
6774         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6775                 int len;
6776                 char *idx, *end;
6777
6778                 if (!repl) {
6779                         repl = strchr(str, CTLESC);
6780                         if (repl)
6781                                 *repl++ = '\0';
6782                         else
6783                                 repl = nullstr;
6784                 }
6785                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6786
6787                 /* If there's no pattern to match, return the expansion unmolested */
6788                 if (str[0] == '\0')
6789                         return NULL;
6790
6791                 len = 0;
6792                 idx = startp;
6793                 end = str - 1;
6794                 while (idx < end) {
6795  try_to_match:
6796                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6797                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6798                         if (!loc) {
6799                                 /* No match, advance */
6800                                 char *restart_detect = stackblock();
6801  skip_matching:
6802                                 STPUTC(*idx, expdest);
6803                                 if (quotes && (unsigned char)*idx == CTLESC) {
6804                                         idx++;
6805                                         len++;
6806                                         STPUTC(*idx, expdest);
6807                                 }
6808                                 if (stackblock() != restart_detect)
6809                                         goto restart;
6810                                 idx++;
6811                                 len++;
6812                                 rmesc++;
6813                                 /* continue; - prone to quadratic behavior, smarter code: */
6814                                 if (idx >= end)
6815                                         break;
6816                                 if (str[0] == '*') {
6817                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6818                                          * it would never match "ong_string" etc, no point in trying.
6819                                          */
6820                                         goto skip_matching;
6821                                 }
6822                                 goto try_to_match;
6823                         }
6824
6825                         if (subtype == VSREPLACEALL) {
6826                                 while (idx < loc) {
6827                                         if (quotes && (unsigned char)*idx == CTLESC)
6828                                                 idx++;
6829                                         idx++;
6830                                         rmesc++;
6831                                 }
6832                         } else {
6833                                 idx = loc;
6834                         }
6835
6836                         //bb_error_msg("repl:'%s'", repl);
6837                         for (loc = (char*)repl; *loc; loc++) {
6838                                 char *restart_detect = stackblock();
6839                                 if (quotes && *loc == '\\') {
6840                                         STPUTC(CTLESC, expdest);
6841                                         len++;
6842                                 }
6843                                 STPUTC(*loc, expdest);
6844                                 if (stackblock() != restart_detect)
6845                                         goto restart;
6846                                 len++;
6847                         }
6848
6849                         if (subtype == VSREPLACE) {
6850                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6851                                 while (*idx) {
6852                                         char *restart_detect = stackblock();
6853                                         STPUTC(*idx, expdest);
6854                                         if (stackblock() != restart_detect)
6855                                                 goto restart;
6856                                         len++;
6857                                         idx++;
6858                                 }
6859                                 break;
6860                         }
6861                 }
6862
6863                 /* We've put the replaced text into a buffer at workloc, now
6864                  * move it to the right place and adjust the stack.
6865                  */
6866                 STPUTC('\0', expdest);
6867                 startp = (char *)stackblock() + startloc;
6868                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6869                 //bb_error_msg("startp:'%s'", startp);
6870                 amount = expdest - (startp + len);
6871                 STADJUST(-amount, expdest);
6872                 return startp;
6873         }
6874 #endif /* BASH_PATTERN_SUBST */
6875
6876         subtype -= VSTRIMRIGHT;
6877 #if DEBUG
6878         if (subtype < 0 || subtype > 7)
6879                 abort();
6880 #endif
6881         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6882         zero = subtype >> 1;
6883         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6884         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6885
6886         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6887         if (loc) {
6888                 if (zero) {
6889                         memmove(startp, loc, str - loc);
6890                         loc = startp + (str - loc) - 1;
6891                 }
6892                 *loc = '\0';
6893                 amount = loc - expdest;
6894                 STADJUST(amount, expdest);
6895         }
6896         return loc;
6897 }
6898
6899 /*
6900  * Add the value of a specialized variable to the stack string.
6901  * name parameter (examples):
6902  * ash -c 'echo $1'      name:'1='
6903  * ash -c 'echo $qwe'    name:'qwe='
6904  * ash -c 'echo $$'      name:'$='
6905  * ash -c 'echo ${$}'    name:'$='
6906  * ash -c 'echo ${$##q}' name:'$=q'
6907  * ash -c 'echo ${#$}'   name:'$='
6908  * note: examples with bad shell syntax:
6909  * ash -c 'echo ${#$1}'  name:'$=1'
6910  * ash -c 'echo ${#1#}'  name:'1=#'
6911  */
6912 static NOINLINE ssize_t
6913 varvalue(char *name, int varflags, int flags, int *quotedp)
6914 {
6915         const char *p;
6916         int num;
6917         int i;
6918         ssize_t len = 0;
6919         int sep;
6920         int quoted = *quotedp;
6921         int subtype = varflags & VSTYPE;
6922         int discard = subtype == VSPLUS || subtype == VSLENGTH;
6923         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
6924         int syntax;
6925
6926         sep = (flags & EXP_FULL) << CHAR_BIT;
6927         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6928
6929         switch (*name) {
6930         case '$':
6931                 num = rootpid;
6932                 goto numvar;
6933         case '?':
6934                 num = exitstatus;
6935                 goto numvar;
6936         case '#':
6937                 num = shellparam.nparam;
6938                 goto numvar;
6939         case '!':
6940                 num = backgndpid;
6941                 if (num == 0)
6942                         return -1;
6943  numvar:
6944                 len = cvtnum(num);
6945                 goto check_1char_name;
6946         case '-':
6947                 expdest = makestrspace(NOPTS, expdest);
6948                 for (i = NOPTS - 1; i >= 0; i--) {
6949                         if (optlist[i]) {
6950                                 USTPUTC(optletters(i), expdest);
6951                                 len++;
6952                         }
6953                 }
6954  check_1char_name:
6955 #if 0
6956                 /* handles cases similar to ${#$1} */
6957                 if (name[2] != '\0')
6958                         raise_error_syntax("bad substitution");
6959 #endif
6960                 break;
6961         case '@':
6962                 if (quoted && sep)
6963                         goto param;
6964                 /* fall through */
6965         case '*': {
6966                 char **ap;
6967                 char sepc;
6968
6969                 if (quoted)
6970                         sep = 0;
6971                 sep |= ifsset() ? ifsval()[0] : ' ';
6972  param:
6973                 sepc = sep;
6974                 *quotedp = !sepc;
6975                 ap = shellparam.p;
6976                 if (!ap)
6977                         return -1;
6978                 while ((p = *ap++) != NULL) {
6979                         len += strtodest(p, syntax, quotes);
6980
6981                         if (*ap && sep) {
6982                                 len++;
6983                                 memtodest(&sepc, 1, syntax, quotes);
6984                         }
6985                 }
6986                 break;
6987         } /* case '*' */
6988         case '0':
6989         case '1':
6990         case '2':
6991         case '3':
6992         case '4':
6993         case '5':
6994         case '6':
6995         case '7':
6996         case '8':
6997         case '9':
6998                 num = atoi(name); /* number(name) fails on ${N#str} etc */
6999                 if (num < 0 || num > shellparam.nparam)
7000                         return -1;
7001                 p = num ? shellparam.p[num - 1] : arg0;
7002                 goto value;
7003         default:
7004                 /* NB: name has form "VAR=..." */
7005                 p = lookupvar(name);
7006  value:
7007                 if (!p)
7008                         return -1;
7009
7010                 len = strtodest(p, syntax, quotes);
7011 #if ENABLE_UNICODE_SUPPORT
7012                 if (subtype == VSLENGTH && len > 0) {
7013                         reinit_unicode_for_ash();
7014                         if (unicode_status == UNICODE_ON) {
7015                                 STADJUST(-len, expdest);
7016                                 discard = 0;
7017                                 len = unicode_strlen(p);
7018                         }
7019                 }
7020 #endif
7021                 break;
7022         }
7023
7024         if (discard)
7025                 STADJUST(-len, expdest);
7026         return len;
7027 }
7028
7029 /*
7030  * Expand a variable, and return a pointer to the next character in the
7031  * input string.
7032  */
7033 static char *
7034 evalvar(char *p, int flag)
7035 {
7036         char varflags;
7037         char subtype;
7038         int quoted;
7039         char easy;
7040         char *var;
7041         int patloc;
7042         int startloc;
7043         ssize_t varlen;
7044
7045         varflags = (unsigned char) *p++;
7046         subtype = varflags & VSTYPE;
7047
7048         if (!subtype)
7049                 raise_error_syntax("bad substitution");
7050
7051         quoted = flag & EXP_QUOTED;
7052         var = p;
7053         easy = (!quoted || (*var == '@' && shellparam.nparam));
7054         startloc = expdest - (char *)stackblock();
7055         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7056
7057  again:
7058         varlen = varvalue(var, varflags, flag, &quoted);
7059         if (varflags & VSNUL)
7060                 varlen--;
7061
7062         if (subtype == VSPLUS) {
7063                 varlen = -1 - varlen;
7064                 goto vsplus;
7065         }
7066
7067         if (subtype == VSMINUS) {
7068  vsplus:
7069                 if (varlen < 0) {
7070                         argstr(
7071                                 p,
7072                                 flag | EXP_TILDE | EXP_WORD
7073                         );
7074                         goto end;
7075                 }
7076                 goto record;
7077         }
7078
7079         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7080                 if (varlen >= 0)
7081                         goto record;
7082
7083                 subevalvar(p, var, 0, subtype, startloc, varflags,
7084                            flag & ~QUOTES_ESC);
7085                 varflags &= ~VSNUL;
7086                 /*
7087                  * Remove any recorded regions beyond
7088                  * start of variable
7089                  */
7090                 removerecordregions(startloc);
7091                 goto again;
7092         }
7093
7094         if (varlen < 0 && uflag)
7095                 varunset(p, var, 0, 0);
7096
7097         if (subtype == VSLENGTH) {
7098                 cvtnum(varlen > 0 ? varlen : 0);
7099                 goto record;
7100         }
7101
7102         if (subtype == VSNORMAL) {
7103  record:
7104                 if (!easy)
7105                         goto end;
7106                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7107                 goto end;
7108         }
7109
7110 #if DEBUG
7111         switch (subtype) {
7112         case VSTRIMLEFT:
7113         case VSTRIMLEFTMAX:
7114         case VSTRIMRIGHT:
7115         case VSTRIMRIGHTMAX:
7116 #if BASH_SUBSTR
7117         case VSSUBSTR:
7118 #endif
7119 #if BASH_PATTERN_SUBST
7120         case VSREPLACE:
7121         case VSREPLACEALL:
7122 #endif
7123                 break;
7124         default:
7125                 abort();
7126         }
7127 #endif
7128
7129         if (varlen >= 0) {
7130                 /*
7131                  * Terminate the string and start recording the pattern
7132                  * right after it
7133                  */
7134                 STPUTC('\0', expdest);
7135                 patloc = expdest - (char *)stackblock();
7136                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7137                                 startloc, varflags, flag)) {
7138                         int amount = expdest - (
7139                                 (char *)stackblock() + patloc - 1
7140                         );
7141                         STADJUST(-amount, expdest);
7142                 }
7143                 /* Remove any recorded regions beyond start of variable */
7144                 removerecordregions(startloc);
7145                 goto record;
7146         }
7147
7148  end:
7149         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7150                 int nesting = 1;
7151                 for (;;) {
7152                         unsigned char c = *p++;
7153                         if (c == CTLESC)
7154                                 p++;
7155                         else if (c == CTLBACKQ) {
7156                                 if (varlen >= 0)
7157                                         argbackq = argbackq->next;
7158                         } else if (c == CTLVAR) {
7159                                 if ((*p++ & VSTYPE) != VSNORMAL)
7160                                         nesting++;
7161                         } else if (c == CTLENDVAR) {
7162                                 if (--nesting == 0)
7163                                         break;
7164                         }
7165                 }
7166         }
7167         return p;
7168 }
7169
7170 /*
7171  * Add a file name to the list.
7172  */
7173 static void
7174 addfname(const char *name)
7175 {
7176         struct strlist *sp;
7177
7178         sp = stzalloc(sizeof(*sp));
7179         sp->text = sstrdup(name);
7180         *exparg.lastp = sp;
7181         exparg.lastp = &sp->next;
7182 }
7183
7184 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7185 static int
7186 hasmeta(const char *p)
7187 {
7188         static const char chars[] ALIGN1 = {
7189                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7190         };
7191
7192         for (;;) {
7193                 p = strpbrk(p, chars);
7194                 if (!p)
7195                         break;
7196                 switch ((unsigned char) *p) {
7197                 case CTLQUOTEMARK:
7198                         for (;;) {
7199                                 p++;
7200                                 if (*p == CTLQUOTEMARK)
7201                                         break;
7202                                 if (*p == CTLESC)
7203                                         p++;
7204                                 if (*p == '\0') /* huh? */
7205                                         return 0;
7206                         }
7207                         break;
7208                 case '\\':
7209                 case CTLESC:
7210                         p++;
7211                         if (*p == '\0')
7212                                 return 0;
7213                         break;
7214                 case '[':
7215                         if (!strchr(p + 1, ']')) {
7216                                 /* It's not a properly closed [] pattern,
7217                                  * but other metas may follow. Continue checking.
7218                                  * my[file* _is_ globbed by bash
7219                                  * and matches filenames like "my[file1".
7220                                  */
7221                                 break;
7222                         }
7223                         /* fallthrough */
7224                 default:
7225                 /* case '*': */
7226                 /* case '?': */
7227                         return 1;
7228                 }
7229                 p++;
7230         }
7231
7232         return 0;
7233 }
7234
7235 /* If we want to use glob() from libc... */
7236 #if !ENABLE_ASH_INTERNAL_GLOB
7237
7238 /* Add the result of glob() to the list */
7239 static void
7240 addglob(const glob_t *pglob)
7241 {
7242         char **p = pglob->gl_pathv;
7243
7244         do {
7245                 addfname(*p);
7246         } while (*++p);
7247 }
7248 static void
7249 expandmeta(struct strlist *str /*, int flag*/)
7250 {
7251         /* TODO - EXP_REDIR */
7252
7253         while (str) {
7254                 char *p;
7255                 glob_t pglob;
7256                 int i;
7257
7258                 if (fflag)
7259                         goto nometa;
7260
7261                 if (!hasmeta(str->text))
7262                         goto nometa;
7263
7264                 INT_OFF;
7265                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7266 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7267 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7268 //
7269 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7270 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7271 // Which means you need to unescape the string, right? Not so fast:
7272 // if there _is_ a file named "file\?" (with backslash), it is returned
7273 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7274 // You DON'T KNOW by looking at the result whether you need to unescape it.
7275 //
7276 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7277 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7278 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7279 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7280 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7281 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7282                 i = glob(p, 0, NULL, &pglob);
7283                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7284                 if (p != str->text)
7285                         free(p);
7286                 switch (i) {
7287                 case 0:
7288 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7289                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7290                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7291                                 goto nometa2;
7292 #endif
7293                         addglob(&pglob);
7294                         globfree(&pglob);
7295                         INT_ON;
7296                         break;
7297                 case GLOB_NOMATCH:
7298  //nometa2:
7299                         globfree(&pglob);
7300                         INT_ON;
7301  nometa:
7302                         *exparg.lastp = str;
7303                         rmescapes(str->text, 0);
7304                         exparg.lastp = &str->next;
7305                         break;
7306                 default:        /* GLOB_NOSPACE */
7307                         globfree(&pglob);
7308                         INT_ON;
7309                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7310                 }
7311                 str = str->next;
7312         }
7313 }
7314
7315 #else
7316 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7317
7318 /*
7319  * Do metacharacter (i.e. *, ?, [...]) expansion.
7320  */
7321 static void
7322 expmeta(char *expdir, char *enddir, char *name)
7323 {
7324         char *p;
7325         const char *cp;
7326         char *start;
7327         char *endname;
7328         int metaflag;
7329         struct stat statb;
7330         DIR *dirp;
7331         struct dirent *dp;
7332         int atend;
7333         int matchdot;
7334         int esc;
7335
7336         metaflag = 0;
7337         start = name;
7338         for (p = name; esc = 0, *p; p += esc + 1) {
7339                 if (*p == '*' || *p == '?')
7340                         metaflag = 1;
7341                 else if (*p == '[') {
7342                         char *q = p + 1;
7343                         if (*q == '!')
7344                                 q++;
7345                         for (;;) {
7346                                 if (*q == '\\')
7347                                         q++;
7348                                 if (*q == '/' || *q == '\0')
7349                                         break;
7350                                 if (*++q == ']') {
7351                                         metaflag = 1;
7352                                         break;
7353                                 }
7354                         }
7355                 } else {
7356                         if (*p == '\\')
7357                                 esc++;
7358                         if (p[esc] == '/') {
7359                                 if (metaflag)
7360                                         break;
7361                                 start = p + esc + 1;
7362                         }
7363                 }
7364         }
7365         if (metaflag == 0) {    /* we've reached the end of the file name */
7366                 if (enddir != expdir)
7367                         metaflag++;
7368                 p = name;
7369                 do {
7370                         if (*p == '\\')
7371                                 p++;
7372                         *enddir++ = *p;
7373                 } while (*p++);
7374                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7375                         addfname(expdir);
7376                 return;
7377         }
7378         endname = p;
7379         if (name < start) {
7380                 p = name;
7381                 do {
7382                         if (*p == '\\')
7383                                 p++;
7384                         *enddir++ = *p++;
7385                 } while (p < start);
7386         }
7387         if (enddir == expdir) {
7388                 cp = ".";
7389         } else if (enddir == expdir + 1 && *expdir == '/') {
7390                 cp = "/";
7391         } else {
7392                 cp = expdir;
7393                 enddir[-1] = '\0';
7394         }
7395         dirp = opendir(cp);
7396         if (dirp == NULL)
7397                 return;
7398         if (enddir != expdir)
7399                 enddir[-1] = '/';
7400         if (*endname == 0) {
7401                 atend = 1;
7402         } else {
7403                 atend = 0;
7404                 *endname = '\0';
7405                 endname += esc + 1;
7406         }
7407         matchdot = 0;
7408         p = start;
7409         if (*p == '\\')
7410                 p++;
7411         if (*p == '.')
7412                 matchdot++;
7413         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7414                 if (dp->d_name[0] == '.' && !matchdot)
7415                         continue;
7416                 if (pmatch(start, dp->d_name)) {
7417                         if (atend) {
7418                                 strcpy(enddir, dp->d_name);
7419                                 addfname(expdir);
7420                         } else {
7421                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7422                                         continue;
7423                                 p[-1] = '/';
7424                                 expmeta(expdir, p, endname);
7425                         }
7426                 }
7427         }
7428         closedir(dirp);
7429         if (!atend)
7430                 endname[-esc - 1] = esc ? '\\' : '/';
7431 }
7432
7433 static struct strlist *
7434 msort(struct strlist *list, int len)
7435 {
7436         struct strlist *p, *q = NULL;
7437         struct strlist **lpp;
7438         int half;
7439         int n;
7440
7441         if (len <= 1)
7442                 return list;
7443         half = len >> 1;
7444         p = list;
7445         for (n = half; --n >= 0;) {
7446                 q = p;
7447                 p = p->next;
7448         }
7449         q->next = NULL;                 /* terminate first half of list */
7450         q = msort(list, half);          /* sort first half of list */
7451         p = msort(p, len - half);               /* sort second half */
7452         lpp = &list;
7453         for (;;) {
7454 #if ENABLE_LOCALE_SUPPORT
7455                 if (strcoll(p->text, q->text) < 0)
7456 #else
7457                 if (strcmp(p->text, q->text) < 0)
7458 #endif
7459                                                 {
7460                         *lpp = p;
7461                         lpp = &p->next;
7462                         p = *lpp;
7463                         if (p == NULL) {
7464                                 *lpp = q;
7465                                 break;
7466                         }
7467                 } else {
7468                         *lpp = q;
7469                         lpp = &q->next;
7470                         q = *lpp;
7471                         if (q == NULL) {
7472                                 *lpp = p;
7473                                 break;
7474                         }
7475                 }
7476         }
7477         return list;
7478 }
7479
7480 /*
7481  * Sort the results of file name expansion.  It calculates the number of
7482  * strings to sort and then calls msort (short for merge sort) to do the
7483  * work.
7484  */
7485 static struct strlist *
7486 expsort(struct strlist *str)
7487 {
7488         int len;
7489         struct strlist *sp;
7490
7491         len = 0;
7492         for (sp = str; sp; sp = sp->next)
7493                 len++;
7494         return msort(str, len);
7495 }
7496
7497 static void
7498 expandmeta(struct strlist *str /*, int flag*/)
7499 {
7500         /* TODO - EXP_REDIR */
7501
7502         while (str) {
7503                 char *expdir;
7504                 struct strlist **savelastp;
7505                 struct strlist *sp;
7506                 char *p;
7507
7508                 if (fflag)
7509                         goto nometa;
7510                 if (!hasmeta(str->text))
7511                         goto nometa;
7512                 savelastp = exparg.lastp;
7513
7514                 INT_OFF;
7515                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7516                 {
7517                         int i = strlen(str->text);
7518 //BUGGY estimation of how long expanded name can be
7519                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7520                 }
7521                 expmeta(expdir, expdir, p);
7522                 free(expdir);
7523                 if (p != str->text)
7524                         free(p);
7525                 INT_ON;
7526                 if (exparg.lastp == savelastp) {
7527                         /*
7528                          * no matches
7529                          */
7530  nometa:
7531                         *exparg.lastp = str;
7532                         rmescapes(str->text, 0);
7533                         exparg.lastp = &str->next;
7534                 } else {
7535                         *exparg.lastp = NULL;
7536                         *savelastp = sp = expsort(*savelastp);
7537                         while (sp->next != NULL)
7538                                 sp = sp->next;
7539                         exparg.lastp = &sp->next;
7540                 }
7541                 str = str->next;
7542         }
7543 }
7544 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7545
7546 /*
7547  * Perform variable substitution and command substitution on an argument,
7548  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7549  * perform splitting and file name expansion.  When arglist is NULL, perform
7550  * here document expansion.
7551  */
7552 static void
7553 expandarg(union node *arg, struct arglist *arglist, int flag)
7554 {
7555         struct strlist *sp;
7556         char *p;
7557
7558         argbackq = arg->narg.backquote;
7559         STARTSTACKSTR(expdest);
7560         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7561         argstr(arg->narg.text, flag);
7562         p = _STPUTC('\0', expdest);
7563         expdest = p - 1;
7564         if (arglist == NULL) {
7565                 /* here document expanded */
7566                 goto out;
7567         }
7568         p = grabstackstr(p);
7569         TRACE(("expandarg: p:'%s'\n", p));
7570         exparg.lastp = &exparg.list;
7571         /*
7572          * TODO - EXP_REDIR
7573          */
7574         if (flag & EXP_FULL) {
7575                 ifsbreakup(p, &exparg);
7576                 *exparg.lastp = NULL;
7577                 exparg.lastp = &exparg.list;
7578                 expandmeta(exparg.list /*, flag*/);
7579         } else {
7580                 sp = stzalloc(sizeof(*sp));
7581                 sp->text = p;
7582                 *exparg.lastp = sp;
7583                 exparg.lastp = &sp->next;
7584         }
7585         *exparg.lastp = NULL;
7586         if (exparg.list) {
7587                 *arglist->lastp = exparg.list;
7588                 arglist->lastp = exparg.lastp;
7589         }
7590
7591  out:
7592         ifsfree();
7593 }
7594
7595 /*
7596  * Expand shell variables and backquotes inside a here document.
7597  */
7598 static void
7599 expandhere(union node *arg, int fd)
7600 {
7601         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7602         full_write(fd, stackblock(), expdest - (char *)stackblock());
7603 }
7604
7605 /*
7606  * Returns true if the pattern matches the string.
7607  */
7608 static int
7609 patmatch(char *pattern, const char *string)
7610 {
7611         char *p = preglob(pattern, 0);
7612         //bb_error_msg("fnmatch(pattern:'%s',str:'%s')", p, string);
7613         return pmatch(p, string);
7614 }
7615
7616 /*
7617  * See if a pattern matches in a case statement.
7618  */
7619 static int
7620 casematch(union node *pattern, char *val)
7621 {
7622         struct stackmark smark;
7623         int result;
7624
7625         setstackmark(&smark);
7626         argbackq = pattern->narg.backquote;
7627         STARTSTACKSTR(expdest);
7628         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7629         STACKSTRNUL(expdest);
7630         ifsfree();
7631         result = patmatch(stackblock(), val);
7632         popstackmark(&smark);
7633         return result;
7634 }
7635
7636
7637 /* ============ find_command */
7638
7639 struct builtincmd {
7640         const char *name;
7641         int (*builtin)(int, char **) FAST_FUNC;
7642         /* unsigned flags; */
7643 };
7644 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7645 /* "regular" builtins always take precedence over commands,
7646  * regardless of PATH=....%builtin... position */
7647 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7648 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7649
7650 struct cmdentry {
7651         smallint cmdtype;       /* CMDxxx */
7652         union param {
7653                 int index;
7654                 /* index >= 0 for commands without path (slashes) */
7655                 /* (TODO: what exactly does the value mean? PATH position?) */
7656                 /* index == -1 for commands with slashes */
7657                 /* index == (-2 - applet_no) for NOFORK applets */
7658                 const struct builtincmd *cmd;
7659                 struct funcnode *func;
7660         } u;
7661 };
7662 /* values of cmdtype */
7663 #define CMDUNKNOWN      -1      /* no entry in table for command */
7664 #define CMDNORMAL       0       /* command is an executable program */
7665 #define CMDFUNCTION     1       /* command is a shell function */
7666 #define CMDBUILTIN      2       /* command is a shell builtin */
7667
7668 /* action to find_command() */
7669 #define DO_ERR          0x01    /* prints errors */
7670 #define DO_ABS          0x02    /* checks absolute paths */
7671 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7672 #define DO_ALTPATH      0x08    /* using alternate path */
7673 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7674
7675 static void find_command(char *, struct cmdentry *, int, const char *);
7676
7677
7678 /* ============ Hashing commands */
7679
7680 /*
7681  * When commands are first encountered, they are entered in a hash table.
7682  * This ensures that a full path search will not have to be done for them
7683  * on each invocation.
7684  *
7685  * We should investigate converting to a linear search, even though that
7686  * would make the command name "hash" a misnomer.
7687  */
7688
7689 struct tblentry {
7690         struct tblentry *next;  /* next entry in hash chain */
7691         union param param;      /* definition of builtin function */
7692         smallint cmdtype;       /* CMDxxx */
7693         char rehash;            /* if set, cd done since entry created */
7694         char cmdname[1];        /* name of command */
7695 };
7696
7697 static struct tblentry **cmdtable;
7698 #define INIT_G_cmdtable() do { \
7699         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7700 } while (0)
7701
7702 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7703
7704
7705 static void
7706 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7707 {
7708 #if ENABLE_FEATURE_SH_STANDALONE
7709         if (applet_no >= 0) {
7710                 if (APPLET_IS_NOEXEC(applet_no)) {
7711                         clearenv();
7712                         while (*envp)
7713                                 putenv(*envp++);
7714                         popredir(/*drop:*/ 1, /*restore:*/ 0);
7715                         run_applet_no_and_exit(applet_no, cmd, argv);
7716                 }
7717                 /* re-exec ourselves with the new arguments */
7718                 execve(bb_busybox_exec_path, argv, envp);
7719                 /* If they called chroot or otherwise made the binary no longer
7720                  * executable, fall through */
7721         }
7722 #endif
7723
7724  repeat:
7725 #ifdef SYSV
7726         do {
7727                 execve(cmd, argv, envp);
7728         } while (errno == EINTR);
7729 #else
7730         execve(cmd, argv, envp);
7731 #endif
7732         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
7733                 /* Run "cmd" as a shell script:
7734                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7735                  * "If the execve() function fails with ENOEXEC, the shell
7736                  * shall execute a command equivalent to having a shell invoked
7737                  * with the command name as its first operand,
7738                  * with any remaining arguments passed to the new shell"
7739                  *
7740                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7741                  * just call ourselves.
7742                  *
7743                  * Note that bash reads ~80 chars of the file, and if it sees
7744                  * a zero byte before it sees newline, it doesn't try to
7745                  * interpret it, but fails with "cannot execute binary file"
7746                  * message and exit code 126. For one, this prevents attempts
7747                  * to interpret foreign ELF binaries as shell scripts.
7748                  */
7749                 argv[0] = (char*) cmd;
7750                 cmd = bb_busybox_exec_path;
7751                 /* NB: this is only possible because all callers of shellexec()
7752                  * ensure that the argv[-1] slot exists!
7753                  */
7754                 argv--;
7755                 argv[0] = (char*) "ash";
7756                 goto repeat;
7757         }
7758 }
7759
7760 /*
7761  * Exec a program.  Never returns.  If you change this routine, you may
7762  * have to change the find_command routine as well.
7763  * argv[-1] must exist and be writable! See tryexec() for why.
7764  */
7765 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7766 static void shellexec(char *prog, char **argv, const char *path, int idx)
7767 {
7768         char *cmdname;
7769         int e;
7770         char **envp;
7771         int exerrno;
7772         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7773
7774         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7775         if (strchr(prog, '/') != NULL
7776 #if ENABLE_FEATURE_SH_STANDALONE
7777          || (applet_no = find_applet_by_name(prog)) >= 0
7778 #endif
7779         ) {
7780                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7781                 if (applet_no >= 0) {
7782                         /* We tried execing ourself, but it didn't work.
7783                          * Maybe /proc/self/exe doesn't exist?
7784                          * Try $PATH search.
7785                          */
7786                         goto try_PATH;
7787                 }
7788                 e = errno;
7789         } else {
7790  try_PATH:
7791                 e = ENOENT;
7792                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7793                         if (--idx < 0 && pathopt == NULL) {
7794                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7795                                 if (errno != ENOENT && errno != ENOTDIR)
7796                                         e = errno;
7797                         }
7798                         stunalloc(cmdname);
7799                 }
7800         }
7801
7802         /* Map to POSIX errors */
7803         switch (e) {
7804         case EACCES:
7805                 exerrno = 126;
7806                 break;
7807         case ENOENT:
7808                 exerrno = 127;
7809                 break;
7810         default:
7811                 exerrno = 2;
7812                 break;
7813         }
7814         exitstatus = exerrno;
7815         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7816                 prog, e, suppress_int));
7817         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7818         /* NOTREACHED */
7819 }
7820
7821 static void
7822 printentry(struct tblentry *cmdp)
7823 {
7824         int idx;
7825         const char *path;
7826         char *name;
7827
7828         idx = cmdp->param.index;
7829         path = pathval();
7830         do {
7831                 name = path_advance(&path, cmdp->cmdname);
7832                 stunalloc(name);
7833         } while (--idx >= 0);
7834         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7835 }
7836
7837 /*
7838  * Clear out command entries.  The argument specifies the first entry in
7839  * PATH which has changed.
7840  */
7841 static void
7842 clearcmdentry(int firstchange)
7843 {
7844         struct tblentry **tblp;
7845         struct tblentry **pp;
7846         struct tblentry *cmdp;
7847
7848         INT_OFF;
7849         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7850                 pp = tblp;
7851                 while ((cmdp = *pp) != NULL) {
7852                         if ((cmdp->cmdtype == CMDNORMAL &&
7853                              cmdp->param.index >= firstchange)
7854                          || (cmdp->cmdtype == CMDBUILTIN &&
7855                              builtinloc >= firstchange)
7856                         ) {
7857                                 *pp = cmdp->next;
7858                                 free(cmdp);
7859                         } else {
7860                                 pp = &cmdp->next;
7861                         }
7862                 }
7863         }
7864         INT_ON;
7865 }
7866
7867 /*
7868  * Locate a command in the command hash table.  If "add" is nonzero,
7869  * add the command to the table if it is not already present.  The
7870  * variable "lastcmdentry" is set to point to the address of the link
7871  * pointing to the entry, so that delete_cmd_entry can delete the
7872  * entry.
7873  *
7874  * Interrupts must be off if called with add != 0.
7875  */
7876 static struct tblentry **lastcmdentry;
7877
7878 static struct tblentry *
7879 cmdlookup(const char *name, int add)
7880 {
7881         unsigned int hashval;
7882         const char *p;
7883         struct tblentry *cmdp;
7884         struct tblentry **pp;
7885
7886         p = name;
7887         hashval = (unsigned char)*p << 4;
7888         while (*p)
7889                 hashval += (unsigned char)*p++;
7890         hashval &= 0x7FFF;
7891         pp = &cmdtable[hashval % CMDTABLESIZE];
7892         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7893                 if (strcmp(cmdp->cmdname, name) == 0)
7894                         break;
7895                 pp = &cmdp->next;
7896         }
7897         if (add && cmdp == NULL) {
7898                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7899                                 + strlen(name)
7900                                 /* + 1 - already done because
7901                                  * tblentry::cmdname is char[1] */);
7902                 /*cmdp->next = NULL; - ckzalloc did it */
7903                 cmdp->cmdtype = CMDUNKNOWN;
7904                 strcpy(cmdp->cmdname, name);
7905         }
7906         lastcmdentry = pp;
7907         return cmdp;
7908 }
7909
7910 /*
7911  * Delete the command entry returned on the last lookup.
7912  */
7913 static void
7914 delete_cmd_entry(void)
7915 {
7916         struct tblentry *cmdp;
7917
7918         INT_OFF;
7919         cmdp = *lastcmdentry;
7920         *lastcmdentry = cmdp->next;
7921         if (cmdp->cmdtype == CMDFUNCTION)
7922                 freefunc(cmdp->param.func);
7923         free(cmdp);
7924         INT_ON;
7925 }
7926
7927 /*
7928  * Add a new command entry, replacing any existing command entry for
7929  * the same name - except special builtins.
7930  */
7931 static void
7932 addcmdentry(char *name, struct cmdentry *entry)
7933 {
7934         struct tblentry *cmdp;
7935
7936         cmdp = cmdlookup(name, 1);
7937         if (cmdp->cmdtype == CMDFUNCTION) {
7938                 freefunc(cmdp->param.func);
7939         }
7940         cmdp->cmdtype = entry->cmdtype;
7941         cmdp->param = entry->u;
7942         cmdp->rehash = 0;
7943 }
7944
7945 static int FAST_FUNC
7946 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7947 {
7948         struct tblentry **pp;
7949         struct tblentry *cmdp;
7950         int c;
7951         struct cmdentry entry;
7952         char *name;
7953
7954         if (nextopt("r") != '\0') {
7955                 clearcmdentry(0);
7956                 return 0;
7957         }
7958
7959         if (*argptr == NULL) {
7960                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7961                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7962                                 if (cmdp->cmdtype == CMDNORMAL)
7963                                         printentry(cmdp);
7964                         }
7965                 }
7966                 return 0;
7967         }
7968
7969         c = 0;
7970         while ((name = *argptr) != NULL) {
7971                 cmdp = cmdlookup(name, 0);
7972                 if (cmdp != NULL
7973                  && (cmdp->cmdtype == CMDNORMAL
7974                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7975                 ) {
7976                         delete_cmd_entry();
7977                 }
7978                 find_command(name, &entry, DO_ERR, pathval());
7979                 if (entry.cmdtype == CMDUNKNOWN)
7980                         c = 1;
7981                 argptr++;
7982         }
7983         return c;
7984 }
7985
7986 /*
7987  * Called when a cd is done.  Marks all commands so the next time they
7988  * are executed they will be rehashed.
7989  */
7990 static void
7991 hashcd(void)
7992 {
7993         struct tblentry **pp;
7994         struct tblentry *cmdp;
7995
7996         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7997                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7998                         if (cmdp->cmdtype == CMDNORMAL
7999                          || (cmdp->cmdtype == CMDBUILTIN
8000                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
8001                              && builtinloc > 0)
8002                         ) {
8003                                 cmdp->rehash = 1;
8004                         }
8005                 }
8006         }
8007 }
8008
8009 /*
8010  * Fix command hash table when PATH changed.
8011  * Called before PATH is changed.  The argument is the new value of PATH;
8012  * pathval() still returns the old value at this point.
8013  * Called with interrupts off.
8014  */
8015 static void FAST_FUNC
8016 changepath(const char *new)
8017 {
8018         const char *old;
8019         int firstchange;
8020         int idx;
8021         int idx_bltin;
8022
8023         old = pathval();
8024         firstchange = 9999;     /* assume no change */
8025         idx = 0;
8026         idx_bltin = -1;
8027         for (;;) {
8028                 if (*old != *new) {
8029                         firstchange = idx;
8030                         if ((*old == '\0' && *new == ':')
8031                          || (*old == ':' && *new == '\0')
8032                         ) {
8033                                 firstchange++;
8034                         }
8035                         old = new;      /* ignore subsequent differences */
8036                 }
8037                 if (*new == '\0')
8038                         break;
8039                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8040                         idx_bltin = idx;
8041                 if (*new == ':')
8042                         idx++;
8043                 new++;
8044                 old++;
8045         }
8046         if (builtinloc < 0 && idx_bltin >= 0)
8047                 builtinloc = idx_bltin;             /* zap builtins */
8048         if (builtinloc >= 0 && idx_bltin < 0)
8049                 firstchange = 0;
8050         clearcmdentry(firstchange);
8051         builtinloc = idx_bltin;
8052 }
8053 enum {
8054         TEOF,
8055         TNL,
8056         TREDIR,
8057         TWORD,
8058         TSEMI,
8059         TBACKGND,
8060         TAND,
8061         TOR,
8062         TPIPE,
8063         TLP,
8064         TRP,
8065         TENDCASE,
8066         TENDBQUOTE,
8067         TNOT,
8068         TCASE,
8069         TDO,
8070         TDONE,
8071         TELIF,
8072         TELSE,
8073         TESAC,
8074         TFI,
8075         TFOR,
8076 #if BASH_FUNCTION
8077         TFUNCTION,
8078 #endif
8079         TIF,
8080         TIN,
8081         TTHEN,
8082         TUNTIL,
8083         TWHILE,
8084         TBEGIN,
8085         TEND
8086 };
8087 typedef smallint token_id_t;
8088
8089 /* Nth bit indicates if token marks the end of a list */
8090 enum {
8091         tokendlist = 0
8092         /*  0 */ | (1u << TEOF)
8093         /*  1 */ | (0u << TNL)
8094         /*  2 */ | (0u << TREDIR)
8095         /*  3 */ | (0u << TWORD)
8096         /*  4 */ | (0u << TSEMI)
8097         /*  5 */ | (0u << TBACKGND)
8098         /*  6 */ | (0u << TAND)
8099         /*  7 */ | (0u << TOR)
8100         /*  8 */ | (0u << TPIPE)
8101         /*  9 */ | (0u << TLP)
8102         /* 10 */ | (1u << TRP)
8103         /* 11 */ | (1u << TENDCASE)
8104         /* 12 */ | (1u << TENDBQUOTE)
8105         /* 13 */ | (0u << TNOT)
8106         /* 14 */ | (0u << TCASE)
8107         /* 15 */ | (1u << TDO)
8108         /* 16 */ | (1u << TDONE)
8109         /* 17 */ | (1u << TELIF)
8110         /* 18 */ | (1u << TELSE)
8111         /* 19 */ | (1u << TESAC)
8112         /* 20 */ | (1u << TFI)
8113         /* 21 */ | (0u << TFOR)
8114 #if BASH_FUNCTION
8115         /* 22 */ | (0u << TFUNCTION)
8116 #endif
8117         /* 23 */ | (0u << TIF)
8118         /* 24 */ | (0u << TIN)
8119         /* 25 */ | (1u << TTHEN)
8120         /* 26 */ | (0u << TUNTIL)
8121         /* 27 */ | (0u << TWHILE)
8122         /* 28 */ | (0u << TBEGIN)
8123         /* 29 */ | (1u << TEND)
8124         , /* thus far 29 bits used */
8125 };
8126
8127 static const char *const tokname_array[] = {
8128         "end of file",
8129         "newline",
8130         "redirection",
8131         "word",
8132         ";",
8133         "&",
8134         "&&",
8135         "||",
8136         "|",
8137         "(",
8138         ")",
8139         ";;",
8140         "`",
8141 #define KWDOFFSET 13
8142         /* the following are keywords */
8143         "!",
8144         "case",
8145         "do",
8146         "done",
8147         "elif",
8148         "else",
8149         "esac",
8150         "fi",
8151         "for",
8152 #if BASH_FUNCTION
8153         "function",
8154 #endif
8155         "if",
8156         "in",
8157         "then",
8158         "until",
8159         "while",
8160         "{",
8161         "}",
8162 };
8163
8164 /* Wrapper around strcmp for qsort/bsearch/... */
8165 static int
8166 pstrcmp(const void *a, const void *b)
8167 {
8168         return strcmp((char*)a, *(char**)b);
8169 }
8170
8171 static const char *const *
8172 findkwd(const char *s)
8173 {
8174         return bsearch(s, tokname_array + KWDOFFSET,
8175                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8176                         sizeof(tokname_array[0]), pstrcmp);
8177 }
8178
8179 /*
8180  * Locate and print what a word is...
8181  */
8182 static int
8183 describe_command(char *command, const char *path, int describe_command_verbose)
8184 {
8185         struct cmdentry entry;
8186 #if ENABLE_ASH_ALIAS
8187         const struct alias *ap;
8188 #endif
8189
8190         path = path ? path : pathval();
8191
8192         if (describe_command_verbose) {
8193                 out1str(command);
8194         }
8195
8196         /* First look at the keywords */
8197         if (findkwd(command)) {
8198                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8199                 goto out;
8200         }
8201
8202 #if ENABLE_ASH_ALIAS
8203         /* Then look at the aliases */
8204         ap = lookupalias(command, 0);
8205         if (ap != NULL) {
8206                 if (!describe_command_verbose) {
8207                         out1str("alias ");
8208                         printalias(ap);
8209                         return 0;
8210                 }
8211                 out1fmt(" is an alias for %s", ap->val);
8212                 goto out;
8213         }
8214 #endif
8215         /* Brute force */
8216         find_command(command, &entry, DO_ABS, path);
8217
8218         switch (entry.cmdtype) {
8219         case CMDNORMAL: {
8220                 int j = entry.u.index;
8221                 char *p;
8222                 if (j < 0) {
8223                         p = command;
8224                 } else {
8225                         do {
8226                                 p = path_advance(&path, command);
8227                                 stunalloc(p);
8228                         } while (--j >= 0);
8229                 }
8230                 if (describe_command_verbose) {
8231                         out1fmt(" is %s", p);
8232                 } else {
8233                         out1str(p);
8234                 }
8235                 break;
8236         }
8237
8238         case CMDFUNCTION:
8239                 if (describe_command_verbose) {
8240                         out1str(" is a shell function");
8241                 } else {
8242                         out1str(command);
8243                 }
8244                 break;
8245
8246         case CMDBUILTIN:
8247                 if (describe_command_verbose) {
8248                         out1fmt(" is a %sshell builtin",
8249                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8250                                         "special " : nullstr
8251                         );
8252                 } else {
8253                         out1str(command);
8254                 }
8255                 break;
8256
8257         default:
8258                 if (describe_command_verbose) {
8259                         out1str(": not found\n");
8260                 }
8261                 return 127;
8262         }
8263  out:
8264         out1str("\n");
8265         return 0;
8266 }
8267
8268 static int FAST_FUNC
8269 typecmd(int argc UNUSED_PARAM, char **argv)
8270 {
8271         int i = 1;
8272         int err = 0;
8273         int verbose = 1;
8274
8275         /* type -p ... ? (we don't bother checking for 'p') */
8276         if (argv[1] && argv[1][0] == '-') {
8277                 i++;
8278                 verbose = 0;
8279         }
8280         while (argv[i]) {
8281                 err |= describe_command(argv[i++], NULL, verbose);
8282         }
8283         return err;
8284 }
8285
8286 #if ENABLE_ASH_CMDCMD
8287 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8288 static char **
8289 parse_command_args(char **argv, const char **path)
8290 {
8291         char *cp, c;
8292
8293         for (;;) {
8294                 cp = *++argv;
8295                 if (!cp)
8296                         return NULL;
8297                 if (*cp++ != '-')
8298                         break;
8299                 c = *cp++;
8300                 if (!c)
8301                         break;
8302                 if (c == '-' && !*cp) {
8303                         if (!*++argv)
8304                                 return NULL;
8305                         break;
8306                 }
8307                 do {
8308                         switch (c) {
8309                         case 'p':
8310                                 *path = bb_default_path;
8311                                 break;
8312                         default:
8313                                 /* run 'typecmd' for other options */
8314                                 return NULL;
8315                         }
8316                         c = *cp++;
8317                 } while (c);
8318         }
8319         return argv;
8320 }
8321
8322 static int FAST_FUNC
8323 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8324 {
8325         char *cmd;
8326         int c;
8327         enum {
8328                 VERIFY_BRIEF = 1,
8329                 VERIFY_VERBOSE = 2,
8330         } verify = 0;
8331         const char *path = NULL;
8332
8333         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8334          * never reaches this function.
8335          */
8336
8337         while ((c = nextopt("pvV")) != '\0')
8338                 if (c == 'V')
8339                         verify |= VERIFY_VERBOSE;
8340                 else if (c == 'v')
8341                         /*verify |= VERIFY_BRIEF*/;
8342 #if DEBUG
8343                 else if (c != 'p')
8344                         abort();
8345 #endif
8346                 else
8347                         path = bb_default_path;
8348
8349         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8350         cmd = *argptr;
8351         if (/*verify && */ cmd)
8352                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8353
8354         return 0;
8355 }
8356 #endif
8357
8358
8359 /*static int funcblocksize;     // size of structures in function */
8360 /*static int funcstringsize;    // size of strings in node */
8361 static void *funcblock;         /* block to allocate function from */
8362 static char *funcstring_end;    /* end of block to allocate strings from */
8363
8364 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8365         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8366         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8367         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8368         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8369         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8370         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8371         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8372         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8373         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8374         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8375         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8376         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8377         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8378         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8379         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8380         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8381         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8382 #if BASH_REDIR_OUTPUT
8383         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8384 #endif
8385         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8386         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8387         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8388         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8389         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8390         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8391         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8392         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8393         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8394 };
8395
8396 static int calcsize(int funcblocksize, union node *n);
8397
8398 static int
8399 sizenodelist(int funcblocksize, struct nodelist *lp)
8400 {
8401         while (lp) {
8402                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8403                 funcblocksize = calcsize(funcblocksize, lp->n);
8404                 lp = lp->next;
8405         }
8406         return funcblocksize;
8407 }
8408
8409 static int
8410 calcsize(int funcblocksize, union node *n)
8411 {
8412         if (n == NULL)
8413                 return funcblocksize;
8414         funcblocksize += nodesize[n->type];
8415         switch (n->type) {
8416         case NCMD:
8417                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8418                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8419                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8420                 break;
8421         case NPIPE:
8422                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8423                 break;
8424         case NREDIR:
8425         case NBACKGND:
8426         case NSUBSHELL:
8427                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8428                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8429                 break;
8430         case NAND:
8431         case NOR:
8432         case NSEMI:
8433         case NWHILE:
8434         case NUNTIL:
8435                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8436                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8437                 break;
8438         case NIF:
8439                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8440                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8441                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8442                 break;
8443         case NFOR:
8444                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8445                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8446                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8447                 break;
8448         case NCASE:
8449                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8450                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8451                 break;
8452         case NCLIST:
8453                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8454                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8455                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8456                 break;
8457         case NDEFUN:
8458         case NARG:
8459                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8460                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8461                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8462                 break;
8463         case NTO:
8464 #if BASH_REDIR_OUTPUT
8465         case NTO2:
8466 #endif
8467         case NCLOBBER:
8468         case NFROM:
8469         case NFROMTO:
8470         case NAPPEND:
8471                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8472                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8473                 break;
8474         case NTOFD:
8475         case NFROMFD:
8476                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8477                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8478         break;
8479         case NHERE:
8480         case NXHERE:
8481                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8482                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8483                 break;
8484         case NNOT:
8485                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8486                 break;
8487         };
8488         return funcblocksize;
8489 }
8490
8491 static char *
8492 nodeckstrdup(char *s)
8493 {
8494         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8495         return strcpy(funcstring_end, s);
8496 }
8497
8498 static union node *copynode(union node *);
8499
8500 static struct nodelist *
8501 copynodelist(struct nodelist *lp)
8502 {
8503         struct nodelist *start;
8504         struct nodelist **lpp;
8505
8506         lpp = &start;
8507         while (lp) {
8508                 *lpp = funcblock;
8509                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8510                 (*lpp)->n = copynode(lp->n);
8511                 lp = lp->next;
8512                 lpp = &(*lpp)->next;
8513         }
8514         *lpp = NULL;
8515         return start;
8516 }
8517
8518 static union node *
8519 copynode(union node *n)
8520 {
8521         union node *new;
8522
8523         if (n == NULL)
8524                 return NULL;
8525         new = funcblock;
8526         funcblock = (char *) funcblock + nodesize[n->type];
8527
8528         switch (n->type) {
8529         case NCMD:
8530                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8531                 new->ncmd.args = copynode(n->ncmd.args);
8532                 new->ncmd.assign = copynode(n->ncmd.assign);
8533                 break;
8534         case NPIPE:
8535                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8536                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8537                 break;
8538         case NREDIR:
8539         case NBACKGND:
8540         case NSUBSHELL:
8541                 new->nredir.redirect = copynode(n->nredir.redirect);
8542                 new->nredir.n = copynode(n->nredir.n);
8543                 break;
8544         case NAND:
8545         case NOR:
8546         case NSEMI:
8547         case NWHILE:
8548         case NUNTIL:
8549                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8550                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8551                 break;
8552         case NIF:
8553                 new->nif.elsepart = copynode(n->nif.elsepart);
8554                 new->nif.ifpart = copynode(n->nif.ifpart);
8555                 new->nif.test = copynode(n->nif.test);
8556                 break;
8557         case NFOR:
8558                 new->nfor.var = nodeckstrdup(n->nfor.var);
8559                 new->nfor.body = copynode(n->nfor.body);
8560                 new->nfor.args = copynode(n->nfor.args);
8561                 break;
8562         case NCASE:
8563                 new->ncase.cases = copynode(n->ncase.cases);
8564                 new->ncase.expr = copynode(n->ncase.expr);
8565                 break;
8566         case NCLIST:
8567                 new->nclist.body = copynode(n->nclist.body);
8568                 new->nclist.pattern = copynode(n->nclist.pattern);
8569                 new->nclist.next = copynode(n->nclist.next);
8570                 break;
8571         case NDEFUN:
8572         case NARG:
8573                 new->narg.backquote = copynodelist(n->narg.backquote);
8574                 new->narg.text = nodeckstrdup(n->narg.text);
8575                 new->narg.next = copynode(n->narg.next);
8576                 break;
8577         case NTO:
8578 #if BASH_REDIR_OUTPUT
8579         case NTO2:
8580 #endif
8581         case NCLOBBER:
8582         case NFROM:
8583         case NFROMTO:
8584         case NAPPEND:
8585                 new->nfile.fname = copynode(n->nfile.fname);
8586                 new->nfile.fd = n->nfile.fd;
8587                 new->nfile.next = copynode(n->nfile.next);
8588                 break;
8589         case NTOFD:
8590         case NFROMFD:
8591                 new->ndup.vname = copynode(n->ndup.vname);
8592                 new->ndup.dupfd = n->ndup.dupfd;
8593                 new->ndup.fd = n->ndup.fd;
8594                 new->ndup.next = copynode(n->ndup.next);
8595                 break;
8596         case NHERE:
8597         case NXHERE:
8598                 new->nhere.doc = copynode(n->nhere.doc);
8599                 new->nhere.fd = n->nhere.fd;
8600                 new->nhere.next = copynode(n->nhere.next);
8601                 break;
8602         case NNOT:
8603                 new->nnot.com = copynode(n->nnot.com);
8604                 break;
8605         };
8606         new->type = n->type;
8607         return new;
8608 }
8609
8610 /*
8611  * Make a copy of a parse tree.
8612  */
8613 static struct funcnode *
8614 copyfunc(union node *n)
8615 {
8616         struct funcnode *f;
8617         size_t blocksize;
8618
8619         /*funcstringsize = 0;*/
8620         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8621         f = ckzalloc(blocksize /* + funcstringsize */);
8622         funcblock = (char *) f + offsetof(struct funcnode, n);
8623         funcstring_end = (char *) f + blocksize;
8624         copynode(n);
8625         /* f->count = 0; - ckzalloc did it */
8626         return f;
8627 }
8628
8629 /*
8630  * Define a shell function.
8631  */
8632 static void
8633 defun(union node *func)
8634 {
8635         struct cmdentry entry;
8636
8637         INT_OFF;
8638         entry.cmdtype = CMDFUNCTION;
8639         entry.u.func = copyfunc(func);
8640         addcmdentry(func->narg.text, &entry);
8641         INT_ON;
8642 }
8643
8644 /* Reasons for skipping commands (see comment on breakcmd routine) */
8645 #define SKIPBREAK      (1 << 0)
8646 #define SKIPCONT       (1 << 1)
8647 #define SKIPFUNC       (1 << 2)
8648 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8649 static int skipcount;           /* number of levels to skip */
8650 static int funcnest;            /* depth of function calls */
8651 static int loopnest;            /* current loop nesting level */
8652
8653 /* Forward decl way out to parsing code - dotrap needs it */
8654 static int evalstring(char *s, int flags);
8655
8656 /* Called to execute a trap.
8657  * Single callsite - at the end of evaltree().
8658  * If we return non-zero, evaltree raises EXEXIT exception.
8659  *
8660  * Perhaps we should avoid entering new trap handlers
8661  * while we are executing a trap handler. [is it a TODO?]
8662  */
8663 static void
8664 dotrap(void)
8665 {
8666         uint8_t *g;
8667         int sig;
8668         uint8_t last_status;
8669
8670         if (!pending_sig)
8671                 return;
8672
8673         last_status = exitstatus;
8674         pending_sig = 0;
8675         barrier();
8676
8677         TRACE(("dotrap entered\n"));
8678         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8679                 char *p;
8680
8681                 if (!*g)
8682                         continue;
8683
8684                 if (evalskip) {
8685                         pending_sig = sig;
8686                         break;
8687                 }
8688
8689                 p = trap[sig];
8690                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8691                  * don't upset it by resetting gotsig[SIGINT-1] */
8692                 if (sig == SIGINT && !p)
8693                         continue;
8694
8695                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8696                 *g = 0;
8697                 if (!p)
8698                         continue;
8699                 evalstring(p, 0);
8700         }
8701         exitstatus = last_status;
8702         TRACE(("dotrap returns\n"));
8703 }
8704
8705 /* forward declarations - evaluation is fairly recursive business... */
8706 static int evalloop(union node *, int);
8707 static int evalfor(union node *, int);
8708 static int evalcase(union node *, int);
8709 static int evalsubshell(union node *, int);
8710 static void expredir(union node *);
8711 static int evalpipe(union node *, int);
8712 static int evalcommand(union node *, int);
8713 static int evalbltin(const struct builtincmd *, int, char **, int);
8714 static void prehash(union node *);
8715
8716 /*
8717  * Evaluate a parse tree.  The value is left in the global variable
8718  * exitstatus.
8719  */
8720 static int
8721 evaltree(union node *n, int flags)
8722 {
8723         int checkexit = 0;
8724         int (*evalfn)(union node *, int);
8725         int status = 0;
8726
8727         if (n == NULL) {
8728                 TRACE(("evaltree(NULL) called\n"));
8729                 goto out;
8730         }
8731         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8732
8733         dotrap();
8734
8735         switch (n->type) {
8736         default:
8737 #if DEBUG
8738                 out1fmt("Node type = %d\n", n->type);
8739                 fflush_all();
8740                 break;
8741 #endif
8742         case NNOT:
8743                 status = !evaltree(n->nnot.com, EV_TESTED);
8744                 goto setstatus;
8745         case NREDIR:
8746                 expredir(n->nredir.redirect);
8747                 pushredir(n->nredir.redirect);
8748                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8749                 if (!status) {
8750                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8751                 }
8752                 if (n->nredir.redirect)
8753                         popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8754                 goto setstatus;
8755         case NCMD:
8756                 evalfn = evalcommand;
8757  checkexit:
8758                 if (eflag && !(flags & EV_TESTED))
8759                         checkexit = ~0;
8760                 goto calleval;
8761         case NFOR:
8762                 evalfn = evalfor;
8763                 goto calleval;
8764         case NWHILE:
8765         case NUNTIL:
8766                 evalfn = evalloop;
8767                 goto calleval;
8768         case NSUBSHELL:
8769         case NBACKGND:
8770                 evalfn = evalsubshell;
8771                 goto checkexit;
8772         case NPIPE:
8773                 evalfn = evalpipe;
8774                 goto checkexit;
8775         case NCASE:
8776                 evalfn = evalcase;
8777                 goto calleval;
8778         case NAND:
8779         case NOR:
8780         case NSEMI: {
8781
8782 #if NAND + 1 != NOR
8783 #error NAND + 1 != NOR
8784 #endif
8785 #if NOR + 1 != NSEMI
8786 #error NOR + 1 != NSEMI
8787 #endif
8788                 unsigned is_or = n->type - NAND;
8789                 status = evaltree(
8790                         n->nbinary.ch1,
8791                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8792                 );
8793                 if ((!status) == is_or || evalskip)
8794                         break;
8795                 n = n->nbinary.ch2;
8796  evaln:
8797                 evalfn = evaltree;
8798  calleval:
8799                 status = evalfn(n, flags);
8800                 goto setstatus;
8801         }
8802         case NIF:
8803                 status = evaltree(n->nif.test, EV_TESTED);
8804                 if (evalskip)
8805                         break;
8806                 if (!status) {
8807                         n = n->nif.ifpart;
8808                         goto evaln;
8809                 }
8810                 if (n->nif.elsepart) {
8811                         n = n->nif.elsepart;
8812                         goto evaln;
8813                 }
8814                 status = 0;
8815                 goto setstatus;
8816         case NDEFUN:
8817                 defun(n);
8818                 /* Not necessary. To test it:
8819                  * "false; f() { qwerty; }; echo $?" should print 0.
8820                  */
8821                 /* status = 0; */
8822  setstatus:
8823                 exitstatus = status;
8824                 break;
8825         }
8826  out:
8827         /* Order of checks below is important:
8828          * signal handlers trigger before exit caused by "set -e".
8829          */
8830         dotrap();
8831
8832         if (checkexit & status)
8833                 raise_exception(EXEXIT);
8834         if (flags & EV_EXIT)
8835                 raise_exception(EXEXIT);
8836
8837         TRACE(("leaving evaltree (no interrupts)\n"));
8838         return exitstatus;
8839 }
8840
8841 static int
8842 skiploop(void)
8843 {
8844         int skip = evalskip;
8845
8846         switch (skip) {
8847         case 0:
8848                 break;
8849         case SKIPBREAK:
8850         case SKIPCONT:
8851                 if (--skipcount <= 0) {
8852                         evalskip = 0;
8853                         break;
8854                 }
8855                 skip = SKIPBREAK;
8856                 break;
8857         }
8858         return skip;
8859 }
8860
8861 static int
8862 evalloop(union node *n, int flags)
8863 {
8864         int skip;
8865         int status;
8866
8867         loopnest++;
8868         status = 0;
8869         flags &= EV_TESTED;
8870         do {
8871                 int i;
8872
8873                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8874                 skip = skiploop();
8875                 if (skip == SKIPFUNC)
8876                         status = i;
8877                 if (skip)
8878                         continue;
8879                 if (n->type != NWHILE)
8880                         i = !i;
8881                 if (i != 0)
8882                         break;
8883                 status = evaltree(n->nbinary.ch2, flags);
8884                 skip = skiploop();
8885         } while (!(skip & ~SKIPCONT));
8886         loopnest--;
8887
8888         return status;
8889 }
8890
8891 static int
8892 evalfor(union node *n, int flags)
8893 {
8894         struct arglist arglist;
8895         union node *argp;
8896         struct strlist *sp;
8897         struct stackmark smark;
8898         int status = 0;
8899
8900         setstackmark(&smark);
8901         arglist.list = NULL;
8902         arglist.lastp = &arglist.list;
8903         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8904                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8905         }
8906         *arglist.lastp = NULL;
8907
8908         loopnest++;
8909         flags &= EV_TESTED;
8910         for (sp = arglist.list; sp; sp = sp->next) {
8911                 setvar0(n->nfor.var, sp->text);
8912                 status = evaltree(n->nfor.body, flags);
8913                 if (skiploop() & ~SKIPCONT)
8914                         break;
8915         }
8916         loopnest--;
8917         popstackmark(&smark);
8918
8919         return status;
8920 }
8921
8922 static int
8923 evalcase(union node *n, int flags)
8924 {
8925         union node *cp;
8926         union node *patp;
8927         struct arglist arglist;
8928         struct stackmark smark;
8929         int status = 0;
8930
8931         setstackmark(&smark);
8932         arglist.list = NULL;
8933         arglist.lastp = &arglist.list;
8934         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8935         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8936                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8937                         if (casematch(patp, arglist.list->text)) {
8938                                 /* Ensure body is non-empty as otherwise
8939                                  * EV_EXIT may prevent us from setting the
8940                                  * exit status.
8941                                  */
8942                                 if (evalskip == 0 && cp->nclist.body) {
8943                                         status = evaltree(cp->nclist.body, flags);
8944                                 }
8945                                 goto out;
8946                         }
8947                 }
8948         }
8949  out:
8950         popstackmark(&smark);
8951
8952         return status;
8953 }
8954
8955 /*
8956  * Kick off a subshell to evaluate a tree.
8957  */
8958 static int
8959 evalsubshell(union node *n, int flags)
8960 {
8961         struct job *jp;
8962         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
8963         int status;
8964
8965         expredir(n->nredir.redirect);
8966         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
8967                 goto nofork;
8968         INT_OFF;
8969         if (backgnd == FORK_FG)
8970                 get_tty_state();
8971         jp = makejob(/*n,*/ 1);
8972         if (forkshell(jp, n, backgnd) == 0) {
8973                 /* child */
8974                 INT_ON;
8975                 flags |= EV_EXIT;
8976                 if (backgnd)
8977                         flags &= ~EV_TESTED;
8978  nofork:
8979                 redirect(n->nredir.redirect, 0);
8980                 evaltreenr(n->nredir.n, flags);
8981                 /* never returns */
8982         }
8983         /* parent */
8984         status = 0;
8985         if (backgnd == FORK_FG)
8986                 status = waitforjob(jp);
8987         INT_ON;
8988         return status;
8989 }
8990
8991 /*
8992  * Compute the names of the files in a redirection list.
8993  */
8994 static void fixredir(union node *, const char *, int);
8995 static void
8996 expredir(union node *n)
8997 {
8998         union node *redir;
8999
9000         for (redir = n; redir; redir = redir->nfile.next) {
9001                 struct arglist fn;
9002
9003                 fn.list = NULL;
9004                 fn.lastp = &fn.list;
9005                 switch (redir->type) {
9006                 case NFROMTO:
9007                 case NFROM:
9008                 case NTO:
9009 #if BASH_REDIR_OUTPUT
9010                 case NTO2:
9011 #endif
9012                 case NCLOBBER:
9013                 case NAPPEND:
9014                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9015                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9016 #if BASH_REDIR_OUTPUT
9017  store_expfname:
9018 #endif
9019 #if 0
9020 // By the design of stack allocator, the loop of this kind:
9021 //      while true; do while true; do break; done </dev/null; done
9022 // will look like a memory leak: ash plans to free expfname's
9023 // of "/dev/null" as soon as it finishes running the loop
9024 // (in this case, never).
9025 // This "fix" is wrong:
9026                         if (redir->nfile.expfname)
9027                                 stunalloc(redir->nfile.expfname);
9028 // It results in corrupted state of stacked allocations.
9029 #endif
9030                         redir->nfile.expfname = fn.list->text;
9031                         break;
9032                 case NFROMFD:
9033                 case NTOFD: /* >& */
9034                         if (redir->ndup.vname) {
9035                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9036                                 if (fn.list == NULL)
9037                                         ash_msg_and_raise_error("redir error");
9038 #if BASH_REDIR_OUTPUT
9039 //FIXME: we used expandarg with different args!
9040                                 if (!isdigit_str9(fn.list->text)) {
9041                                         /* >&file, not >&fd */
9042                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9043                                                 ash_msg_and_raise_error("redir error");
9044                                         redir->type = NTO2;
9045                                         goto store_expfname;
9046                                 }
9047 #endif
9048                                 fixredir(redir, fn.list->text, 1);
9049                         }
9050                         break;
9051                 }
9052         }
9053 }
9054
9055 /*
9056  * Evaluate a pipeline.  All the processes in the pipeline are children
9057  * of the process creating the pipeline.  (This differs from some versions
9058  * of the shell, which make the last process in a pipeline the parent
9059  * of all the rest.)
9060  */
9061 static int
9062 evalpipe(union node *n, int flags)
9063 {
9064         struct job *jp;
9065         struct nodelist *lp;
9066         int pipelen;
9067         int prevfd;
9068         int pip[2];
9069         int status = 0;
9070
9071         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9072         pipelen = 0;
9073         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9074                 pipelen++;
9075         flags |= EV_EXIT;
9076         INT_OFF;
9077         if (n->npipe.pipe_backgnd == 0)
9078                 get_tty_state();
9079         jp = makejob(/*n,*/ pipelen);
9080         prevfd = -1;
9081         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9082                 prehash(lp->n);
9083                 pip[1] = -1;
9084                 if (lp->next) {
9085                         if (pipe(pip) < 0) {
9086                                 close(prevfd);
9087                                 ash_msg_and_raise_error("pipe call failed");
9088                         }
9089                 }
9090                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9091                         /* child */
9092                         INT_ON;
9093                         if (pip[1] >= 0) {
9094                                 close(pip[0]);
9095                         }
9096                         if (prevfd > 0) {
9097                                 dup2(prevfd, 0);
9098                                 close(prevfd);
9099                         }
9100                         if (pip[1] > 1) {
9101                                 dup2(pip[1], 1);
9102                                 close(pip[1]);
9103                         }
9104                         evaltreenr(lp->n, flags);
9105                         /* never returns */
9106                 }
9107                 /* parent */
9108                 if (prevfd >= 0)
9109                         close(prevfd);
9110                 prevfd = pip[0];
9111                 /* Don't want to trigger debugging */
9112                 if (pip[1] != -1)
9113                         close(pip[1]);
9114         }
9115         if (n->npipe.pipe_backgnd == 0) {
9116                 status = waitforjob(jp);
9117                 TRACE(("evalpipe:  job done exit status %d\n", status));
9118         }
9119         INT_ON;
9120
9121         return status;
9122 }
9123
9124 /*
9125  * Controls whether the shell is interactive or not.
9126  */
9127 static void
9128 setinteractive(int on)
9129 {
9130         static smallint is_interactive;
9131
9132         if (++on == is_interactive)
9133                 return;
9134         is_interactive = on;
9135         setsignal(SIGINT);
9136         setsignal(SIGQUIT);
9137         setsignal(SIGTERM);
9138 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9139         if (is_interactive > 1) {
9140                 /* Looks like they want an interactive shell */
9141                 static smallint did_banner;
9142
9143                 if (!did_banner) {
9144                         /* note: ash and hush share this string */
9145                         out1fmt("\n\n%s %s\n"
9146                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9147                                 "\n",
9148                                 bb_banner,
9149                                 "built-in shell (ash)"
9150                         );
9151                         did_banner = 1;
9152                 }
9153         }
9154 #endif
9155 }
9156
9157 static void
9158 optschanged(void)
9159 {
9160 #if DEBUG
9161         opentrace();
9162 #endif
9163         setinteractive(iflag);
9164         setjobctl(mflag);
9165 #if ENABLE_FEATURE_EDITING_VI
9166         if (viflag)
9167                 line_input_state->flags |= VI_MODE;
9168         else
9169                 line_input_state->flags &= ~VI_MODE;
9170 #else
9171         viflag = 0; /* forcibly keep the option off */
9172 #endif
9173 }
9174
9175 struct localvar_list {
9176         struct localvar_list *next;
9177         struct localvar *lv;
9178 };
9179
9180 static struct localvar_list *localvar_stack;
9181
9182 /*
9183  * Called after a function returns.
9184  * Interrupts must be off.
9185  */
9186 static void
9187 poplocalvars(int keep)
9188 {
9189         struct localvar_list *ll;
9190         struct localvar *lvp, *next;
9191         struct var *vp;
9192
9193         INT_OFF;
9194         ll = localvar_stack;
9195         localvar_stack = ll->next;
9196
9197         next = ll->lv;
9198         free(ll);
9199
9200         while ((lvp = next) != NULL) {
9201                 next = lvp->next;
9202                 vp = lvp->vp;
9203                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9204                 if (keep) {
9205                         int bits = VSTRFIXED;
9206
9207                         if (lvp->flags != VUNSET) {
9208                                 if (vp->var_text == lvp->text)
9209                                         bits |= VTEXTFIXED;
9210                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9211                                         free((char*)lvp->text);
9212                         }
9213
9214                         vp->flags &= ~bits;
9215                         vp->flags |= (lvp->flags & bits);
9216
9217                         if ((vp->flags &
9218                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9219                                 unsetvar(vp->var_text);
9220                 } else if (vp == NULL) {        /* $- saved */
9221                         memcpy(optlist, lvp->text, sizeof(optlist));
9222                         free((char*)lvp->text);
9223                         optschanged();
9224                 } else if (lvp->flags == VUNSET) {
9225                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9226                         unsetvar(vp->var_text);
9227                 } else {
9228                         if (vp->var_func)
9229                                 vp->var_func(var_end(lvp->text));
9230                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9231                                 free((char*)vp->var_text);
9232                         vp->flags = lvp->flags;
9233                         vp->var_text = lvp->text;
9234                 }
9235                 free(lvp);
9236         }
9237         INT_ON;
9238 }
9239
9240 /*
9241  * Create a new localvar environment.
9242  */
9243 static struct localvar_list *
9244 pushlocalvars(void)
9245 {
9246         struct localvar_list *ll;
9247
9248         INT_OFF;
9249         ll = ckzalloc(sizeof(*ll));
9250         /*ll->lv = NULL; - zalloc did it */
9251         ll->next = localvar_stack;
9252         localvar_stack = ll;
9253         INT_ON;
9254
9255         return ll->next;
9256 }
9257
9258 static void
9259 unwindlocalvars(struct localvar_list *stop)
9260 {
9261         while (localvar_stack != stop)
9262                 poplocalvars(0);
9263 }
9264
9265 static int
9266 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9267 {
9268         volatile struct shparam saveparam;
9269         struct jmploc *volatile savehandler;
9270         struct jmploc jmploc;
9271         int e;
9272
9273         saveparam = shellparam;
9274         savehandler = exception_handler;
9275         e = setjmp(jmploc.loc);
9276         if (e) {
9277                 goto funcdone;
9278         }
9279         INT_OFF;
9280         exception_handler = &jmploc;
9281         shellparam.malloced = 0;
9282         func->count++;
9283         funcnest++;
9284         INT_ON;
9285         shellparam.nparam = argc - 1;
9286         shellparam.p = argv + 1;
9287 #if ENABLE_ASH_GETOPTS
9288         shellparam.optind = 1;
9289         shellparam.optoff = -1;
9290 #endif
9291         pushlocalvars();
9292         evaltree(func->n.narg.next, flags & EV_TESTED);
9293         poplocalvars(0);
9294  funcdone:
9295         INT_OFF;
9296         funcnest--;
9297         freefunc(func);
9298         freeparam(&shellparam);
9299         shellparam = saveparam;
9300         exception_handler = savehandler;
9301         INT_ON;
9302         evalskip &= ~SKIPFUNC;
9303         return e;
9304 }
9305
9306 /*
9307  * Make a variable a local variable.  When a variable is made local, it's
9308  * value and flags are saved in a localvar structure.  The saved values
9309  * will be restored when the shell function returns.  We handle the name
9310  * "-" as a special case: it makes changes to "set +-options" local
9311  * (options will be restored on return from the function).
9312  */
9313 static void
9314 mklocal(char *name)
9315 {
9316         struct localvar *lvp;
9317         struct var **vpp;
9318         struct var *vp;
9319         char *eq = strchr(name, '=');
9320
9321         INT_OFF;
9322         /* Cater for duplicate "local". Examples:
9323          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9324          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9325          */
9326         lvp = localvar_stack->lv;
9327         while (lvp) {
9328                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9329                         if (eq)
9330                                 setvareq(name, 0);
9331                         /* else:
9332                          * it's a duplicate "local VAR" declaration, do nothing
9333                          */
9334                         goto ret;
9335                 }
9336                 lvp = lvp->next;
9337         }
9338
9339         lvp = ckzalloc(sizeof(*lvp));
9340         if (LONE_DASH(name)) {
9341                 char *p;
9342                 p = ckmalloc(sizeof(optlist));
9343                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9344                 vp = NULL;
9345         } else {
9346                 vpp = hashvar(name);
9347                 vp = *findvar(vpp, name);
9348                 if (vp == NULL) {
9349                         /* variable did not exist yet */
9350                         if (eq)
9351                                 vp = setvareq(name, VSTRFIXED);
9352                         else
9353                                 vp = setvar(name, NULL, VSTRFIXED);
9354                         lvp->flags = VUNSET;
9355                 } else {
9356                         lvp->text = vp->var_text;
9357                         lvp->flags = vp->flags;
9358                         /* make sure neither "struct var" nor string gets freed
9359                          * during (un)setting:
9360                          */
9361                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9362                         if (eq)
9363                                 setvareq(name, 0);
9364                         else
9365                                 /* "local VAR" unsets VAR: */
9366                                 setvar0(name, NULL);
9367                 }
9368         }
9369         lvp->vp = vp;
9370         lvp->next = localvar_stack->lv;
9371         localvar_stack->lv = lvp;
9372  ret:
9373         INT_ON;
9374 }
9375
9376 /*
9377  * The "local" command.
9378  */
9379 static int FAST_FUNC
9380 localcmd(int argc UNUSED_PARAM, char **argv)
9381 {
9382         char *name;
9383
9384         if (!localvar_stack)
9385                 ash_msg_and_raise_error("not in a function");
9386
9387         argv = argptr;
9388         while ((name = *argv++) != NULL) {
9389                 mklocal(name);
9390         }
9391         return 0;
9392 }
9393
9394 static int FAST_FUNC
9395 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9396 {
9397         return 1;
9398 }
9399
9400 static int FAST_FUNC
9401 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9402 {
9403         return 0;
9404 }
9405
9406 static int FAST_FUNC
9407 execcmd(int argc UNUSED_PARAM, char **argv)
9408 {
9409         optionarg = NULL;
9410         while (nextopt("a:") != '\0')
9411                 /* nextopt() sets optionarg to "-a ARGV0" */;
9412
9413         argv = argptr;
9414         if (argv[0]) {
9415                 char *prog;
9416
9417                 iflag = 0;              /* exit on error */
9418                 mflag = 0;
9419                 optschanged();
9420                 /* We should set up signals for "exec CMD"
9421                  * the same way as for "CMD" without "exec".
9422                  * But optschanged->setinteractive->setsignal
9423                  * still thought we are a root shell. Therefore, for example,
9424                  * SIGQUIT is still set to IGN. Fix it:
9425                  */
9426                 shlvl++;
9427                 setsignal(SIGQUIT);
9428                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9429                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9430                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9431
9432                 prog = argv[0];
9433                 if (optionarg)
9434                         argv[0] = optionarg;
9435                 shellexec(prog, argv, pathval(), 0);
9436                 /* NOTREACHED */
9437         }
9438         return 0;
9439 }
9440
9441 /*
9442  * The return command.
9443  */
9444 static int FAST_FUNC
9445 returncmd(int argc UNUSED_PARAM, char **argv)
9446 {
9447         /*
9448          * If called outside a function, do what ksh does;
9449          * skip the rest of the file.
9450          */
9451         evalskip = SKIPFUNC;
9452         return argv[1] ? number(argv[1]) : exitstatus;
9453 }
9454
9455 /* Forward declarations for builtintab[] */
9456 static int breakcmd(int, char **) FAST_FUNC;
9457 static int dotcmd(int, char **) FAST_FUNC;
9458 static int evalcmd(int, char **, int) FAST_FUNC;
9459 static int exitcmd(int, char **) FAST_FUNC;
9460 static int exportcmd(int, char **) FAST_FUNC;
9461 #if ENABLE_ASH_GETOPTS
9462 static int getoptscmd(int, char **) FAST_FUNC;
9463 #endif
9464 #if ENABLE_ASH_HELP
9465 static int helpcmd(int, char **) FAST_FUNC;
9466 #endif
9467 #if MAX_HISTORY
9468 static int historycmd(int, char **) FAST_FUNC;
9469 #endif
9470 #if ENABLE_FEATURE_SH_MATH
9471 static int letcmd(int, char **) FAST_FUNC;
9472 #endif
9473 static int readcmd(int, char **) FAST_FUNC;
9474 static int setcmd(int, char **) FAST_FUNC;
9475 static int shiftcmd(int, char **) FAST_FUNC;
9476 static int timescmd(int, char **) FAST_FUNC;
9477 static int trapcmd(int, char **) FAST_FUNC;
9478 static int umaskcmd(int, char **) FAST_FUNC;
9479 static int unsetcmd(int, char **) FAST_FUNC;
9480 static int ulimitcmd(int, char **) FAST_FUNC;
9481
9482 #define BUILTIN_NOSPEC          "0"
9483 #define BUILTIN_SPECIAL         "1"
9484 #define BUILTIN_REGULAR         "2"
9485 #define BUILTIN_SPEC_REG        "3"
9486 #define BUILTIN_ASSIGN          "4"
9487 #define BUILTIN_SPEC_ASSG       "5"
9488 #define BUILTIN_REG_ASSG        "6"
9489 #define BUILTIN_SPEC_REG_ASSG   "7"
9490
9491 /* Stubs for calling non-FAST_FUNC's */
9492 #if ENABLE_ASH_ECHO
9493 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9494 #endif
9495 #if ENABLE_ASH_PRINTF
9496 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9497 #endif
9498 #if ENABLE_ASH_TEST || BASH_TEST2
9499 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9500 #endif
9501
9502 /* Keep these in proper order since it is searched via bsearch() */
9503 static const struct builtincmd builtintab[] = {
9504         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9505         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9506 #if ENABLE_ASH_TEST
9507         { BUILTIN_REGULAR       "["       , testcmd    },
9508 #endif
9509 #if BASH_TEST2
9510         { BUILTIN_REGULAR       "[["      , testcmd    },
9511 #endif
9512 #if ENABLE_ASH_ALIAS
9513         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9514 #endif
9515 #if JOBS
9516         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9517 #endif
9518         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9519         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9520         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9521 #if ENABLE_ASH_CMDCMD
9522         { BUILTIN_REGULAR       "command" , commandcmd },
9523 #endif
9524         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9525 #if ENABLE_ASH_ECHO
9526         { BUILTIN_REGULAR       "echo"    , echocmd    },
9527 #endif
9528         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9529         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9530         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9531         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9532         { BUILTIN_REGULAR       "false"   , falsecmd   },
9533 #if JOBS
9534         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9535 #endif
9536 #if ENABLE_ASH_GETOPTS
9537         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9538 #endif
9539         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9540 #if ENABLE_ASH_HELP
9541         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9542 #endif
9543 #if MAX_HISTORY
9544         { BUILTIN_NOSPEC        "history" , historycmd },
9545 #endif
9546 #if JOBS
9547         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9548         { BUILTIN_REGULAR       "kill"    , killcmd    },
9549 #endif
9550 #if ENABLE_FEATURE_SH_MATH
9551         { BUILTIN_NOSPEC        "let"     , letcmd     },
9552 #endif
9553         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9554 #if ENABLE_ASH_PRINTF
9555         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9556 #endif
9557         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9558         { BUILTIN_REGULAR       "read"    , readcmd    },
9559         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9560         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9561         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9562         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9563 #if BASH_SOURCE
9564         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9565 #endif
9566 #if ENABLE_ASH_TEST
9567         { BUILTIN_REGULAR       "test"    , testcmd    },
9568 #endif
9569         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9570         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9571         { BUILTIN_REGULAR       "true"    , truecmd    },
9572         { BUILTIN_NOSPEC        "type"    , typecmd    },
9573         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9574         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9575 #if ENABLE_ASH_ALIAS
9576         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9577 #endif
9578         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9579         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9580 };
9581
9582 /* Should match the above table! */
9583 #define COMMANDCMD (builtintab + \
9584         /* . : */       2 + \
9585         /* [ */         1 * ENABLE_ASH_TEST + \
9586         /* [[ */        1 * BASH_TEST2 + \
9587         /* alias */     1 * ENABLE_ASH_ALIAS + \
9588         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9589         /* break cd cddir  */   3)
9590 #define EVALCMD (COMMANDCMD + \
9591         /* command */   1 * ENABLE_ASH_CMDCMD + \
9592         /* continue */  1 + \
9593         /* echo */      1 * ENABLE_ASH_ECHO + \
9594         0)
9595 #define EXECCMD (EVALCMD + \
9596         /* eval */      1)
9597
9598 /*
9599  * Search the table of builtin commands.
9600  */
9601 static int
9602 pstrcmp1(const void *a, const void *b)
9603 {
9604         return strcmp((char*)a, *(char**)b + 1);
9605 }
9606 static struct builtincmd *
9607 find_builtin(const char *name)
9608 {
9609         struct builtincmd *bp;
9610
9611         bp = bsearch(
9612                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9613                 pstrcmp1
9614         );
9615         return bp;
9616 }
9617
9618 /*
9619  * Execute a simple command.
9620  */
9621 static int
9622 isassignment(const char *p)
9623 {
9624         const char *q = endofname(p);
9625         if (p == q)
9626                 return 0;
9627         return *q == '=';
9628 }
9629 static int FAST_FUNC
9630 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9631 {
9632         /* Preserve exitstatus of a previous possible redirection
9633          * as POSIX mandates */
9634         return back_exitstatus;
9635 }
9636 static int
9637 evalcommand(union node *cmd, int flags)
9638 {
9639         static const struct builtincmd null_bltin = {
9640                 "\0\0", bltincmd /* why three NULs? */
9641         };
9642         struct localvar_list *localvar_stop;
9643         struct redirtab *redir_stop;
9644         struct stackmark smark;
9645         union node *argp;
9646         struct arglist arglist;
9647         struct arglist varlist;
9648         char **argv;
9649         int argc;
9650         const struct strlist *sp;
9651         struct cmdentry cmdentry;
9652         struct job *jp;
9653         char *lastarg;
9654         const char *path;
9655         int spclbltin;
9656         int status;
9657         char **nargv;
9658         struct builtincmd *bcmd;
9659         smallint cmd_is_exec;
9660         smallint pseudovarflag = 0;
9661
9662         /* First expand the arguments. */
9663         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9664         setstackmark(&smark);
9665         localvar_stop = pushlocalvars();
9666         back_exitstatus = 0;
9667
9668         cmdentry.cmdtype = CMDBUILTIN;
9669         cmdentry.u.cmd = &null_bltin;
9670         varlist.lastp = &varlist.list;
9671         *varlist.lastp = NULL;
9672         arglist.lastp = &arglist.list;
9673         *arglist.lastp = NULL;
9674
9675         argc = 0;
9676         if (cmd->ncmd.args) {
9677                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9678                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9679         }
9680
9681         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9682                 struct strlist **spp;
9683
9684                 spp = arglist.lastp;
9685                 if (pseudovarflag && isassignment(argp->narg.text))
9686                         expandarg(argp, &arglist, EXP_VARTILDE);
9687                 else
9688                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9689
9690                 for (sp = *spp; sp; sp = sp->next)
9691                         argc++;
9692         }
9693
9694         /* Reserve one extra spot at the front for shellexec. */
9695         nargv = stalloc(sizeof(char *) * (argc + 2));
9696         argv = ++nargv;
9697         for (sp = arglist.list; sp; sp = sp->next) {
9698                 TRACE(("evalcommand arg: %s\n", sp->text));
9699                 *nargv++ = sp->text;
9700         }
9701         *nargv = NULL;
9702
9703         lastarg = NULL;
9704         if (iflag && funcnest == 0 && argc > 0)
9705                 lastarg = nargv[-1];
9706
9707         preverrout_fd = 2;
9708         expredir(cmd->ncmd.redirect);
9709         redir_stop = pushredir(cmd->ncmd.redirect);
9710         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9711
9712         path = vpath.var_text;
9713         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9714                 struct strlist **spp;
9715                 char *p;
9716
9717                 spp = varlist.lastp;
9718                 expandarg(argp, &varlist, EXP_VARTILDE);
9719
9720                 mklocal((*spp)->text);
9721
9722                 /*
9723                  * Modify the command lookup path, if a PATH= assignment
9724                  * is present
9725                  */
9726                 p = (*spp)->text;
9727                 if (varcmp(p, path) == 0)
9728                         path = p;
9729         }
9730
9731         /* Print the command if xflag is set. */
9732         if (xflag) {
9733                 const char *pfx = "";
9734
9735                 fdprintf(preverrout_fd, "%s", expandstr(ps4val(), DQSYNTAX));
9736
9737                 sp = varlist.list;
9738                 while (sp) {
9739                         char *varval = sp->text;
9740                         char *eq = strchrnul(varval, '=');
9741                         if (*eq)
9742                                 eq++;
9743                         fdprintf(preverrout_fd, "%s%.*s%s",
9744                                 pfx,
9745                                 (int)(eq - varval), varval,
9746                                 maybe_single_quote(eq)
9747                         );
9748                         sp = sp->next;
9749                         pfx = " ";
9750                 }
9751
9752                 sp = arglist.list;
9753                 while (sp) {
9754                         fdprintf(preverrout_fd, "%s%s",
9755                                 pfx,
9756                                 /* always quote if matches reserved word: */
9757                                 findkwd(sp->text)
9758                                 ? single_quote(sp->text)
9759                                 : maybe_single_quote(sp->text)
9760                         );
9761                         sp = sp->next;
9762                         pfx = " ";
9763                 }
9764                 safe_write(preverrout_fd, "\n", 1);
9765         }
9766
9767         cmd_is_exec = 0;
9768         spclbltin = -1;
9769
9770         /* Now locate the command. */
9771         if (argc) {
9772                 int cmd_flag = DO_ERR;
9773 #if ENABLE_ASH_CMDCMD
9774                 const char *oldpath = path + 5;
9775 #endif
9776                 path += 5;
9777                 for (;;) {
9778                         find_command(argv[0], &cmdentry, cmd_flag, path);
9779                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9780                                 flush_stdout_stderr();
9781                                 status = 127;
9782                                 goto bail;
9783                         }
9784
9785                         /* implement bltin and command here */
9786                         if (cmdentry.cmdtype != CMDBUILTIN)
9787                                 break;
9788                         if (spclbltin < 0)
9789                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9790                         if (cmdentry.u.cmd == EXECCMD)
9791                                 cmd_is_exec = 1;
9792 #if ENABLE_ASH_CMDCMD
9793                         if (cmdentry.u.cmd == COMMANDCMD) {
9794                                 path = oldpath;
9795                                 nargv = parse_command_args(argv, &path);
9796                                 if (!nargv)
9797                                         break;
9798                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9799                                  * nargv => "PROG". path is updated if -p.
9800                                  */
9801                                 argc -= nargv - argv;
9802                                 argv = nargv;
9803                                 cmd_flag |= DO_NOFUNC;
9804                         } else
9805 #endif
9806                                 break;
9807                 }
9808         }
9809
9810         if (status) {
9811  bail:
9812                 exitstatus = status;
9813
9814                 /* We have a redirection error. */
9815                 if (spclbltin > 0)
9816                         raise_exception(EXERROR);
9817
9818                 goto out;
9819         }
9820
9821         /* Execute the command. */
9822         switch (cmdentry.cmdtype) {
9823         default: {
9824
9825 #if ENABLE_FEATURE_SH_NOFORK
9826 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9827  *     around run_nofork_applet() call.
9828  * (2) Should this check also be done in forkshell()?
9829  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9830  */
9831                 /* find_command() encodes applet_no as (-2 - applet_no) */
9832                 int applet_no = (- cmdentry.u.index - 2);
9833                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9834                         listsetvar(varlist.list, VEXPORT|VSTACK);
9835                         /* run <applet>_main() */
9836                         status = run_nofork_applet(applet_no, argv);
9837                         break;
9838                 }
9839 #endif
9840                 /* Can we avoid forking off? For example, very last command
9841                  * in a script or a subshell does not need forking,
9842                  * we can just exec it.
9843                  */
9844                 if (!(flags & EV_EXIT) || may_have_traps) {
9845                         /* No, forking off a child is necessary */
9846                         INT_OFF;
9847                         get_tty_state();
9848                         jp = makejob(/*cmd,*/ 1);
9849                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9850                                 /* parent */
9851                                 status = waitforjob(jp);
9852                                 INT_ON;
9853                                 TRACE(("forked child exited with %d\n", status));
9854                                 break;
9855                         }
9856                         /* child */
9857                         FORCE_INT_ON;
9858                         /* fall through to exec'ing external program */
9859                 }
9860                 listsetvar(varlist.list, VEXPORT|VSTACK);
9861                 shellexec(argv[0], argv, path, cmdentry.u.index);
9862                 /* NOTREACHED */
9863         } /* default */
9864         case CMDBUILTIN:
9865                 if (spclbltin > 0 || argc == 0) {
9866                         poplocalvars(1);
9867                         if (cmd_is_exec && argc > 1)
9868                                 listsetvar(varlist.list, VEXPORT);
9869                 }
9870
9871                 /* Tight loop with builtins only:
9872                  * "while kill -0 $child; do true; done"
9873                  * will never exit even if $child died, unless we do this
9874                  * to reap the zombie and make kill detect that it's gone: */
9875                 dowait(DOWAIT_NONBLOCK, NULL);
9876
9877                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9878                         if (exception_type == EXERROR && spclbltin <= 0) {
9879                                 FORCE_INT_ON;
9880                                 goto readstatus;
9881                         }
9882  raise:
9883                         longjmp(exception_handler->loc, 1);
9884                 }
9885                 goto readstatus;
9886
9887         case CMDFUNCTION:
9888                 poplocalvars(1);
9889                 /* See above for the rationale */
9890                 dowait(DOWAIT_NONBLOCK, NULL);
9891                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9892                         goto raise;
9893  readstatus:
9894                 status = exitstatus;
9895                 break;
9896         } /* switch */
9897
9898  out:
9899         if (cmd->ncmd.redirect)
9900                 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9901         unwindredir(redir_stop);
9902         unwindlocalvars(localvar_stop);
9903         if (lastarg) {
9904                 /* dsl: I think this is intended to be used to support
9905                  * '_' in 'vi' command mode during line editing...
9906                  * However I implemented that within libedit itself.
9907                  */
9908                 setvar0("_", lastarg);
9909         }
9910         popstackmark(&smark);
9911
9912         return status;
9913 }
9914
9915 static int
9916 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9917 {
9918         char *volatile savecmdname;
9919         struct jmploc *volatile savehandler;
9920         struct jmploc jmploc;
9921         int status;
9922         int i;
9923
9924         savecmdname = commandname;
9925         savehandler = exception_handler;
9926         i = setjmp(jmploc.loc);
9927         if (i)
9928                 goto cmddone;
9929         exception_handler = &jmploc;
9930         commandname = argv[0];
9931         argptr = argv + 1;
9932         optptr = NULL;                  /* initialize nextopt */
9933         if (cmd == EVALCMD)
9934                 status = evalcmd(argc, argv, flags);
9935         else
9936                 status = (*cmd->builtin)(argc, argv);
9937         flush_stdout_stderr();
9938         status |= ferror(stdout);
9939         exitstatus = status;
9940  cmddone:
9941         clearerr(stdout);
9942         commandname = savecmdname;
9943         exception_handler = savehandler;
9944
9945         return i;
9946 }
9947
9948 static int
9949 goodname(const char *p)
9950 {
9951         return endofname(p)[0] == '\0';
9952 }
9953
9954
9955 /*
9956  * Search for a command.  This is called before we fork so that the
9957  * location of the command will be available in the parent as well as
9958  * the child.  The check for "goodname" is an overly conservative
9959  * check that the name will not be subject to expansion.
9960  */
9961 static void
9962 prehash(union node *n)
9963 {
9964         struct cmdentry entry;
9965
9966         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9967                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9968 }
9969
9970
9971 /* ============ Builtin commands
9972  *
9973  * Builtin commands whose functions are closely tied to evaluation
9974  * are implemented here.
9975  */
9976
9977 /*
9978  * Handle break and continue commands.  Break, continue, and return are
9979  * all handled by setting the evalskip flag.  The evaluation routines
9980  * above all check this flag, and if it is set they start skipping
9981  * commands rather than executing them.  The variable skipcount is
9982  * the number of loops to break/continue, or the number of function
9983  * levels to return.  (The latter is always 1.)  It should probably
9984  * be an error to break out of more loops than exist, but it isn't
9985  * in the standard shell so we don't make it one here.
9986  */
9987 static int FAST_FUNC
9988 breakcmd(int argc UNUSED_PARAM, char **argv)
9989 {
9990         int n = argv[1] ? number(argv[1]) : 1;
9991
9992         if (n <= 0)
9993                 ash_msg_and_raise_error(msg_illnum, argv[1]);
9994         if (n > loopnest)
9995                 n = loopnest;
9996         if (n > 0) {
9997                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9998                 skipcount = n;
9999         }
10000         return 0;
10001 }
10002
10003
10004 /*
10005  * This implements the input routines used by the parser.
10006  */
10007
10008 enum {
10009         INPUT_PUSH_FILE = 1,
10010         INPUT_NOFILE_OK = 2,
10011 };
10012
10013 static smallint checkkwd;
10014 /* values of checkkwd variable */
10015 #define CHKALIAS        0x1
10016 #define CHKKWD          0x2
10017 #define CHKNL           0x4
10018 #define CHKEOFMARK      0x8
10019
10020 /*
10021  * Push a string back onto the input at this current parsefile level.
10022  * We handle aliases this way.
10023  */
10024 #if !ENABLE_ASH_ALIAS
10025 #define pushstring(s, ap) pushstring(s)
10026 #endif
10027 static void
10028 pushstring(char *s, struct alias *ap)
10029 {
10030         struct strpush *sp;
10031         int len;
10032
10033         len = strlen(s);
10034         INT_OFF;
10035         if (g_parsefile->strpush) {
10036                 sp = ckzalloc(sizeof(*sp));
10037                 sp->prev = g_parsefile->strpush;
10038         } else {
10039                 sp = &(g_parsefile->basestrpush);
10040         }
10041         g_parsefile->strpush = sp;
10042         sp->prev_string = g_parsefile->next_to_pgetc;
10043         sp->prev_left_in_line = g_parsefile->left_in_line;
10044         sp->unget = g_parsefile->unget;
10045         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10046 #if ENABLE_ASH_ALIAS
10047         sp->ap = ap;
10048         if (ap) {
10049                 ap->flag |= ALIASINUSE;
10050                 sp->string = s;
10051         }
10052 #endif
10053         g_parsefile->next_to_pgetc = s;
10054         g_parsefile->left_in_line = len;
10055         g_parsefile->unget = 0;
10056         INT_ON;
10057 }
10058
10059 static void
10060 popstring(void)
10061 {
10062         struct strpush *sp = g_parsefile->strpush;
10063
10064         INT_OFF;
10065 #if ENABLE_ASH_ALIAS
10066         if (sp->ap) {
10067                 if (g_parsefile->next_to_pgetc[-1] == ' '
10068                  || g_parsefile->next_to_pgetc[-1] == '\t'
10069                 ) {
10070                         checkkwd |= CHKALIAS;
10071                 }
10072                 if (sp->string != sp->ap->val) {
10073                         free(sp->string);
10074                 }
10075                 sp->ap->flag &= ~ALIASINUSE;
10076                 if (sp->ap->flag & ALIASDEAD) {
10077                         unalias(sp->ap->name);
10078                 }
10079         }
10080 #endif
10081         g_parsefile->next_to_pgetc = sp->prev_string;
10082         g_parsefile->left_in_line = sp->prev_left_in_line;
10083         g_parsefile->unget = sp->unget;
10084         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10085         g_parsefile->strpush = sp->prev;
10086         if (sp != &(g_parsefile->basestrpush))
10087                 free(sp);
10088         INT_ON;
10089 }
10090
10091 static int
10092 preadfd(void)
10093 {
10094         int nr;
10095         char *buf = g_parsefile->buf;
10096
10097         g_parsefile->next_to_pgetc = buf;
10098 #if ENABLE_FEATURE_EDITING
10099  retry:
10100         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10101                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10102         else {
10103                 int timeout = -1;
10104 # if ENABLE_ASH_IDLE_TIMEOUT
10105                 if (iflag) {
10106                         const char *tmout_var = lookupvar("TMOUT");
10107                         if (tmout_var) {
10108                                 timeout = atoi(tmout_var) * 1000;
10109                                 if (timeout <= 0)
10110                                         timeout = -1;
10111                         }
10112                 }
10113 # endif
10114 # if ENABLE_FEATURE_TAB_COMPLETION
10115                 line_input_state->path_lookup = pathval();
10116 # endif
10117                 reinit_unicode_for_ash();
10118                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
10119                 if (nr == 0) {
10120                         /* ^C pressed, "convert" to SIGINT */
10121                         write(STDOUT_FILENO, "^C", 2);
10122                         if (trap[SIGINT]) {
10123                                 buf[0] = '\n';
10124                                 buf[1] = '\0';
10125                                 raise(SIGINT);
10126                                 return 1;
10127                         }
10128                         exitstatus = 128 + SIGINT;
10129                         bb_putchar('\n');
10130                         goto retry;
10131                 }
10132                 if (nr < 0) {
10133                         if (errno == 0) {
10134                                 /* Ctrl+D pressed */
10135                                 nr = 0;
10136                         }
10137 # if ENABLE_ASH_IDLE_TIMEOUT
10138                         else if (errno == EAGAIN && timeout > 0) {
10139                                 puts("\007timed out waiting for input: auto-logout");
10140                                 exitshell();
10141                         }
10142 # endif
10143                 }
10144         }
10145 #else
10146         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10147 #endif
10148
10149 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10150         if (nr < 0) {
10151                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10152                         int flags = fcntl(0, F_GETFL);
10153                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10154                                 flags &= ~O_NONBLOCK;
10155                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10156                                         out2str("sh: turning off NDELAY mode\n");
10157                                         goto retry;
10158                                 }
10159                         }
10160                 }
10161         }
10162 #endif
10163         return nr;
10164 }
10165
10166 /*
10167  * Refill the input buffer and return the next input character:
10168  *
10169  * 1) If a string was pushed back on the input, pop it;
10170  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10171  *    or we are reading from a string so we can't refill the buffer,
10172  *    return EOF.
10173  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10174  * 4) Process input up to the next newline, deleting nul characters.
10175  */
10176 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10177 #define pgetc_debug(...) ((void)0)
10178 static int pgetc(void);
10179 static int
10180 preadbuffer(void)
10181 {
10182         char *q;
10183         int more;
10184
10185         if (g_parsefile->strpush) {
10186 #if ENABLE_ASH_ALIAS
10187                 if (g_parsefile->left_in_line == -1
10188                  && g_parsefile->strpush->ap
10189                  && g_parsefile->next_to_pgetc[-1] != ' '
10190                  && g_parsefile->next_to_pgetc[-1] != '\t'
10191                 ) {
10192                         pgetc_debug("preadbuffer PEOA");
10193                         return PEOA;
10194                 }
10195 #endif
10196                 popstring();
10197                 return pgetc();
10198         }
10199         /* on both branches above g_parsefile->left_in_line < 0.
10200          * "pgetc" needs refilling.
10201          */
10202
10203         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10204          * pungetc() may increment it a few times.
10205          * Assuming it won't increment it to less than -90.
10206          */
10207         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10208                 pgetc_debug("preadbuffer PEOF1");
10209                 /* even in failure keep left_in_line and next_to_pgetc
10210                  * in lock step, for correct multi-layer pungetc.
10211                  * left_in_line was decremented before preadbuffer(),
10212                  * must inc next_to_pgetc: */
10213                 g_parsefile->next_to_pgetc++;
10214                 return PEOF;
10215         }
10216
10217         more = g_parsefile->left_in_buffer;
10218         if (more <= 0) {
10219                 flush_stdout_stderr();
10220  again:
10221                 more = preadfd();
10222                 if (more <= 0) {
10223                         /* don't try reading again */
10224                         g_parsefile->left_in_line = -99;
10225                         pgetc_debug("preadbuffer PEOF2");
10226                         g_parsefile->next_to_pgetc++;
10227                         return PEOF;
10228                 }
10229         }
10230
10231         /* Find out where's the end of line.
10232          * Set g_parsefile->left_in_line
10233          * and g_parsefile->left_in_buffer acordingly.
10234          * NUL chars are deleted.
10235          */
10236         q = g_parsefile->next_to_pgetc;
10237         for (;;) {
10238                 char c;
10239
10240                 more--;
10241
10242                 c = *q;
10243                 if (c == '\0') {
10244                         memmove(q, q + 1, more);
10245                 } else {
10246                         q++;
10247                         if (c == '\n') {
10248                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10249                                 break;
10250                         }
10251                 }
10252
10253                 if (more <= 0) {
10254                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10255                         if (g_parsefile->left_in_line < 0)
10256                                 goto again;
10257                         break;
10258                 }
10259         }
10260         g_parsefile->left_in_buffer = more;
10261
10262         if (vflag) {
10263                 char save = *q;
10264                 *q = '\0';
10265                 out2str(g_parsefile->next_to_pgetc);
10266                 *q = save;
10267         }
10268
10269         pgetc_debug("preadbuffer at %d:%p'%s'",
10270                         g_parsefile->left_in_line,
10271                         g_parsefile->next_to_pgetc,
10272                         g_parsefile->next_to_pgetc);
10273         return (unsigned char)*g_parsefile->next_to_pgetc++;
10274 }
10275
10276 static void
10277 nlprompt(void)
10278 {
10279         g_parsefile->linno++;
10280         setprompt_if(doprompt, 2);
10281 }
10282 static void
10283 nlnoprompt(void)
10284 {
10285         g_parsefile->linno++;
10286         needprompt = doprompt;
10287 }
10288
10289 static int
10290 pgetc(void)
10291 {
10292         int c;
10293
10294         pgetc_debug("pgetc at %d:%p'%s'",
10295                         g_parsefile->left_in_line,
10296                         g_parsefile->next_to_pgetc,
10297                         g_parsefile->next_to_pgetc);
10298         if (g_parsefile->unget)
10299                 return g_parsefile->lastc[--g_parsefile->unget];
10300
10301         if (--g_parsefile->left_in_line >= 0)
10302                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10303         else
10304                 c = preadbuffer();
10305
10306         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10307         g_parsefile->lastc[0] = c;
10308
10309         return c;
10310 }
10311
10312 #if ENABLE_ASH_ALIAS
10313 static int
10314 pgetc_without_PEOA(void)
10315 {
10316         int c;
10317         do {
10318                 pgetc_debug("pgetc at %d:%p'%s'",
10319                                 g_parsefile->left_in_line,
10320                                 g_parsefile->next_to_pgetc,
10321                                 g_parsefile->next_to_pgetc);
10322                 c = pgetc();
10323         } while (c == PEOA);
10324         return c;
10325 }
10326 #else
10327 # define pgetc_without_PEOA() pgetc()
10328 #endif
10329
10330 /*
10331  * Undo a call to pgetc.  Only two characters may be pushed back.
10332  * PEOF may be pushed back.
10333  */
10334 static void
10335 pungetc(void)
10336 {
10337         g_parsefile->unget++;
10338 }
10339
10340 /* This one eats backslash+newline */
10341 static int
10342 pgetc_eatbnl(void)
10343 {
10344         int c;
10345
10346         while ((c = pgetc()) == '\\') {
10347                 if (pgetc() != '\n') {
10348                         pungetc();
10349                         break;
10350                 }
10351
10352                 nlprompt();
10353         }
10354
10355         return c;
10356 }
10357
10358 /*
10359  * To handle the "." command, a stack of input files is used.  Pushfile
10360  * adds a new entry to the stack and popfile restores the previous level.
10361  */
10362 static void
10363 pushfile(void)
10364 {
10365         struct parsefile *pf;
10366
10367         pf = ckzalloc(sizeof(*pf));
10368         pf->prev = g_parsefile;
10369         pf->pf_fd = -1;
10370         /*pf->strpush = NULL; - ckzalloc did it */
10371         /*pf->basestrpush.prev = NULL;*/
10372         /*pf->unget = 0;*/
10373         g_parsefile = pf;
10374 }
10375
10376 static void
10377 popfile(void)
10378 {
10379         struct parsefile *pf = g_parsefile;
10380
10381         if (pf == &basepf)
10382                 return;
10383
10384         INT_OFF;
10385         if (pf->pf_fd >= 0)
10386                 close(pf->pf_fd);
10387         free(pf->buf);
10388         while (pf->strpush)
10389                 popstring();
10390         g_parsefile = pf->prev;
10391         free(pf);
10392         INT_ON;
10393 }
10394
10395 /*
10396  * Return to top level.
10397  */
10398 static void
10399 popallfiles(void)
10400 {
10401         while (g_parsefile != &basepf)
10402                 popfile();
10403 }
10404
10405 /*
10406  * Close the file(s) that the shell is reading commands from.  Called
10407  * after a fork is done.
10408  */
10409 static void
10410 closescript(void)
10411 {
10412         popallfiles();
10413         if (g_parsefile->pf_fd > 0) {
10414                 close(g_parsefile->pf_fd);
10415                 g_parsefile->pf_fd = 0;
10416         }
10417 }
10418
10419 /*
10420  * Like setinputfile, but takes an open file descriptor.  Call this with
10421  * interrupts off.
10422  */
10423 static void
10424 setinputfd(int fd, int push)
10425 {
10426         if (push) {
10427                 pushfile();
10428                 g_parsefile->buf = NULL;
10429         }
10430         g_parsefile->pf_fd = fd;
10431         if (g_parsefile->buf == NULL)
10432                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10433         g_parsefile->left_in_buffer = 0;
10434         g_parsefile->left_in_line = 0;
10435         g_parsefile->linno = 1;
10436 }
10437
10438 /*
10439  * Set the input to take input from a file.  If push is set, push the
10440  * old input onto the stack first.
10441  */
10442 static int
10443 setinputfile(const char *fname, int flags)
10444 {
10445         int fd;
10446
10447         INT_OFF;
10448         fd = open(fname, O_RDONLY);
10449         if (fd < 0) {
10450                 if (flags & INPUT_NOFILE_OK)
10451                         goto out;
10452                 exitstatus = 127;
10453                 ash_msg_and_raise_error("can't open '%s'", fname);
10454         }
10455         if (fd < 10)
10456                 fd = savefd(fd);
10457         else
10458                 close_on_exec_on(fd);
10459         setinputfd(fd, flags & INPUT_PUSH_FILE);
10460  out:
10461         INT_ON;
10462         return fd;
10463 }
10464
10465 /*
10466  * Like setinputfile, but takes input from a string.
10467  */
10468 static void
10469 setinputstring(char *string)
10470 {
10471         INT_OFF;
10472         pushfile();
10473         g_parsefile->next_to_pgetc = string;
10474         g_parsefile->left_in_line = strlen(string);
10475         g_parsefile->buf = NULL;
10476         g_parsefile->linno = 1;
10477         INT_ON;
10478 }
10479
10480
10481 /*
10482  * Routines to check for mail.
10483  */
10484
10485 #if ENABLE_ASH_MAIL
10486
10487 /* Hash of mtimes of mailboxes */
10488 static unsigned mailtime_hash;
10489 /* Set if MAIL or MAILPATH is changed. */
10490 static smallint mail_var_path_changed;
10491
10492 /*
10493  * Print appropriate message(s) if mail has arrived.
10494  * If mail_var_path_changed is set,
10495  * then the value of MAIL has mail_var_path_changed,
10496  * so we just update the values.
10497  */
10498 static void
10499 chkmail(void)
10500 {
10501         const char *mpath;
10502         char *p;
10503         char *q;
10504         unsigned new_hash;
10505         struct stackmark smark;
10506         struct stat statb;
10507
10508         setstackmark(&smark);
10509         mpath = mpathset() ? mpathval() : mailval();
10510         new_hash = 0;
10511         for (;;) {
10512                 p = path_advance(&mpath, nullstr);
10513                 if (p == NULL)
10514                         break;
10515                 if (*p == '\0')
10516                         continue;
10517                 for (q = p; *q; q++)
10518                         continue;
10519 #if DEBUG
10520                 if (q[-1] != '/')
10521                         abort();
10522 #endif
10523                 q[-1] = '\0';                   /* delete trailing '/' */
10524                 if (stat(p, &statb) < 0) {
10525                         continue;
10526                 }
10527                 /* Very simplistic "hash": just a sum of all mtimes */
10528                 new_hash += (unsigned)statb.st_mtime;
10529         }
10530         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10531                 if (mailtime_hash != 0)
10532                         out2str("you have mail\n");
10533                 mailtime_hash = new_hash;
10534         }
10535         mail_var_path_changed = 0;
10536         popstackmark(&smark);
10537 }
10538
10539 static void FAST_FUNC
10540 changemail(const char *val UNUSED_PARAM)
10541 {
10542         mail_var_path_changed = 1;
10543 }
10544
10545 #endif /* ASH_MAIL */
10546
10547
10548 /* ============ ??? */
10549
10550 /*
10551  * Set the shell parameters.
10552  */
10553 static void
10554 setparam(char **argv)
10555 {
10556         char **newparam;
10557         char **ap;
10558         int nparam;
10559
10560         for (nparam = 0; argv[nparam]; nparam++)
10561                 continue;
10562         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10563         while (*argv) {
10564                 *ap++ = ckstrdup(*argv++);
10565         }
10566         *ap = NULL;
10567         freeparam(&shellparam);
10568         shellparam.malloced = 1;
10569         shellparam.nparam = nparam;
10570         shellparam.p = newparam;
10571 #if ENABLE_ASH_GETOPTS
10572         shellparam.optind = 1;
10573         shellparam.optoff = -1;
10574 #endif
10575 }
10576
10577 /*
10578  * Process shell options.  The global variable argptr contains a pointer
10579  * to the argument list; we advance it past the options.
10580  *
10581  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10582  * For a non-interactive shell, an error condition encountered
10583  * by a special built-in ... shall cause the shell to write a diagnostic message
10584  * to standard error and exit as shown in the following table:
10585  * Error                                           Special Built-In
10586  * ...
10587  * Utility syntax error (option or operand error)  Shall exit
10588  * ...
10589  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10590  * we see that bash does not do that (set "finishes" with error code 1 instead,
10591  * and shell continues), and people rely on this behavior!
10592  * Testcase:
10593  * set -o barfoo 2>/dev/null
10594  * echo $?
10595  *
10596  * Oh well. Let's mimic that.
10597  */
10598 static int
10599 plus_minus_o(char *name, int val)
10600 {
10601         int i;
10602
10603         if (name) {
10604                 for (i = 0; i < NOPTS; i++) {
10605                         if (strcmp(name, optnames(i)) == 0) {
10606                                 optlist[i] = val;
10607                                 return 0;
10608                         }
10609                 }
10610                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10611                 return 1;
10612         }
10613         for (i = 0; i < NOPTS; i++) {
10614                 if (val) {
10615                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10616                 } else {
10617                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10618                 }
10619         }
10620         return 0;
10621 }
10622 static void
10623 setoption(int flag, int val)
10624 {
10625         int i;
10626
10627         for (i = 0; i < NOPTS; i++) {
10628                 if (optletters(i) == flag) {
10629                         optlist[i] = val;
10630                         return;
10631                 }
10632         }
10633         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10634         /* NOTREACHED */
10635 }
10636 static int
10637 options(int cmdline)
10638 {
10639         char *p;
10640         int val;
10641         int c;
10642
10643         if (cmdline)
10644                 minusc = NULL;
10645         while ((p = *argptr) != NULL) {
10646                 c = *p++;
10647                 if (c != '-' && c != '+')
10648                         break;
10649                 argptr++;
10650                 val = 0; /* val = 0 if c == '+' */
10651                 if (c == '-') {
10652                         val = 1;
10653                         if (p[0] == '\0' || LONE_DASH(p)) {
10654                                 if (!cmdline) {
10655                                         /* "-" means turn off -x and -v */
10656                                         if (p[0] == '\0')
10657                                                 xflag = vflag = 0;
10658                                         /* "--" means reset params */
10659                                         else if (*argptr == NULL)
10660                                                 setparam(argptr);
10661                                 }
10662                                 break;    /* "-" or "--" terminates options */
10663                         }
10664                 }
10665                 /* first char was + or - */
10666                 while ((c = *p++) != '\0') {
10667                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10668                         if (c == 'c' && cmdline) {
10669                                 minusc = p;     /* command is after shell args */
10670                         } else if (c == 'o') {
10671                                 if (plus_minus_o(*argptr, val)) {
10672                                         /* it already printed err message */
10673                                         return 1; /* error */
10674                                 }
10675                                 if (*argptr)
10676                                         argptr++;
10677                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10678                                 isloginsh = 1;
10679                         /* bash does not accept +-login, we also won't */
10680                         } else if (cmdline && val && (c == '-')) { /* long options */
10681                                 if (strcmp(p, "login") == 0)
10682                                         isloginsh = 1;
10683                                 break;
10684                         } else {
10685                                 setoption(c, val);
10686                         }
10687                 }
10688         }
10689         return 0;
10690 }
10691
10692 /*
10693  * The shift builtin command.
10694  */
10695 static int FAST_FUNC
10696 shiftcmd(int argc UNUSED_PARAM, char **argv)
10697 {
10698         int n;
10699         char **ap1, **ap2;
10700
10701         n = 1;
10702         if (argv[1])
10703                 n = number(argv[1]);
10704         if (n > shellparam.nparam)
10705                 n = 0; /* bash compat, was = shellparam.nparam; */
10706         INT_OFF;
10707         shellparam.nparam -= n;
10708         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10709                 if (shellparam.malloced)
10710                         free(*ap1);
10711         }
10712         ap2 = shellparam.p;
10713         while ((*ap2++ = *ap1++) != NULL)
10714                 continue;
10715 #if ENABLE_ASH_GETOPTS
10716         shellparam.optind = 1;
10717         shellparam.optoff = -1;
10718 #endif
10719         INT_ON;
10720         return 0;
10721 }
10722
10723 /*
10724  * POSIX requires that 'set' (but not export or readonly) output the
10725  * variables in lexicographic order - by the locale's collating order (sigh).
10726  * Maybe we could keep them in an ordered balanced binary tree
10727  * instead of hashed lists.
10728  * For now just roll 'em through qsort for printing...
10729  */
10730 static int
10731 showvars(const char *sep_prefix, int on, int off)
10732 {
10733         const char *sep;
10734         char **ep, **epend;
10735
10736         ep = listvars(on, off, &epend);
10737         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10738
10739         sep = *sep_prefix ? " " : sep_prefix;
10740
10741         for (; ep < epend; ep++) {
10742                 const char *p;
10743                 const char *q;
10744
10745                 p = strchrnul(*ep, '=');
10746                 q = nullstr;
10747                 if (*p)
10748                         q = single_quote(++p);
10749                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10750         }
10751         return 0;
10752 }
10753
10754 /*
10755  * The set command builtin.
10756  */
10757 static int FAST_FUNC
10758 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10759 {
10760         int retval;
10761
10762         if (!argv[1])
10763                 return showvars(nullstr, 0, VUNSET);
10764
10765         INT_OFF;
10766         retval = options(/*cmdline:*/ 0);
10767         if (retval == 0) { /* if no parse error... */
10768                 optschanged();
10769                 if (*argptr != NULL) {
10770                         setparam(argptr);
10771                 }
10772         }
10773         INT_ON;
10774         return retval;
10775 }
10776
10777 #if ENABLE_ASH_RANDOM_SUPPORT
10778 static void FAST_FUNC
10779 change_random(const char *value)
10780 {
10781         uint32_t t;
10782
10783         if (value == NULL) {
10784                 /* "get", generate */
10785                 t = next_random(&random_gen);
10786                 /* set without recursion */
10787                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10788                 vrandom.flags &= ~VNOFUNC;
10789         } else {
10790                 /* set/reset */
10791                 t = strtoul(value, NULL, 10);
10792                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10793         }
10794 }
10795 #endif
10796
10797 #if ENABLE_ASH_GETOPTS
10798 static int
10799 getopts(char *optstr, char *optvar, char **optfirst)
10800 {
10801         char *p, *q;
10802         char c = '?';
10803         int done = 0;
10804         char sbuf[2];
10805         char **optnext;
10806         int ind = shellparam.optind;
10807         int off = shellparam.optoff;
10808
10809         sbuf[1] = '\0';
10810
10811         shellparam.optind = -1;
10812         optnext = optfirst + ind - 1;
10813
10814         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10815                 p = NULL;
10816         else
10817                 p = optnext[-1] + off;
10818         if (p == NULL || *p == '\0') {
10819                 /* Current word is done, advance */
10820                 p = *optnext;
10821                 if (p == NULL || *p != '-' || *++p == '\0') {
10822  atend:
10823                         p = NULL;
10824                         done = 1;
10825                         goto out;
10826                 }
10827                 optnext++;
10828                 if (LONE_DASH(p))        /* check for "--" */
10829                         goto atend;
10830         }
10831
10832         c = *p++;
10833         for (q = optstr; *q != c;) {
10834                 if (*q == '\0') {
10835                         if (optstr[0] == ':') {
10836                                 sbuf[0] = c;
10837                                 /*sbuf[1] = '\0'; - already is */
10838                                 setvar0("OPTARG", sbuf);
10839                         } else {
10840                                 fprintf(stderr, "Illegal option -%c\n", c);
10841                                 unsetvar("OPTARG");
10842                         }
10843                         c = '?';
10844                         goto out;
10845                 }
10846                 if (*++q == ':')
10847                         q++;
10848         }
10849
10850         if (*++q == ':') {
10851                 if (*p == '\0' && (p = *optnext) == NULL) {
10852                         if (optstr[0] == ':') {
10853                                 sbuf[0] = c;
10854                                 /*sbuf[1] = '\0'; - already is */
10855                                 setvar0("OPTARG", sbuf);
10856                                 c = ':';
10857                         } else {
10858                                 fprintf(stderr, "No arg for -%c option\n", c);
10859                                 unsetvar("OPTARG");
10860                                 c = '?';
10861                         }
10862                         goto out;
10863                 }
10864
10865                 if (p == *optnext)
10866                         optnext++;
10867                 setvar0("OPTARG", p);
10868                 p = NULL;
10869         } else
10870                 setvar0("OPTARG", nullstr);
10871  out:
10872         ind = optnext - optfirst + 1;
10873         setvar("OPTIND", itoa(ind), VNOFUNC);
10874         sbuf[0] = c;
10875         /*sbuf[1] = '\0'; - already is */
10876         setvar0(optvar, sbuf);
10877
10878         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10879         shellparam.optind = ind;
10880
10881         return done;
10882 }
10883
10884 /*
10885  * The getopts builtin.  Shellparam.optnext points to the next argument
10886  * to be processed.  Shellparam.optptr points to the next character to
10887  * be processed in the current argument.  If shellparam.optnext is NULL,
10888  * then it's the first time getopts has been called.
10889  */
10890 static int FAST_FUNC
10891 getoptscmd(int argc, char **argv)
10892 {
10893         char **optbase;
10894
10895         if (argc < 3)
10896                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10897         if (argc == 3) {
10898                 optbase = shellparam.p;
10899                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10900                         shellparam.optind = 1;
10901                         shellparam.optoff = -1;
10902                 }
10903         } else {
10904                 optbase = &argv[3];
10905                 if ((unsigned)shellparam.optind > argc - 2) {
10906                         shellparam.optind = 1;
10907                         shellparam.optoff = -1;
10908                 }
10909         }
10910
10911         return getopts(argv[1], argv[2], optbase);
10912 }
10913 #endif /* ASH_GETOPTS */
10914
10915
10916 /* ============ Shell parser */
10917
10918 struct heredoc {
10919         struct heredoc *next;   /* next here document in list */
10920         union node *here;       /* redirection node */
10921         char *eofmark;          /* string indicating end of input */
10922         smallint striptabs;     /* if set, strip leading tabs */
10923 };
10924
10925 static smallint tokpushback;           /* last token pushed back */
10926 static smallint quoteflag;             /* set if (part of) last token was quoted */
10927 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10928 static struct heredoc *heredoclist;    /* list of here documents to read */
10929 static char *wordtext;                 /* text of last word returned by readtoken */
10930 static struct nodelist *backquotelist;
10931 static union node *redirnode;
10932 static struct heredoc *heredoc;
10933
10934 static const char *
10935 tokname(char *buf, int tok)
10936 {
10937         if (tok < TSEMI)
10938                 return tokname_array[tok];
10939         sprintf(buf, "\"%s\"", tokname_array[tok]);
10940         return buf;
10941 }
10942
10943 /* raise_error_unexpected_syntax:
10944  * Called when an unexpected token is read during the parse.  The argument
10945  * is the token that is expected, or -1 if more than one type of token can
10946  * occur at this point.
10947  */
10948 static void raise_error_unexpected_syntax(int) NORETURN;
10949 static void
10950 raise_error_unexpected_syntax(int token)
10951 {
10952         char msg[64];
10953         char buf[16];
10954         int l;
10955
10956         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10957         if (token >= 0)
10958                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10959         raise_error_syntax(msg);
10960         /* NOTREACHED */
10961 }
10962
10963 /* parsing is heavily cross-recursive, need these forward decls */
10964 static union node *andor(void);
10965 static union node *pipeline(void);
10966 static union node *parse_command(void);
10967 static void parseheredoc(void);
10968 static int peektoken(void);
10969 static int readtoken(void);
10970
10971 static union node *
10972 list(int nlflag)
10973 {
10974         union node *n1, *n2, *n3;
10975         int tok;
10976
10977         n1 = NULL;
10978         for (;;) {
10979                 switch (peektoken()) {
10980                 case TNL:
10981                         if (!(nlflag & 1))
10982                                 break;
10983                         parseheredoc();
10984                         return n1;
10985
10986                 case TEOF:
10987                         if (!n1 && (nlflag & 1))
10988                                 n1 = NODE_EOF;
10989                         parseheredoc();
10990                         return n1;
10991                 }
10992
10993                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10994                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
10995                         return n1;
10996                 nlflag |= 2;
10997
10998                 n2 = andor();
10999                 tok = readtoken();
11000                 if (tok == TBACKGND) {
11001                         if (n2->type == NPIPE) {
11002                                 n2->npipe.pipe_backgnd = 1;
11003                         } else {
11004                                 if (n2->type != NREDIR) {
11005                                         n3 = stzalloc(sizeof(struct nredir));
11006                                         n3->nredir.n = n2;
11007                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11008                                         n2 = n3;
11009                                 }
11010                                 n2->type = NBACKGND;
11011                         }
11012                 }
11013                 if (n1 == NULL) {
11014                         n1 = n2;
11015                 } else {
11016                         n3 = stzalloc(sizeof(struct nbinary));
11017                         n3->type = NSEMI;
11018                         n3->nbinary.ch1 = n1;
11019                         n3->nbinary.ch2 = n2;
11020                         n1 = n3;
11021                 }
11022                 switch (tok) {
11023                 case TNL:
11024                 case TEOF:
11025                         tokpushback = 1;
11026                         /* fall through */
11027                 case TBACKGND:
11028                 case TSEMI:
11029                         break;
11030                 default:
11031                         if ((nlflag & 1))
11032                                 raise_error_unexpected_syntax(-1);
11033                         tokpushback = 1;
11034                         return n1;
11035                 }
11036         }
11037 }
11038
11039 static union node *
11040 andor(void)
11041 {
11042         union node *n1, *n2, *n3;
11043         int t;
11044
11045         n1 = pipeline();
11046         for (;;) {
11047                 t = readtoken();
11048                 if (t == TAND) {
11049                         t = NAND;
11050                 } else if (t == TOR) {
11051                         t = NOR;
11052                 } else {
11053                         tokpushback = 1;
11054                         return n1;
11055                 }
11056                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11057                 n2 = pipeline();
11058                 n3 = stzalloc(sizeof(struct nbinary));
11059                 n3->type = t;
11060                 n3->nbinary.ch1 = n1;
11061                 n3->nbinary.ch2 = n2;
11062                 n1 = n3;
11063         }
11064 }
11065
11066 static union node *
11067 pipeline(void)
11068 {
11069         union node *n1, *n2, *pipenode;
11070         struct nodelist *lp, *prev;
11071         int negate;
11072
11073         negate = 0;
11074         TRACE(("pipeline: entered\n"));
11075         if (readtoken() == TNOT) {
11076                 negate = !negate;
11077                 checkkwd = CHKKWD | CHKALIAS;
11078         } else
11079                 tokpushback = 1;
11080         n1 = parse_command();
11081         if (readtoken() == TPIPE) {
11082                 pipenode = stzalloc(sizeof(struct npipe));
11083                 pipenode->type = NPIPE;
11084                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11085                 lp = stzalloc(sizeof(struct nodelist));
11086                 pipenode->npipe.cmdlist = lp;
11087                 lp->n = n1;
11088                 do {
11089                         prev = lp;
11090                         lp = stzalloc(sizeof(struct nodelist));
11091                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11092                         lp->n = parse_command();
11093                         prev->next = lp;
11094                 } while (readtoken() == TPIPE);
11095                 lp->next = NULL;
11096                 n1 = pipenode;
11097         }
11098         tokpushback = 1;
11099         if (negate) {
11100                 n2 = stzalloc(sizeof(struct nnot));
11101                 n2->type = NNOT;
11102                 n2->nnot.com = n1;
11103                 return n2;
11104         }
11105         return n1;
11106 }
11107
11108 static union node *
11109 makename(void)
11110 {
11111         union node *n;
11112
11113         n = stzalloc(sizeof(struct narg));
11114         n->type = NARG;
11115         /*n->narg.next = NULL; - stzalloc did it */
11116         n->narg.text = wordtext;
11117         n->narg.backquote = backquotelist;
11118         return n;
11119 }
11120
11121 static void
11122 fixredir(union node *n, const char *text, int err)
11123 {
11124         int fd;
11125
11126         TRACE(("Fix redir %s %d\n", text, err));
11127         if (!err)
11128                 n->ndup.vname = NULL;
11129
11130         fd = bb_strtou(text, NULL, 10);
11131         if (!errno && fd >= 0)
11132                 n->ndup.dupfd = fd;
11133         else if (LONE_DASH(text))
11134                 n->ndup.dupfd = -1;
11135         else {
11136                 if (err)
11137                         raise_error_syntax("bad fd number");
11138                 n->ndup.vname = makename();
11139         }
11140 }
11141
11142 static void
11143 parsefname(void)
11144 {
11145         union node *n = redirnode;
11146
11147         if (n->type == NHERE)
11148                 checkkwd = CHKEOFMARK;
11149         if (readtoken() != TWORD)
11150                 raise_error_unexpected_syntax(-1);
11151         if (n->type == NHERE) {
11152                 struct heredoc *here = heredoc;
11153                 struct heredoc *p;
11154
11155                 if (quoteflag == 0)
11156                         n->type = NXHERE;
11157                 TRACE(("Here document %d\n", n->type));
11158                 rmescapes(wordtext, 0);
11159                 here->eofmark = wordtext;
11160                 here->next = NULL;
11161                 if (heredoclist == NULL)
11162                         heredoclist = here;
11163                 else {
11164                         for (p = heredoclist; p->next; p = p->next)
11165                                 continue;
11166                         p->next = here;
11167                 }
11168         } else if (n->type == NTOFD || n->type == NFROMFD) {
11169                 fixredir(n, wordtext, 0);
11170         } else {
11171                 n->nfile.fname = makename();
11172         }
11173 }
11174
11175 static union node *
11176 simplecmd(void)
11177 {
11178         union node *args, **app;
11179         union node *n = NULL;
11180         union node *vars, **vpp;
11181         union node **rpp, *redir;
11182         int savecheckkwd;
11183 #if BASH_TEST2
11184         smallint double_brackets_flag = 0;
11185 #endif
11186         IF_BASH_FUNCTION(smallint function_flag = 0;)
11187
11188         args = NULL;
11189         app = &args;
11190         vars = NULL;
11191         vpp = &vars;
11192         redir = NULL;
11193         rpp = &redir;
11194
11195         savecheckkwd = CHKALIAS;
11196         for (;;) {
11197                 int t;
11198                 checkkwd = savecheckkwd;
11199                 t = readtoken();
11200                 switch (t) {
11201 #if BASH_FUNCTION
11202                 case TFUNCTION:
11203                         if (peektoken() != TWORD)
11204                                 raise_error_unexpected_syntax(TWORD);
11205                         function_flag = 1;
11206                         break;
11207 #endif
11208 #if BASH_TEST2
11209                 case TAND: /* "&&" */
11210                 case TOR: /* "||" */
11211                         if (!double_brackets_flag) {
11212                                 tokpushback = 1;
11213                                 goto out;
11214                         }
11215                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11216 #endif
11217                 case TWORD:
11218                         n = stzalloc(sizeof(struct narg));
11219                         n->type = NARG;
11220                         /*n->narg.next = NULL; - stzalloc did it */
11221                         n->narg.text = wordtext;
11222 #if BASH_TEST2
11223                         if (strcmp("[[", wordtext) == 0)
11224                                 double_brackets_flag = 1;
11225                         else if (strcmp("]]", wordtext) == 0)
11226                                 double_brackets_flag = 0;
11227 #endif
11228                         n->narg.backquote = backquotelist;
11229                         if (savecheckkwd && isassignment(wordtext)) {
11230                                 *vpp = n;
11231                                 vpp = &n->narg.next;
11232                         } else {
11233                                 *app = n;
11234                                 app = &n->narg.next;
11235                                 savecheckkwd = 0;
11236                         }
11237 #if BASH_FUNCTION
11238                         if (function_flag) {
11239                                 checkkwd = CHKNL | CHKKWD;
11240                                 switch (peektoken()) {
11241                                 case TBEGIN:
11242                                 case TIF:
11243                                 case TCASE:
11244                                 case TUNTIL:
11245                                 case TWHILE:
11246                                 case TFOR:
11247                                         goto do_func;
11248                                 case TLP:
11249                                         function_flag = 0;
11250                                         break;
11251                                 case TWORD:
11252                                         if (strcmp("[[", wordtext) == 0)
11253                                                 goto do_func;
11254                                         /* fall through */
11255                                 default:
11256                                         raise_error_unexpected_syntax(-1);
11257                                 }
11258                         }
11259 #endif
11260                         break;
11261                 case TREDIR:
11262                         *rpp = n = redirnode;
11263                         rpp = &n->nfile.next;
11264                         parsefname();   /* read name of redirection file */
11265                         break;
11266                 case TLP:
11267  IF_BASH_FUNCTION(do_func:)
11268                         if (args && app == &args->narg.next
11269                          && !vars && !redir
11270                         ) {
11271                                 struct builtincmd *bcmd;
11272                                 const char *name;
11273
11274                                 /* We have a function */
11275                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11276                                         raise_error_unexpected_syntax(TRP);
11277                                 name = n->narg.text;
11278                                 if (!goodname(name)
11279                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11280                                 ) {
11281                                         raise_error_syntax("bad function name");
11282                                 }
11283                                 n->type = NDEFUN;
11284                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11285                                 n->narg.next = parse_command();
11286                                 return n;
11287                         }
11288                         IF_BASH_FUNCTION(function_flag = 0;)
11289                         /* fall through */
11290                 default:
11291                         tokpushback = 1;
11292                         goto out;
11293                 }
11294         }
11295  out:
11296         *app = NULL;
11297         *vpp = NULL;
11298         *rpp = NULL;
11299         n = stzalloc(sizeof(struct ncmd));
11300         n->type = NCMD;
11301         n->ncmd.args = args;
11302         n->ncmd.assign = vars;
11303         n->ncmd.redirect = redir;
11304         return n;
11305 }
11306
11307 static union node *
11308 parse_command(void)
11309 {
11310         union node *n1, *n2;
11311         union node *ap, **app;
11312         union node *cp, **cpp;
11313         union node *redir, **rpp;
11314         union node **rpp2;
11315         int t;
11316
11317         redir = NULL;
11318         rpp2 = &redir;
11319
11320         switch (readtoken()) {
11321         default:
11322                 raise_error_unexpected_syntax(-1);
11323                 /* NOTREACHED */
11324         case TIF:
11325                 n1 = stzalloc(sizeof(struct nif));
11326                 n1->type = NIF;
11327                 n1->nif.test = list(0);
11328                 if (readtoken() != TTHEN)
11329                         raise_error_unexpected_syntax(TTHEN);
11330                 n1->nif.ifpart = list(0);
11331                 n2 = n1;
11332                 while (readtoken() == TELIF) {
11333                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11334                         n2 = n2->nif.elsepart;
11335                         n2->type = NIF;
11336                         n2->nif.test = list(0);
11337                         if (readtoken() != TTHEN)
11338                                 raise_error_unexpected_syntax(TTHEN);
11339                         n2->nif.ifpart = list(0);
11340                 }
11341                 if (lasttoken == TELSE)
11342                         n2->nif.elsepart = list(0);
11343                 else {
11344                         n2->nif.elsepart = NULL;
11345                         tokpushback = 1;
11346                 }
11347                 t = TFI;
11348                 break;
11349         case TWHILE:
11350         case TUNTIL: {
11351                 int got;
11352                 n1 = stzalloc(sizeof(struct nbinary));
11353                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11354                 n1->nbinary.ch1 = list(0);
11355                 got = readtoken();
11356                 if (got != TDO) {
11357                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11358                                         got == TWORD ? wordtext : ""));
11359                         raise_error_unexpected_syntax(TDO);
11360                 }
11361                 n1->nbinary.ch2 = list(0);
11362                 t = TDONE;
11363                 break;
11364         }
11365         case TFOR:
11366                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11367                         raise_error_syntax("bad for loop variable");
11368                 n1 = stzalloc(sizeof(struct nfor));
11369                 n1->type = NFOR;
11370                 n1->nfor.var = wordtext;
11371                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11372                 if (readtoken() == TIN) {
11373                         app = &ap;
11374                         while (readtoken() == TWORD) {
11375                                 n2 = stzalloc(sizeof(struct narg));
11376                                 n2->type = NARG;
11377                                 /*n2->narg.next = NULL; - stzalloc did it */
11378                                 n2->narg.text = wordtext;
11379                                 n2->narg.backquote = backquotelist;
11380                                 *app = n2;
11381                                 app = &n2->narg.next;
11382                         }
11383                         *app = NULL;
11384                         n1->nfor.args = ap;
11385                         if (lasttoken != TNL && lasttoken != TSEMI)
11386                                 raise_error_unexpected_syntax(-1);
11387                 } else {
11388                         n2 = stzalloc(sizeof(struct narg));
11389                         n2->type = NARG;
11390                         /*n2->narg.next = NULL; - stzalloc did it */
11391                         n2->narg.text = (char *)dolatstr;
11392                         /*n2->narg.backquote = NULL;*/
11393                         n1->nfor.args = n2;
11394                         /*
11395                          * Newline or semicolon here is optional (but note
11396                          * that the original Bourne shell only allowed NL).
11397                          */
11398                         if (lasttoken != TSEMI)
11399                                 tokpushback = 1;
11400                 }
11401                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11402                 if (readtoken() != TDO)
11403                         raise_error_unexpected_syntax(TDO);
11404                 n1->nfor.body = list(0);
11405                 t = TDONE;
11406                 break;
11407         case TCASE:
11408                 n1 = stzalloc(sizeof(struct ncase));
11409                 n1->type = NCASE;
11410                 if (readtoken() != TWORD)
11411                         raise_error_unexpected_syntax(TWORD);
11412                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11413                 n2->type = NARG;
11414                 /*n2->narg.next = NULL; - stzalloc did it */
11415                 n2->narg.text = wordtext;
11416                 n2->narg.backquote = backquotelist;
11417                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11418                 if (readtoken() != TIN)
11419                         raise_error_unexpected_syntax(TIN);
11420                 cpp = &n1->ncase.cases;
11421  next_case:
11422                 checkkwd = CHKNL | CHKKWD;
11423                 t = readtoken();
11424                 while (t != TESAC) {
11425                         if (lasttoken == TLP)
11426                                 readtoken();
11427                         *cpp = cp = stzalloc(sizeof(struct nclist));
11428                         cp->type = NCLIST;
11429                         app = &cp->nclist.pattern;
11430                         for (;;) {
11431                                 *app = ap = stzalloc(sizeof(struct narg));
11432                                 ap->type = NARG;
11433                                 /*ap->narg.next = NULL; - stzalloc did it */
11434                                 ap->narg.text = wordtext;
11435                                 ap->narg.backquote = backquotelist;
11436                                 if (readtoken() != TPIPE)
11437                                         break;
11438                                 app = &ap->narg.next;
11439                                 readtoken();
11440                         }
11441                         //ap->narg.next = NULL;
11442                         if (lasttoken != TRP)
11443                                 raise_error_unexpected_syntax(TRP);
11444                         cp->nclist.body = list(2);
11445
11446                         cpp = &cp->nclist.next;
11447
11448                         checkkwd = CHKNL | CHKKWD;
11449                         t = readtoken();
11450                         if (t != TESAC) {
11451                                 if (t != TENDCASE)
11452                                         raise_error_unexpected_syntax(TENDCASE);
11453                                 goto next_case;
11454                         }
11455                 }
11456                 *cpp = NULL;
11457                 goto redir;
11458         case TLP:
11459                 n1 = stzalloc(sizeof(struct nredir));
11460                 n1->type = NSUBSHELL;
11461                 n1->nredir.n = list(0);
11462                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11463                 t = TRP;
11464                 break;
11465         case TBEGIN:
11466                 n1 = list(0);
11467                 t = TEND;
11468                 break;
11469         IF_BASH_FUNCTION(case TFUNCTION:)
11470         case TWORD:
11471         case TREDIR:
11472                 tokpushback = 1;
11473                 return simplecmd();
11474         }
11475
11476         if (readtoken() != t)
11477                 raise_error_unexpected_syntax(t);
11478
11479  redir:
11480         /* Now check for redirection which may follow command */
11481         checkkwd = CHKKWD | CHKALIAS;
11482         rpp = rpp2;
11483         while (readtoken() == TREDIR) {
11484                 *rpp = n2 = redirnode;
11485                 rpp = &n2->nfile.next;
11486                 parsefname();
11487         }
11488         tokpushback = 1;
11489         *rpp = NULL;
11490         if (redir) {
11491                 if (n1->type != NSUBSHELL) {
11492                         n2 = stzalloc(sizeof(struct nredir));
11493                         n2->type = NREDIR;
11494                         n2->nredir.n = n1;
11495                         n1 = n2;
11496                 }
11497                 n1->nredir.redirect = redir;
11498         }
11499         return n1;
11500 }
11501
11502 #if BASH_DOLLAR_SQUOTE
11503 static int
11504 decode_dollar_squote(void)
11505 {
11506         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11507         int c, cnt;
11508         char *p;
11509         char buf[4];
11510
11511         c = pgetc();
11512         p = strchr(C_escapes, c);
11513         if (p) {
11514                 buf[0] = c;
11515                 p = buf;
11516                 cnt = 3;
11517                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11518                         do {
11519                                 c = pgetc();
11520                                 *++p = c;
11521                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11522                         pungetc();
11523                 } else if (c == 'x') { /* \xHH */
11524                         do {
11525                                 c = pgetc();
11526                                 *++p = c;
11527                         } while (isxdigit(c) && --cnt);
11528                         pungetc();
11529                         if (cnt == 3) { /* \x but next char is "bad" */
11530                                 c = 'x';
11531                                 goto unrecognized;
11532                         }
11533                 } else { /* simple seq like \\ or \t */
11534                         p++;
11535                 }
11536                 *p = '\0';
11537                 p = buf;
11538                 c = bb_process_escape_sequence((void*)&p);
11539         } else { /* unrecognized "\z": print both chars unless ' or " */
11540                 if (c != '\'' && c != '"') {
11541  unrecognized:
11542                         c |= 0x100; /* "please encode \, then me" */
11543                 }
11544         }
11545         return c;
11546 }
11547 #endif
11548
11549 /* Used by expandstr to get here-doc like behaviour. */
11550 #define FAKEEOFMARK ((char*)(uintptr_t)1)
11551
11552 static ALWAYS_INLINE int
11553 realeofmark(const char *eofmark)
11554 {
11555         return eofmark && eofmark != FAKEEOFMARK;
11556 }
11557
11558 /*
11559  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11560  * is not NULL, read a here document.  In the latter case, eofmark is the
11561  * word which marks the end of the document and striptabs is true if
11562  * leading tabs should be stripped from the document.  The argument c
11563  * is the first character of the input token or document.
11564  *
11565  * Because C does not have internal subroutines, I have simulated them
11566  * using goto's to implement the subroutine linkage.  The following macros
11567  * will run code that appears at the end of readtoken1.
11568  */
11569 #define CHECKEND()      {goto checkend; checkend_return:;}
11570 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11571 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11572 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11573 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11574 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11575 static int
11576 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11577 {
11578         /* NB: syntax parameter fits into smallint */
11579         /* c parameter is an unsigned char or PEOF or PEOA */
11580         char *out;
11581         size_t len;
11582         struct nodelist *bqlist;
11583         smallint quotef;
11584         smallint dblquote;
11585         smallint oldstyle;
11586         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11587         smallint pssyntax;   /* we are expanding a prompt string */
11588         int varnest;         /* levels of variables expansion */
11589         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11590         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11591         int dqvarnest;       /* levels of variables expansion within double quotes */
11592
11593         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11594
11595         startlinno = g_parsefile->linno;
11596         bqlist = NULL;
11597         quotef = 0;
11598         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11599 #if ENABLE_ASH_EXPAND_PRMT
11600         pssyntax = (syntax == PSSYNTAX);
11601         if (pssyntax)
11602                 syntax = DQSYNTAX;
11603 #else
11604         pssyntax = 0; /* constant */
11605 #endif
11606         dblquote = (syntax == DQSYNTAX);
11607         varnest = 0;
11608         IF_FEATURE_SH_MATH(arinest = 0;)
11609         IF_FEATURE_SH_MATH(parenlevel = 0;)
11610         dqvarnest = 0;
11611
11612         STARTSTACKSTR(out);
11613  loop:
11614         /* For each line, until end of word */
11615         CHECKEND();     /* set c to PEOF if at end of here document */
11616         for (;;) {      /* until end of line or end of word */
11617                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11618                 switch (SIT(c, syntax)) {
11619                 case CNL:       /* '\n' */
11620                         if (syntax == BASESYNTAX)
11621                                 goto endword;   /* exit outer loop */
11622                         USTPUTC(c, out);
11623                         nlprompt();
11624                         c = pgetc();
11625                         goto loop;              /* continue outer loop */
11626                 case CWORD:
11627                         USTPUTC(c, out);
11628                         break;
11629                 case CCTL:
11630 #if BASH_DOLLAR_SQUOTE
11631                         if (c == '\\' && bash_dollar_squote) {
11632                                 c = decode_dollar_squote();
11633                                 if (c == '\0') {
11634                                         /* skip $'\000', $'\x00' (like bash) */
11635                                         break;
11636                                 }
11637                                 if (c & 0x100) {
11638                                         /* Unknown escape. Encode as '\z' */
11639                                         c = (unsigned char)c;
11640                                         if (eofmark == NULL || dblquote)
11641                                                 USTPUTC(CTLESC, out);
11642                                         USTPUTC('\\', out);
11643                                 }
11644                         }
11645 #endif
11646                         if (eofmark == NULL || dblquote)
11647                                 USTPUTC(CTLESC, out);
11648                         USTPUTC(c, out);
11649                         break;
11650                 case CBACK:     /* backslash */
11651                         c = pgetc_without_PEOA();
11652                         if (c == PEOF) {
11653                                 USTPUTC(CTLESC, out);
11654                                 USTPUTC('\\', out);
11655                                 pungetc();
11656                         } else if (c == '\n') {
11657                                 nlprompt();
11658                         } else {
11659                                 if (pssyntax && c == '$') {
11660                                         USTPUTC(CTLESC, out);
11661                                         USTPUTC('\\', out);
11662                                 }
11663                                 /* Backslash is retained if we are in "str" and next char isn't special */
11664                                 if (dblquote
11665                                  && c != '\\'
11666                                  && c != '`'
11667                                  && c != '$'
11668                                  && (c != '"' || eofmark != NULL)
11669                                 ) {
11670                                         USTPUTC('\\', out);
11671                                 }
11672                                 USTPUTC(CTLESC, out);
11673                                 USTPUTC(c, out);
11674                                 quotef = 1;
11675                         }
11676                         break;
11677                 case CSQUOTE:
11678                         syntax = SQSYNTAX;
11679  quotemark:
11680                         if (eofmark == NULL) {
11681                                 USTPUTC(CTLQUOTEMARK, out);
11682                         }
11683                         break;
11684                 case CDQUOTE:
11685                         syntax = DQSYNTAX;
11686                         dblquote = 1;
11687                         goto quotemark;
11688                 case CENDQUOTE:
11689                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11690                         if (eofmark != NULL && varnest == 0) {
11691                                 USTPUTC(c, out);
11692                         } else {
11693                                 if (dqvarnest == 0) {
11694                                         syntax = BASESYNTAX;
11695                                         dblquote = 0;
11696                                 }
11697                                 quotef = 1;
11698                                 goto quotemark;
11699                         }
11700                         break;
11701                 case CVAR:      /* '$' */
11702                         PARSESUB();             /* parse substitution */
11703                         break;
11704                 case CENDVAR:   /* '}' */
11705                         if (varnest > 0) {
11706                                 varnest--;
11707                                 if (dqvarnest > 0) {
11708                                         dqvarnest--;
11709                                 }
11710                                 c = CTLENDVAR;
11711                         }
11712                         USTPUTC(c, out);
11713                         break;
11714 #if ENABLE_FEATURE_SH_MATH
11715                 case CLP:       /* '(' in arithmetic */
11716                         parenlevel++;
11717                         USTPUTC(c, out);
11718                         break;
11719                 case CRP:       /* ')' in arithmetic */
11720                         if (parenlevel > 0) {
11721                                 parenlevel--;
11722                         } else {
11723                                 if (pgetc_eatbnl() == ')') {
11724                                         c = CTLENDARI;
11725                                         if (--arinest == 0) {
11726                                                 syntax = prevsyntax;
11727                                         }
11728                                 } else {
11729                                         /*
11730                                          * unbalanced parens
11731                                          * (don't 2nd guess - no error)
11732                                          */
11733                                         pungetc();
11734                                 }
11735                         }
11736                         USTPUTC(c, out);
11737                         break;
11738 #endif
11739                 case CBQUOTE:   /* '`' */
11740                         PARSEBACKQOLD();
11741                         break;
11742                 case CENDFILE:
11743                         goto endword;           /* exit outer loop */
11744                 case CIGN:
11745                         break;
11746                 default:
11747                         if (varnest == 0) {
11748 #if BASH_REDIR_OUTPUT
11749                                 if (c == '&') {
11750 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11751                                         if (pgetc() == '>')
11752                                                 c = 0x100 + '>'; /* flag &> */
11753                                         pungetc();
11754                                 }
11755 #endif
11756                                 goto endword;   /* exit outer loop */
11757                         }
11758                         IF_ASH_ALIAS(if (c != PEOA))
11759                                 USTPUTC(c, out);
11760                 }
11761                 c = pgetc();
11762         } /* for (;;) */
11763  endword:
11764
11765 #if ENABLE_FEATURE_SH_MATH
11766         if (syntax == ARISYNTAX)
11767                 raise_error_syntax("missing '))'");
11768 #endif
11769         if (syntax != BASESYNTAX && eofmark == NULL)
11770                 raise_error_syntax("unterminated quoted string");
11771         if (varnest != 0) {
11772                 startlinno = g_parsefile->linno;
11773                 /* { */
11774                 raise_error_syntax("missing '}'");
11775         }
11776         USTPUTC('\0', out);
11777         len = out - (char *)stackblock();
11778         out = stackblock();
11779         if (eofmark == NULL) {
11780                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11781                  && quotef == 0
11782                 ) {
11783                         if (isdigit_str9(out)) {
11784                                 PARSEREDIR(); /* passed as params: out, c */
11785                                 lasttoken = TREDIR;
11786                                 return lasttoken;
11787                         }
11788                         /* else: non-number X seen, interpret it
11789                          * as "NNNX>file" = "NNNX >file" */
11790                 }
11791                 pungetc();
11792         }
11793         quoteflag = quotef;
11794         backquotelist = bqlist;
11795         grabstackblock(len);
11796         wordtext = out;
11797         lasttoken = TWORD;
11798         return lasttoken;
11799 /* end of readtoken routine */
11800
11801 /*
11802  * Check to see whether we are at the end of the here document.  When this
11803  * is called, c is set to the first character of the next input line.  If
11804  * we are at the end of the here document, this routine sets the c to PEOF.
11805  */
11806 checkend: {
11807         if (realeofmark(eofmark)) {
11808                 int markloc;
11809                 char *p;
11810
11811 #if ENABLE_ASH_ALIAS
11812                 if (c == PEOA)
11813                         c = pgetc_without_PEOA();
11814 #endif
11815                 if (striptabs) {
11816                         while (c == '\t') {
11817                                 c = pgetc_without_PEOA();
11818                         }
11819                 }
11820
11821                 markloc = out - (char *)stackblock();
11822                 for (p = eofmark; STPUTC(c, out), *p; p++) {
11823                         if (c != *p)
11824                                 goto more_heredoc;
11825
11826                         c = pgetc_without_PEOA();
11827                 }
11828
11829                 if (c == '\n' || c == PEOF) {
11830                         c = PEOF;
11831                         g_parsefile->linno++;
11832                         needprompt = doprompt;
11833                 } else {
11834                         int len_here;
11835
11836  more_heredoc:
11837                         p = (char *)stackblock() + markloc + 1;
11838                         len_here = out - p;
11839
11840                         if (len_here) {
11841                                 len_here -= (c >= PEOF);
11842                                 c = p[-1];
11843
11844                                 if (len_here) {
11845                                         char *str;
11846
11847                                         str = alloca(len_here + 1);
11848                                         *(char *)mempcpy(str, p, len_here) = '\0';
11849
11850                                         pushstring(str, NULL);
11851                                 }
11852                         }
11853                 }
11854
11855                 STADJUST((char *)stackblock() + markloc - out, out);
11856         }
11857         goto checkend_return;
11858 }
11859
11860 /*
11861  * Parse a redirection operator.  The variable "out" points to a string
11862  * specifying the fd to be redirected.  The variable "c" contains the
11863  * first character of the redirection operator.
11864  */
11865 parseredir: {
11866         /* out is already checked to be a valid number or "" */
11867         int fd = (*out == '\0' ? -1 : atoi(out));
11868         union node *np;
11869
11870         np = stzalloc(sizeof(struct nfile));
11871         if (c == '>') {
11872                 np->nfile.fd = 1;
11873                 c = pgetc();
11874                 if (c == '>')
11875                         np->type = NAPPEND;
11876                 else if (c == '|')
11877                         np->type = NCLOBBER;
11878                 else if (c == '&')
11879                         np->type = NTOFD;
11880                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11881                 else {
11882                         np->type = NTO;
11883                         pungetc();
11884                 }
11885         }
11886 #if BASH_REDIR_OUTPUT
11887         else if (c == 0x100 + '>') { /* this flags &> redirection */
11888                 np->nfile.fd = 1;
11889                 pgetc(); /* this is '>', no need to check */
11890                 np->type = NTO2;
11891         }
11892 #endif
11893         else { /* c == '<' */
11894                 /*np->nfile.fd = 0; - stzalloc did it */
11895                 c = pgetc();
11896                 switch (c) {
11897                 case '<':
11898                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11899                                 np = stzalloc(sizeof(struct nhere));
11900                                 /*np->nfile.fd = 0; - stzalloc did it */
11901                         }
11902                         np->type = NHERE;
11903                         heredoc = stzalloc(sizeof(struct heredoc));
11904                         heredoc->here = np;
11905                         c = pgetc();
11906                         if (c == '-') {
11907                                 heredoc->striptabs = 1;
11908                         } else {
11909                                 /*heredoc->striptabs = 0; - stzalloc did it */
11910                                 pungetc();
11911                         }
11912                         break;
11913
11914                 case '&':
11915                         np->type = NFROMFD;
11916                         break;
11917
11918                 case '>':
11919                         np->type = NFROMTO;
11920                         break;
11921
11922                 default:
11923                         np->type = NFROM;
11924                         pungetc();
11925                         break;
11926                 }
11927         }
11928         if (fd >= 0)
11929                 np->nfile.fd = fd;
11930         redirnode = np;
11931         goto parseredir_return;
11932 }
11933
11934 /*
11935  * Parse a substitution.  At this point, we have read the dollar sign
11936  * and nothing else.
11937  */
11938
11939 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11940  * (assuming ascii char codes, as the original implementation did) */
11941 #define is_special(c) \
11942         (((unsigned)(c) - 33 < 32) \
11943                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11944 parsesub: {
11945         unsigned char subtype;
11946         int typeloc;
11947
11948         c = pgetc_eatbnl();
11949         if ((checkkwd & CHKEOFMARK)
11950          || c > 255 /* PEOA or PEOF */
11951          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11952         ) {
11953 #if BASH_DOLLAR_SQUOTE
11954                 if (syntax != DQSYNTAX && c == '\'')
11955                         bash_dollar_squote = 1;
11956                 else
11957 #endif
11958                         USTPUTC('$', out);
11959                 pungetc();
11960         } else if (c == '(') {
11961                 /* $(command) or $((arith)) */
11962                 if (pgetc_eatbnl() == '(') {
11963 #if ENABLE_FEATURE_SH_MATH
11964                         PARSEARITH();
11965 #else
11966                         raise_error_syntax("support for $((arith)) is disabled");
11967 #endif
11968                 } else {
11969                         pungetc();
11970                         PARSEBACKQNEW();
11971                 }
11972         } else {
11973                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11974                 USTPUTC(CTLVAR, out);
11975                 typeloc = out - (char *)stackblock();
11976                 STADJUST(1, out);
11977                 subtype = VSNORMAL;
11978                 if (c == '{') {
11979                         c = pgetc_eatbnl();
11980                         subtype = 0;
11981                 }
11982  varname:
11983                 if (is_name(c)) {
11984                         /* $[{[#]]NAME[}] */
11985                         do {
11986                                 STPUTC(c, out);
11987                                 c = pgetc_eatbnl();
11988                         } while (is_in_name(c));
11989                 } else if (isdigit(c)) {
11990                         /* $[{[#]]NUM[}] */
11991                         do {
11992                                 STPUTC(c, out);
11993                                 c = pgetc_eatbnl();
11994                         } while (isdigit(c));
11995                 } else if (is_special(c)) {
11996                         /* $[{[#]]<specialchar>[}] */
11997                         int cc = c;
11998
11999                         c = pgetc_eatbnl();
12000                         if (!subtype && cc == '#') {
12001                                 subtype = VSLENGTH;
12002                                 if (c == '_' || isalnum(c))
12003                                         goto varname;
12004                                 cc = c;
12005                                 c = pgetc_eatbnl();
12006                                 if (cc == '}' || c != '}') {
12007                                         pungetc();
12008                                         subtype = 0;
12009                                         c = cc;
12010                                         cc = '#';
12011                                 }
12012                         }
12013                         USTPUTC(cc, out);
12014                 } else {
12015                         goto badsub;
12016                 }
12017                 if (c != '}' && subtype == VSLENGTH) {
12018                         /* ${#VAR didn't end with } */
12019                         goto badsub;
12020                 }
12021
12022                 if (subtype == 0) {
12023                         static const char types[] ALIGN1 = "}-+?=";
12024                         /* ${VAR...} but not $VAR or ${#VAR} */
12025                         /* c == first char after VAR */
12026                         switch (c) {
12027                         case ':':
12028                                 c = pgetc_eatbnl();
12029 #if BASH_SUBSTR
12030                                 /* This check is only needed to not misinterpret
12031                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12032                                  * constructs.
12033                                  */
12034                                 if (!strchr(types, c)) {
12035                                         subtype = VSSUBSTR;
12036                                         pungetc();
12037                                         break; /* "goto badsub" is bigger (!) */
12038                                 }
12039 #endif
12040                                 subtype = VSNUL;
12041                                 /*FALLTHROUGH*/
12042                         default: {
12043                                 const char *p = strchr(types, c);
12044                                 if (p == NULL)
12045                                         break;
12046                                 subtype |= p - types + VSNORMAL;
12047                                 break;
12048                         }
12049                         case '%':
12050                         case '#': {
12051                                 int cc = c;
12052                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12053                                 c = pgetc_eatbnl();
12054                                 if (c != cc)
12055                                         goto badsub;
12056                                 subtype++;
12057                                 break;
12058                         }
12059 #if BASH_PATTERN_SUBST
12060                         case '/':
12061                                 /* ${v/[/]pattern/repl} */
12062 //TODO: encode pattern and repl separately.
12063 // Currently ${v/$var_with_slash/repl} is horribly broken
12064                                 subtype = VSREPLACE;
12065                                 c = pgetc_eatbnl();
12066                                 if (c != '/')
12067                                         goto badsub;
12068                                 subtype++; /* VSREPLACEALL */
12069                                 break;
12070 #endif
12071                         }
12072                 } else {
12073  badsub:
12074                         pungetc();
12075                 }
12076                 ((unsigned char *)stackblock())[typeloc] = subtype;
12077                 if (subtype != VSNORMAL) {
12078                         varnest++;
12079                         if (dblquote)
12080                                 dqvarnest++;
12081                 }
12082                 STPUTC('=', out);
12083         }
12084         goto parsesub_return;
12085 }
12086
12087 /*
12088  * Called to parse command substitutions.  Newstyle is set if the command
12089  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12090  * list of commands (passed by reference), and savelen is the number of
12091  * characters on the top of the stack which must be preserved.
12092  */
12093 parsebackq: {
12094         struct nodelist **nlpp;
12095         union node *n;
12096         char *str;
12097         size_t savelen;
12098         smallint saveprompt = 0;
12099
12100         str = NULL;
12101         savelen = out - (char *)stackblock();
12102         if (savelen > 0) {
12103                 /*
12104                  * FIXME: this can allocate very large block on stack and SEGV.
12105                  * Example:
12106                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12107                  * allocates 100kb for every command subst. With about
12108                  * a hundred command substitutions stack overflows.
12109                  * With larger prepended string, SEGV happens sooner.
12110                  */
12111                 str = alloca(savelen);
12112                 memcpy(str, stackblock(), savelen);
12113         }
12114
12115         if (oldstyle) {
12116                 /* We must read until the closing backquote, giving special
12117                  * treatment to some slashes, and then push the string and
12118                  * reread it as input, interpreting it normally.
12119                  */
12120                 char *pout;
12121                 size_t psavelen;
12122                 char *pstr;
12123
12124                 STARTSTACKSTR(pout);
12125                 for (;;) {
12126                         int pc;
12127
12128                         setprompt_if(needprompt, 2);
12129                         pc = pgetc();
12130                         switch (pc) {
12131                         case '`':
12132                                 goto done;
12133
12134                         case '\\':
12135                                 pc = pgetc();
12136                                 if (pc == '\n') {
12137                                         nlprompt();
12138                                         /*
12139                                          * If eating a newline, avoid putting
12140                                          * the newline into the new character
12141                                          * stream (via the STPUTC after the
12142                                          * switch).
12143                                          */
12144                                         continue;
12145                                 }
12146                                 if (pc != '\\' && pc != '`' && pc != '$'
12147                                  && (!dblquote || pc != '"')
12148                                 ) {
12149                                         STPUTC('\\', pout);
12150                                 }
12151                                 if (pc <= 255 /* not PEOA or PEOF */) {
12152                                         break;
12153                                 }
12154                                 /* fall through */
12155
12156                         case PEOF:
12157                         IF_ASH_ALIAS(case PEOA:)
12158                                 startlinno = g_parsefile->linno;
12159                                 raise_error_syntax("EOF in backquote substitution");
12160
12161                         case '\n':
12162                                 nlnoprompt();
12163                                 break;
12164
12165                         default:
12166                                 break;
12167                         }
12168                         STPUTC(pc, pout);
12169                 }
12170  done:
12171                 STPUTC('\0', pout);
12172                 psavelen = pout - (char *)stackblock();
12173                 if (psavelen > 0) {
12174                         pstr = grabstackstr(pout);
12175                         setinputstring(pstr);
12176                 }
12177         }
12178         nlpp = &bqlist;
12179         while (*nlpp)
12180                 nlpp = &(*nlpp)->next;
12181         *nlpp = stzalloc(sizeof(**nlpp));
12182         /* (*nlpp)->next = NULL; - stzalloc did it */
12183
12184         if (oldstyle) {
12185                 saveprompt = doprompt;
12186                 doprompt = 0;
12187         }
12188
12189         n = list(2);
12190
12191         if (oldstyle)
12192                 doprompt = saveprompt;
12193         else if (readtoken() != TRP)
12194                 raise_error_unexpected_syntax(TRP);
12195
12196         (*nlpp)->n = n;
12197         if (oldstyle) {
12198                 /*
12199                  * Start reading from old file again, ignoring any pushed back
12200                  * tokens left from the backquote parsing
12201                  */
12202                 popfile();
12203                 tokpushback = 0;
12204         }
12205         while (stackblocksize() <= savelen)
12206                 growstackblock();
12207         STARTSTACKSTR(out);
12208         if (str) {
12209                 memcpy(out, str, savelen);
12210                 STADJUST(savelen, out);
12211         }
12212         USTPUTC(CTLBACKQ, out);
12213         if (oldstyle)
12214                 goto parsebackq_oldreturn;
12215         goto parsebackq_newreturn;
12216 }
12217
12218 #if ENABLE_FEATURE_SH_MATH
12219 /*
12220  * Parse an arithmetic expansion (indicate start of one and set state)
12221  */
12222 parsearith: {
12223         if (++arinest == 1) {
12224                 prevsyntax = syntax;
12225                 syntax = ARISYNTAX;
12226         }
12227         USTPUTC(CTLARI, out);
12228         goto parsearith_return;
12229 }
12230 #endif
12231 } /* end of readtoken */
12232
12233 /*
12234  * Read the next input token.
12235  * If the token is a word, we set backquotelist to the list of cmds in
12236  *      backquotes.  We set quoteflag to true if any part of the word was
12237  *      quoted.
12238  * If the token is TREDIR, then we set redirnode to a structure containing
12239  *      the redirection.
12240  * In all cases, the variable startlinno is set to the number of the line
12241  *      on which the token starts.
12242  *
12243  * [Change comment:  here documents and internal procedures]
12244  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12245  *  word parsing code into a separate routine.  In this case, readtoken
12246  *  doesn't need to have any internal procedures, but parseword does.
12247  *  We could also make parseoperator in essence the main routine, and
12248  *  have parseword (readtoken1?) handle both words and redirection.]
12249  */
12250 #define NEW_xxreadtoken
12251 #ifdef NEW_xxreadtoken
12252 /* singles must be first! */
12253 static const char xxreadtoken_chars[7] ALIGN1 = {
12254         '\n', '(', ')', /* singles */
12255         '&', '|', ';',  /* doubles */
12256         0
12257 };
12258
12259 #define xxreadtoken_singles 3
12260 #define xxreadtoken_doubles 3
12261
12262 static const char xxreadtoken_tokens[] ALIGN1 = {
12263         TNL, TLP, TRP,          /* only single occurrence allowed */
12264         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12265         TEOF,                   /* corresponds to trailing nul */
12266         TAND, TOR, TENDCASE     /* if double occurrence */
12267 };
12268
12269 static int
12270 xxreadtoken(void)
12271 {
12272         int c;
12273
12274         if (tokpushback) {
12275                 tokpushback = 0;
12276                 return lasttoken;
12277         }
12278         setprompt_if(needprompt, 2);
12279         startlinno = g_parsefile->linno;
12280         for (;;) {                      /* until token or start of word found */
12281                 c = pgetc();
12282                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12283                         continue;
12284
12285                 if (c == '#') {
12286                         while ((c = pgetc()) != '\n' && c != PEOF)
12287                                 continue;
12288                         pungetc();
12289                 } else if (c == '\\') {
12290                         if (pgetc() != '\n') {
12291                                 pungetc();
12292                                 break; /* return readtoken1(...) */
12293                         }
12294                         nlprompt();
12295                 } else {
12296                         const char *p;
12297
12298                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12299                         if (c != PEOF) {
12300                                 if (c == '\n') {
12301                                         nlnoprompt();
12302                                 }
12303
12304                                 p = strchr(xxreadtoken_chars, c);
12305                                 if (p == NULL)
12306                                         break; /* return readtoken1(...) */
12307
12308                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12309                                         int cc = pgetc();
12310                                         if (cc == c) {    /* double occurrence? */
12311                                                 p += xxreadtoken_doubles + 1;
12312                                         } else {
12313                                                 pungetc();
12314 #if BASH_REDIR_OUTPUT
12315                                                 if (c == '&' && cc == '>') /* &> */
12316                                                         break; /* return readtoken1(...) */
12317 #endif
12318                                         }
12319                                 }
12320                         }
12321                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12322                         return lasttoken;
12323                 }
12324         } /* for (;;) */
12325
12326         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12327 }
12328 #else /* old xxreadtoken */
12329 #define RETURN(token)   return lasttoken = token
12330 static int
12331 xxreadtoken(void)
12332 {
12333         int c;
12334
12335         if (tokpushback) {
12336                 tokpushback = 0;
12337                 return lasttoken;
12338         }
12339         setprompt_if(needprompt, 2);
12340         startlinno = g_parsefile->linno;
12341         for (;;) {      /* until token or start of word found */
12342                 c = pgetc();
12343                 switch (c) {
12344                 case ' ': case '\t':
12345                 IF_ASH_ALIAS(case PEOA:)
12346                         continue;
12347                 case '#':
12348                         while ((c = pgetc()) != '\n' && c != PEOF)
12349                                 continue;
12350                         pungetc();
12351                         continue;
12352                 case '\\':
12353                         if (pgetc() == '\n') {
12354                                 nlprompt();
12355                                 continue;
12356                         }
12357                         pungetc();
12358                         goto breakloop;
12359                 case '\n':
12360                         nlnoprompt();
12361                         RETURN(TNL);
12362                 case PEOF:
12363                         RETURN(TEOF);
12364                 case '&':
12365                         if (pgetc() == '&')
12366                                 RETURN(TAND);
12367                         pungetc();
12368                         RETURN(TBACKGND);
12369                 case '|':
12370                         if (pgetc() == '|')
12371                                 RETURN(TOR);
12372                         pungetc();
12373                         RETURN(TPIPE);
12374                 case ';':
12375                         if (pgetc() == ';')
12376                                 RETURN(TENDCASE);
12377                         pungetc();
12378                         RETURN(TSEMI);
12379                 case '(':
12380                         RETURN(TLP);
12381                 case ')':
12382                         RETURN(TRP);
12383                 default:
12384                         goto breakloop;
12385                 }
12386         }
12387  breakloop:
12388         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12389 #undef RETURN
12390 }
12391 #endif /* old xxreadtoken */
12392
12393 static int
12394 readtoken(void)
12395 {
12396         int t;
12397         int kwd = checkkwd;
12398 #if DEBUG
12399         smallint alreadyseen = tokpushback;
12400 #endif
12401
12402 #if ENABLE_ASH_ALIAS
12403  top:
12404 #endif
12405
12406         t = xxreadtoken();
12407
12408         /*
12409          * eat newlines
12410          */
12411         if (kwd & CHKNL) {
12412                 while (t == TNL) {
12413                         parseheredoc();
12414                         t = xxreadtoken();
12415                 }
12416         }
12417
12418         if (t != TWORD || quoteflag) {
12419                 goto out;
12420         }
12421
12422         /*
12423          * check for keywords
12424          */
12425         if (kwd & CHKKWD) {
12426                 const char *const *pp;
12427
12428                 pp = findkwd(wordtext);
12429                 if (pp) {
12430                         lasttoken = t = pp - tokname_array;
12431                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12432                         goto out;
12433                 }
12434         }
12435
12436         if (checkkwd & CHKALIAS) {
12437 #if ENABLE_ASH_ALIAS
12438                 struct alias *ap;
12439                 ap = lookupalias(wordtext, 1);
12440                 if (ap != NULL) {
12441                         if (*ap->val) {
12442                                 pushstring(ap->val, ap);
12443                         }
12444                         goto top;
12445                 }
12446 #endif
12447         }
12448  out:
12449         checkkwd = 0;
12450 #if DEBUG
12451         if (!alreadyseen)
12452                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12453         else
12454                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12455 #endif
12456         return t;
12457 }
12458
12459 static int
12460 peektoken(void)
12461 {
12462         int t;
12463
12464         t = readtoken();
12465         tokpushback = 1;
12466         return t;
12467 }
12468
12469 /*
12470  * Read and parse a command.  Returns NODE_EOF on end of file.
12471  * (NULL is a valid parse tree indicating a blank line.)
12472  */
12473 static union node *
12474 parsecmd(int interact)
12475 {
12476         tokpushback = 0;
12477         checkkwd = 0;
12478         heredoclist = 0;
12479         doprompt = interact;
12480         setprompt_if(doprompt, doprompt);
12481         needprompt = 0;
12482         return list(1);
12483 }
12484
12485 /*
12486  * Input any here documents.
12487  */
12488 static void
12489 parseheredoc(void)
12490 {
12491         struct heredoc *here;
12492         union node *n;
12493
12494         here = heredoclist;
12495         heredoclist = NULL;
12496
12497         while (here) {
12498                 setprompt_if(needprompt, 2);
12499                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12500                                 here->eofmark, here->striptabs);
12501                 n = stzalloc(sizeof(struct narg));
12502                 n->narg.type = NARG;
12503                 /*n->narg.next = NULL; - stzalloc did it */
12504                 n->narg.text = wordtext;
12505                 n->narg.backquote = backquotelist;
12506                 here->here->nhere.doc = n;
12507                 here = here->next;
12508         }
12509 }
12510
12511
12512 static const char *
12513 expandstr(const char *ps, int syntax_type)
12514 {
12515         union node n;
12516         int saveprompt;
12517
12518         /* XXX Fix (char *) cast. */
12519         setinputstring((char *)ps);
12520
12521         saveprompt = doprompt;
12522         doprompt = 0;
12523         readtoken1(pgetc(), syntax_type, FAKEEOFMARK, 0);
12524         doprompt = saveprompt;
12525
12526         popfile();
12527
12528         n.narg.type = NARG;
12529         n.narg.next = NULL;
12530         n.narg.text = wordtext;
12531         n.narg.backquote = backquotelist;
12532
12533         expandarg(&n, NULL, EXP_QUOTED);
12534         return stackblock();
12535 }
12536
12537 static inline int
12538 parser_eof(void)
12539 {
12540         return tokpushback && lasttoken == TEOF;
12541 }
12542
12543 /*
12544  * Execute a command or commands contained in a string.
12545  */
12546 static int
12547 evalstring(char *s, int flags)
12548 {
12549         struct jmploc *volatile savehandler;
12550         struct jmploc jmploc;
12551         int ex;
12552
12553         union node *n;
12554         struct stackmark smark;
12555         int status;
12556
12557         s = sstrdup(s);
12558         setinputstring(s);
12559         setstackmark(&smark);
12560
12561         status = 0;
12562         /* On exception inside execution loop, we must popfile().
12563          * Try interactively:
12564          *      readonly a=a
12565          *      command eval "a=b"  # throws "is read only" error
12566          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12567          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12568          */
12569         savehandler = exception_handler;
12570         ex = setjmp(jmploc.loc);
12571         if (ex)
12572                 goto out;
12573         exception_handler = &jmploc;
12574
12575         while ((n = parsecmd(0)) != NODE_EOF) {
12576                 int i;
12577
12578                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12579                 if (n)
12580                         status = i;
12581                 popstackmark(&smark);
12582                 if (evalskip)
12583                         break;
12584         }
12585  out:
12586         popstackmark(&smark);
12587         popfile();
12588         stunalloc(s);
12589
12590         exception_handler = savehandler;
12591         if (ex)
12592                 longjmp(exception_handler->loc, ex);
12593
12594         return status;
12595 }
12596
12597 /*
12598  * The eval command.
12599  */
12600 static int FAST_FUNC
12601 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12602 {
12603         char *p;
12604         char *concat;
12605
12606         if (argv[1]) {
12607                 p = argv[1];
12608                 argv += 2;
12609                 if (argv[0]) {
12610                         STARTSTACKSTR(concat);
12611                         for (;;) {
12612                                 concat = stack_putstr(p, concat);
12613                                 p = *argv++;
12614                                 if (p == NULL)
12615                                         break;
12616                                 STPUTC(' ', concat);
12617                         }
12618                         STPUTC('\0', concat);
12619                         p = grabstackstr(concat);
12620                 }
12621                 return evalstring(p, flags & EV_TESTED);
12622         }
12623         return 0;
12624 }
12625
12626 /*
12627  * Read and execute commands.
12628  * "Top" is nonzero for the top level command loop;
12629  * it turns on prompting if the shell is interactive.
12630  */
12631 static int
12632 cmdloop(int top)
12633 {
12634         union node *n;
12635         struct stackmark smark;
12636         int inter;
12637         int status = 0;
12638         int numeof = 0;
12639
12640         TRACE(("cmdloop(%d) called\n", top));
12641         for (;;) {
12642                 int skip;
12643
12644                 setstackmark(&smark);
12645 #if JOBS
12646                 if (doing_jobctl)
12647                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12648 #endif
12649                 inter = 0;
12650                 if (iflag && top) {
12651                         inter++;
12652                         chkmail();
12653                 }
12654                 n = parsecmd(inter);
12655 #if DEBUG
12656                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12657                         showtree(n);
12658 #endif
12659                 if (n == NODE_EOF) {
12660                         if (!top || numeof >= 50)
12661                                 break;
12662                         if (!stoppedjobs()) {
12663                                 if (!Iflag)
12664                                         break;
12665                                 out2str("\nUse \"exit\" to leave shell.\n");
12666                         }
12667                         numeof++;
12668                 } else if (nflag == 0) {
12669                         int i;
12670
12671                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12672                         job_warning >>= 1;
12673                         numeof = 0;
12674                         i = evaltree(n, 0);
12675                         if (n)
12676                                 status = i;
12677                 }
12678                 popstackmark(&smark);
12679                 skip = evalskip;
12680
12681                 if (skip) {
12682                         evalskip &= ~SKIPFUNC;
12683                         break;
12684                 }
12685         }
12686         return status;
12687 }
12688
12689 /*
12690  * Take commands from a file.  To be compatible we should do a path
12691  * search for the file, which is necessary to find sub-commands.
12692  */
12693 static char *
12694 find_dot_file(char *name)
12695 {
12696         char *fullname;
12697         const char *path = pathval();
12698         struct stat statb;
12699
12700         /* don't try this for absolute or relative paths */
12701         if (strchr(name, '/'))
12702                 return name;
12703
12704         while ((fullname = path_advance(&path, name)) != NULL) {
12705                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12706                         /*
12707                          * Don't bother freeing here, since it will
12708                          * be freed by the caller.
12709                          */
12710                         return fullname;
12711                 }
12712                 if (fullname != name)
12713                         stunalloc(fullname);
12714         }
12715
12716         /* not found in the PATH */
12717         ash_msg_and_raise_error("%s: not found", name);
12718         /* NOTREACHED */
12719 }
12720
12721 static int FAST_FUNC
12722 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12723 {
12724         /* "false; . empty_file; echo $?" should print 0, not 1: */
12725         int status = 0;
12726         char *fullname;
12727         char **argv;
12728         char *args_need_save;
12729         volatile struct shparam saveparam;
12730
12731 //???
12732 //      struct strlist *sp;
12733 //      for (sp = cmdenviron; sp; sp = sp->next)
12734 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12735
12736         nextopt(nullstr); /* handle possible "--" */
12737         argv = argptr;
12738
12739         if (!argv[0]) {
12740                 /* bash says: "bash: .: filename argument required" */
12741                 return 2; /* bash compat */
12742         }
12743
12744         /* This aborts if file isn't found, which is POSIXly correct.
12745          * bash returns exitcode 1 instead.
12746          */
12747         fullname = find_dot_file(argv[0]);
12748         argv++;
12749         args_need_save = argv[0];
12750         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12751                 int argc;
12752                 saveparam = shellparam;
12753                 shellparam.malloced = 0;
12754                 argc = 1;
12755                 while (argv[argc])
12756                         argc++;
12757                 shellparam.nparam = argc;
12758                 shellparam.p = argv;
12759         };
12760
12761         /* This aborts if file can't be opened, which is POSIXly correct.
12762          * bash returns exitcode 1 instead.
12763          */
12764         setinputfile(fullname, INPUT_PUSH_FILE);
12765         commandname = fullname;
12766         status = cmdloop(0);
12767         popfile();
12768
12769         if (args_need_save) {
12770                 freeparam(&shellparam);
12771                 shellparam = saveparam;
12772         };
12773
12774         return status;
12775 }
12776
12777 static int FAST_FUNC
12778 exitcmd(int argc UNUSED_PARAM, char **argv)
12779 {
12780         if (stoppedjobs())
12781                 return 0;
12782         if (argv[1])
12783                 exitstatus = number(argv[1]);
12784         raise_exception(EXEXIT);
12785         /* NOTREACHED */
12786 }
12787
12788 /*
12789  * Read a file containing shell functions.
12790  */
12791 static void
12792 readcmdfile(char *name)
12793 {
12794         setinputfile(name, INPUT_PUSH_FILE);
12795         cmdloop(0);
12796         popfile();
12797 }
12798
12799
12800 /* ============ find_command inplementation */
12801
12802 /*
12803  * Resolve a command name.  If you change this routine, you may have to
12804  * change the shellexec routine as well.
12805  */
12806 static void
12807 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12808 {
12809         struct tblentry *cmdp;
12810         int idx;
12811         int prev;
12812         char *fullname;
12813         struct stat statb;
12814         int e;
12815         int updatetbl;
12816         struct builtincmd *bcmd;
12817
12818         /* If name contains a slash, don't use PATH or hash table */
12819         if (strchr(name, '/') != NULL) {
12820                 entry->u.index = -1;
12821                 if (act & DO_ABS) {
12822                         while (stat(name, &statb) < 0) {
12823 #ifdef SYSV
12824                                 if (errno == EINTR)
12825                                         continue;
12826 #endif
12827                                 entry->cmdtype = CMDUNKNOWN;
12828                                 return;
12829                         }
12830                 }
12831                 entry->cmdtype = CMDNORMAL;
12832                 return;
12833         }
12834
12835 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12836
12837         updatetbl = (path == pathval());
12838         if (!updatetbl) {
12839                 act |= DO_ALTPATH;
12840                 if (strstr(path, "%builtin") != NULL)
12841                         act |= DO_ALTBLTIN;
12842         }
12843
12844         /* If name is in the table, check answer will be ok */
12845         cmdp = cmdlookup(name, 0);
12846         if (cmdp != NULL) {
12847                 int bit;
12848
12849                 switch (cmdp->cmdtype) {
12850                 default:
12851 #if DEBUG
12852                         abort();
12853 #endif
12854                 case CMDNORMAL:
12855                         bit = DO_ALTPATH;
12856                         break;
12857                 case CMDFUNCTION:
12858                         bit = DO_NOFUNC;
12859                         break;
12860                 case CMDBUILTIN:
12861                         bit = DO_ALTBLTIN;
12862                         break;
12863                 }
12864                 if (act & bit) {
12865                         updatetbl = 0;
12866                         cmdp = NULL;
12867                 } else if (cmdp->rehash == 0)
12868                         /* if not invalidated by cd, we're done */
12869                         goto success;
12870         }
12871
12872         /* If %builtin not in path, check for builtin next */
12873         bcmd = find_builtin(name);
12874         if (bcmd) {
12875                 if (IS_BUILTIN_REGULAR(bcmd))
12876                         goto builtin_success;
12877                 if (act & DO_ALTPATH) {
12878                         if (!(act & DO_ALTBLTIN))
12879                                 goto builtin_success;
12880                 } else if (builtinloc <= 0) {
12881                         goto builtin_success;
12882                 }
12883         }
12884
12885 #if ENABLE_FEATURE_SH_STANDALONE
12886         {
12887                 int applet_no = find_applet_by_name(name);
12888                 if (applet_no >= 0) {
12889                         entry->cmdtype = CMDNORMAL;
12890                         entry->u.index = -2 - applet_no;
12891                         return;
12892                 }
12893         }
12894 #endif
12895
12896         /* We have to search path. */
12897         prev = -1;              /* where to start */
12898         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12899                 if (cmdp->cmdtype == CMDBUILTIN)
12900                         prev = builtinloc;
12901                 else
12902                         prev = cmdp->param.index;
12903         }
12904
12905         e = ENOENT;
12906         idx = -1;
12907  loop:
12908         while ((fullname = path_advance(&path, name)) != NULL) {
12909                 stunalloc(fullname);
12910                 /* NB: code below will still use fullname
12911                  * despite it being "unallocated" */
12912                 idx++;
12913                 if (pathopt) {
12914                         if (prefix(pathopt, "builtin")) {
12915                                 if (bcmd)
12916                                         goto builtin_success;
12917                                 continue;
12918                         }
12919                         if ((act & DO_NOFUNC)
12920                          || !prefix(pathopt, "func")
12921                         ) {     /* ignore unimplemented options */
12922                                 continue;
12923                         }
12924                 }
12925                 /* if rehash, don't redo absolute path names */
12926                 if (fullname[0] == '/' && idx <= prev) {
12927                         if (idx < prev)
12928                                 continue;
12929                         TRACE(("searchexec \"%s\": no change\n", name));
12930                         goto success;
12931                 }
12932                 while (stat(fullname, &statb) < 0) {
12933 #ifdef SYSV
12934                         if (errno == EINTR)
12935                                 continue;
12936 #endif
12937                         if (errno != ENOENT && errno != ENOTDIR)
12938                                 e = errno;
12939                         goto loop;
12940                 }
12941                 e = EACCES;     /* if we fail, this will be the error */
12942                 if (!S_ISREG(statb.st_mode))
12943                         continue;
12944                 if (pathopt) {          /* this is a %func directory */
12945                         stalloc(strlen(fullname) + 1);
12946                         /* NB: stalloc will return space pointed by fullname
12947                          * (because we don't have any intervening allocations
12948                          * between stunalloc above and this stalloc) */
12949                         readcmdfile(fullname);
12950                         cmdp = cmdlookup(name, 0);
12951                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12952                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12953                         stunalloc(fullname);
12954                         goto success;
12955                 }
12956                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12957                 if (!updatetbl) {
12958                         entry->cmdtype = CMDNORMAL;
12959                         entry->u.index = idx;
12960                         return;
12961                 }
12962                 INT_OFF;
12963                 cmdp = cmdlookup(name, 1);
12964                 cmdp->cmdtype = CMDNORMAL;
12965                 cmdp->param.index = idx;
12966                 INT_ON;
12967                 goto success;
12968         }
12969
12970         /* We failed.  If there was an entry for this command, delete it */
12971         if (cmdp && updatetbl)
12972                 delete_cmd_entry();
12973         if (act & DO_ERR)
12974                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12975         entry->cmdtype = CMDUNKNOWN;
12976         return;
12977
12978  builtin_success:
12979         if (!updatetbl) {
12980                 entry->cmdtype = CMDBUILTIN;
12981                 entry->u.cmd = bcmd;
12982                 return;
12983         }
12984         INT_OFF;
12985         cmdp = cmdlookup(name, 1);
12986         cmdp->cmdtype = CMDBUILTIN;
12987         cmdp->param.cmd = bcmd;
12988         INT_ON;
12989  success:
12990         cmdp->rehash = 0;
12991         entry->cmdtype = cmdp->cmdtype;
12992         entry->u = cmdp->param;
12993 }
12994
12995
12996 /*
12997  * The trap builtin.
12998  */
12999 static int FAST_FUNC
13000 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13001 {
13002         char *action;
13003         char **ap;
13004         int signo, exitcode;
13005
13006         nextopt(nullstr);
13007         ap = argptr;
13008         if (!*ap) {
13009                 for (signo = 0; signo < NSIG; signo++) {
13010                         char *tr = trap_ptr[signo];
13011                         if (tr) {
13012                                 /* note: bash adds "SIG", but only if invoked
13013                                  * as "bash". If called as "sh", or if set -o posix,
13014                                  * then it prints short signal names.
13015                                  * We are printing short names: */
13016                                 out1fmt("trap -- %s %s\n",
13017                                                 single_quote(tr),
13018                                                 get_signame(signo));
13019                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13020                  * In this case, we will exit very soon, no need to free(). */
13021                                 /* if (trap_ptr != trap && tp[0]) */
13022                                 /*      free(tr); */
13023                         }
13024                 }
13025                 /*
13026                 if (trap_ptr != trap) {
13027                         free(trap_ptr);
13028                         trap_ptr = trap;
13029                 }
13030                 */
13031                 return 0;
13032         }
13033
13034         /* Why the second check?
13035          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13036          * In this case, NUM is signal no, not an action.
13037          */
13038         action = NULL;
13039         if (ap[1] && !is_number(ap[0]))
13040                 action = *ap++;
13041
13042         exitcode = 0;
13043         while (*ap) {
13044                 signo = get_signum(*ap);
13045                 if (signo < 0) {
13046                         /* Mimic bash message exactly */
13047                         ash_msg("%s: invalid signal specification", *ap);
13048                         exitcode = 1;
13049                         goto next;
13050                 }
13051                 INT_OFF;
13052                 if (action) {
13053                         if (LONE_DASH(action))
13054                                 action = NULL;
13055                         else {
13056                                 if (action[0]) /* not NULL and not "" and not "-" */
13057                                         may_have_traps = 1;
13058                                 action = ckstrdup(action);
13059                         }
13060                 }
13061                 free(trap[signo]);
13062                 trap[signo] = action;
13063                 if (signo != 0)
13064                         setsignal(signo);
13065                 INT_ON;
13066  next:
13067                 ap++;
13068         }
13069         return exitcode;
13070 }
13071
13072
13073 /* ============ Builtins */
13074
13075 #if ENABLE_ASH_HELP
13076 static int FAST_FUNC
13077 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13078 {
13079         unsigned col;
13080         unsigned i;
13081
13082         out1fmt(
13083                 "Built-in commands:\n"
13084                 "------------------\n");
13085         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13086                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13087                                         builtintab[i].name + 1);
13088                 if (col > 60) {
13089                         out1fmt("\n");
13090                         col = 0;
13091                 }
13092         }
13093 # if ENABLE_FEATURE_SH_STANDALONE
13094         {
13095                 const char *a = applet_names;
13096                 while (*a) {
13097                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13098                         if (col > 60) {
13099                                 out1fmt("\n");
13100                                 col = 0;
13101                         }
13102                         while (*a++ != '\0')
13103                                 continue;
13104                 }
13105         }
13106 # endif
13107         newline_and_flush(stdout);
13108         return EXIT_SUCCESS;
13109 }
13110 #endif
13111
13112 #if MAX_HISTORY
13113 static int FAST_FUNC
13114 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13115 {
13116         show_history(line_input_state);
13117         return EXIT_SUCCESS;
13118 }
13119 #endif
13120
13121 /*
13122  * The export and readonly commands.
13123  */
13124 static int FAST_FUNC
13125 exportcmd(int argc UNUSED_PARAM, char **argv)
13126 {
13127         struct var *vp;
13128         char *name;
13129         const char *p;
13130         char **aptr;
13131         char opt;
13132         int flag;
13133         int flag_off;
13134
13135         /* "readonly" in bash accepts, but ignores -n.
13136          * We do the same: it saves a conditional in nextopt's param.
13137          */
13138         flag_off = 0;
13139         while ((opt = nextopt("np")) != '\0') {
13140                 if (opt == 'n')
13141                         flag_off = VEXPORT;
13142         }
13143         flag = VEXPORT;
13144         if (argv[0][0] == 'r') {
13145                 flag = VREADONLY;
13146                 flag_off = 0; /* readonly ignores -n */
13147         }
13148         flag_off = ~flag_off;
13149
13150         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13151         {
13152                 aptr = argptr;
13153                 name = *aptr;
13154                 if (name) {
13155                         do {
13156                                 p = strchr(name, '=');
13157                                 if (p != NULL) {
13158                                         p++;
13159                                 } else {
13160                                         vp = *findvar(hashvar(name), name);
13161                                         if (vp) {
13162                                                 vp->flags = ((vp->flags | flag) & flag_off);
13163                                                 continue;
13164                                         }
13165                                 }
13166                                 setvar(name, p, (flag & flag_off));
13167                         } while ((name = *++aptr) != NULL);
13168                         return 0;
13169                 }
13170         }
13171
13172         /* No arguments. Show the list of exported or readonly vars.
13173          * -n is ignored.
13174          */
13175         showvars(argv[0], flag, 0);
13176         return 0;
13177 }
13178
13179 /*
13180  * Delete a function if it exists.
13181  */
13182 static void
13183 unsetfunc(const char *name)
13184 {
13185         struct tblentry *cmdp;
13186
13187         cmdp = cmdlookup(name, 0);
13188         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13189                 delete_cmd_entry();
13190 }
13191
13192 /*
13193  * The unset builtin command.  We unset the function before we unset the
13194  * variable to allow a function to be unset when there is a readonly variable
13195  * with the same name.
13196  */
13197 static int FAST_FUNC
13198 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13199 {
13200         char **ap;
13201         int i;
13202         int flag = 0;
13203
13204         while ((i = nextopt("vf")) != 0) {
13205                 flag = i;
13206         }
13207
13208         for (ap = argptr; *ap; ap++) {
13209                 if (flag != 'f') {
13210                         unsetvar(*ap);
13211                         continue;
13212                 }
13213                 if (flag != 'v')
13214                         unsetfunc(*ap);
13215         }
13216         return 0;
13217 }
13218
13219 static const unsigned char timescmd_str[] ALIGN1 = {
13220         ' ',  offsetof(struct tms, tms_utime),
13221         '\n', offsetof(struct tms, tms_stime),
13222         ' ',  offsetof(struct tms, tms_cutime),
13223         '\n', offsetof(struct tms, tms_cstime),
13224         0
13225 };
13226 static int FAST_FUNC
13227 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13228 {
13229         unsigned long clk_tck, s, t;
13230         const unsigned char *p;
13231         struct tms buf;
13232
13233         clk_tck = bb_clk_tck();
13234         times(&buf);
13235
13236         p = timescmd_str;
13237         do {
13238                 t = *(clock_t *)(((char *) &buf) + p[1]);
13239                 s = t / clk_tck;
13240                 t = t % clk_tck;
13241                 out1fmt("%lum%lu.%03lus%c",
13242                         s / 60, s % 60,
13243                         (t * 1000) / clk_tck,
13244                         p[0]);
13245                 p += 2;
13246         } while (*p);
13247
13248         return 0;
13249 }
13250
13251 #if ENABLE_FEATURE_SH_MATH
13252 /*
13253  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13254  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13255  *
13256  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13257  */
13258 static int FAST_FUNC
13259 letcmd(int argc UNUSED_PARAM, char **argv)
13260 {
13261         arith_t i;
13262
13263         argv++;
13264         if (!*argv)
13265                 ash_msg_and_raise_error("expression expected");
13266         do {
13267                 i = ash_arith(*argv);
13268         } while (*++argv);
13269
13270         return !i;
13271 }
13272 #endif
13273
13274 /*
13275  * The read builtin. Options:
13276  *      -r              Do not interpret '\' specially
13277  *      -s              Turn off echo (tty only)
13278  *      -n NCHARS       Read NCHARS max
13279  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13280  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13281  *      -u FD           Read from given FD instead of fd 0
13282  * This uses unbuffered input, which may be avoidable in some cases.
13283  * TODO: bash also has:
13284  *      -a ARRAY        Read into array[0],[1],etc
13285  *      -d DELIM        End on DELIM char, not newline
13286  *      -e              Use line editing (tty only)
13287  */
13288 static int FAST_FUNC
13289 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13290 {
13291         char *opt_n = NULL;
13292         char *opt_p = NULL;
13293         char *opt_t = NULL;
13294         char *opt_u = NULL;
13295         int read_flags = 0;
13296         const char *r;
13297         int i;
13298
13299         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13300                 switch (i) {
13301                 case 'p':
13302                         opt_p = optionarg;
13303                         break;
13304                 case 'n':
13305                         opt_n = optionarg;
13306                         break;
13307                 case 's':
13308                         read_flags |= BUILTIN_READ_SILENT;
13309                         break;
13310                 case 't':
13311                         opt_t = optionarg;
13312                         break;
13313                 case 'r':
13314                         read_flags |= BUILTIN_READ_RAW;
13315                         break;
13316                 case 'u':
13317                         opt_u = optionarg;
13318                         break;
13319                 default:
13320                         break;
13321                 }
13322         }
13323
13324         /* "read -s" needs to save/restore termios, can't allow ^C
13325          * to jump out of it.
13326          */
13327  again:
13328         INT_OFF;
13329         r = shell_builtin_read(setvar0,
13330                 argptr,
13331                 bltinlookup("IFS"), /* can be NULL */
13332                 read_flags,
13333                 opt_n,
13334                 opt_p,
13335                 opt_t,
13336                 opt_u
13337         );
13338         INT_ON;
13339
13340         if ((uintptr_t)r == 1 && errno == EINTR) {
13341                 /* to get SIGCHLD: sleep 1 & read x; echo $x */
13342                 if (pending_sig == 0)
13343                         goto again;
13344         }
13345
13346         if ((uintptr_t)r > 1)
13347                 ash_msg_and_raise_error(r);
13348
13349         return (uintptr_t)r;
13350 }
13351
13352 static int FAST_FUNC
13353 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13354 {
13355         static const char permuser[3] ALIGN1 = "ogu";
13356
13357         mode_t mask;
13358         int symbolic_mode = 0;
13359
13360         while (nextopt("S") != '\0') {
13361                 symbolic_mode = 1;
13362         }
13363
13364         INT_OFF;
13365         mask = umask(0);
13366         umask(mask);
13367         INT_ON;
13368
13369         if (*argptr == NULL) {
13370                 if (symbolic_mode) {
13371                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13372                         char *p = buf;
13373                         int i;
13374
13375                         i = 2;
13376                         for (;;) {
13377                                 *p++ = ',';
13378                                 *p++ = permuser[i];
13379                                 *p++ = '=';
13380                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13381                                 if (!(mask & 0400)) *p++ = 'r';
13382                                 if (!(mask & 0200)) *p++ = 'w';
13383                                 if (!(mask & 0100)) *p++ = 'x';
13384                                 mask <<= 3;
13385                                 if (--i < 0)
13386                                         break;
13387                         }
13388                         *p = '\0';
13389                         puts(buf + 1);
13390                 } else {
13391                         out1fmt("%04o\n", mask);
13392                 }
13393         } else {
13394                 char *modestr = *argptr;
13395                 /* numeric umasks are taken as-is */
13396                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13397                 if (!isdigit(modestr[0]))
13398                         mask ^= 0777;
13399                 mask = bb_parse_mode(modestr, mask);
13400                 if ((unsigned)mask > 0777) {
13401                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13402                 }
13403                 if (!isdigit(modestr[0]))
13404                         mask ^= 0777;
13405                 umask(mask);
13406         }
13407         return 0;
13408 }
13409
13410 static int FAST_FUNC
13411 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13412 {
13413         return shell_builtin_ulimit(argv);
13414 }
13415
13416 /* ============ main() and helpers */
13417
13418 /*
13419  * Called to exit the shell.
13420  */
13421 static void
13422 exitshell(void)
13423 {
13424         struct jmploc loc;
13425         char *p;
13426         int status;
13427
13428 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13429         save_history(line_input_state);
13430 #endif
13431         status = exitstatus;
13432         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13433         if (setjmp(loc.loc)) {
13434                 if (exception_type == EXEXIT)
13435                         status = exitstatus;
13436                 goto out;
13437         }
13438         exception_handler = &loc;
13439         p = trap[0];
13440         if (p) {
13441                 trap[0] = NULL;
13442                 evalskip = 0;
13443                 evalstring(p, 0);
13444                 /*free(p); - we'll exit soon */
13445         }
13446  out:
13447         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13448          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13449          */
13450         setjobctl(0);
13451         flush_stdout_stderr();
13452         _exit(status);
13453         /* NOTREACHED */
13454 }
13455
13456 static void
13457 init(void)
13458 {
13459         /* we will never free this */
13460         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13461
13462         sigmode[SIGCHLD - 1] = S_DFL;
13463         setsignal(SIGCHLD);
13464
13465         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13466          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13467          */
13468         signal(SIGHUP, SIG_DFL);
13469
13470         {
13471                 char **envp;
13472                 const char *p;
13473                 struct stat st1, st2;
13474
13475                 initvar();
13476                 for (envp = environ; envp && *envp; envp++) {
13477                         p = endofname(*envp);
13478                         if (p != *envp && *p == '=') {
13479                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13480                         }
13481                 }
13482
13483                 setvareq((char*)defoptindvar, VTEXTFIXED);
13484
13485                 setvar0("PPID", utoa(getppid()));
13486 #if BASH_SHLVL_VAR
13487                 p = lookupvar("SHLVL");
13488                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13489 #endif
13490 #if BASH_HOSTNAME_VAR
13491                 if (!lookupvar("HOSTNAME")) {
13492                         struct utsname uts;
13493                         uname(&uts);
13494                         setvar0("HOSTNAME", uts.nodename);
13495                 }
13496 #endif
13497                 p = lookupvar("PWD");
13498                 if (p) {
13499                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13500                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13501                         ) {
13502                                 p = NULL;
13503                         }
13504                 }
13505                 setpwd(p, 0);
13506         }
13507 }
13508
13509
13510 //usage:#define ash_trivial_usage
13511 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13512 //usage:#define ash_full_usage "\n\n"
13513 //usage:        "Unix shell interpreter"
13514
13515 /*
13516  * Process the shell command line arguments.
13517  */
13518 static void
13519 procargs(char **argv)
13520 {
13521         int i;
13522         const char *xminusc;
13523         char **xargv;
13524
13525         xargv = argv;
13526         arg0 = xargv[0];
13527         /* if (xargv[0]) - mmm, this is always true! */
13528                 xargv++;
13529         for (i = 0; i < NOPTS; i++)
13530                 optlist[i] = 2;
13531         argptr = xargv;
13532         if (options(/*cmdline:*/ 1)) {
13533                 /* it already printed err message */
13534                 raise_exception(EXERROR);
13535         }
13536         xargv = argptr;
13537         xminusc = minusc;
13538         if (*xargv == NULL) {
13539                 if (xminusc)
13540                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13541                 sflag = 1;
13542         }
13543         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13544                 iflag = 1;
13545         if (mflag == 2)
13546                 mflag = iflag;
13547         for (i = 0; i < NOPTS; i++)
13548                 if (optlist[i] == 2)
13549                         optlist[i] = 0;
13550 #if DEBUG == 2
13551         debug = 1;
13552 #endif
13553         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13554         if (xminusc) {
13555                 minusc = *xargv++;
13556                 if (*xargv)
13557                         goto setarg0;
13558         } else if (!sflag) {
13559                 setinputfile(*xargv, 0);
13560  setarg0:
13561                 arg0 = *xargv++;
13562                 commandname = arg0;
13563         }
13564
13565         shellparam.p = xargv;
13566 #if ENABLE_ASH_GETOPTS
13567         shellparam.optind = 1;
13568         shellparam.optoff = -1;
13569 #endif
13570         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13571         while (*xargv) {
13572                 shellparam.nparam++;
13573                 xargv++;
13574         }
13575         optschanged();
13576 }
13577
13578 /*
13579  * Read /etc/profile, ~/.profile, $ENV.
13580  */
13581 static void
13582 read_profile(const char *name)
13583 {
13584         name = expandstr(name, DQSYNTAX);
13585         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13586                 return;
13587         cmdloop(0);
13588         popfile();
13589 }
13590
13591 /*
13592  * This routine is called when an error or an interrupt occurs in an
13593  * interactive shell and control is returned to the main command loop.
13594  * (In dash, this function is auto-generated by build machinery).
13595  */
13596 static void
13597 reset(void)
13598 {
13599         /* from eval.c: */
13600         evalskip = 0;
13601         loopnest = 0;
13602
13603         /* from expand.c: */
13604         ifsfree();
13605
13606         /* from input.c: */
13607         g_parsefile->left_in_buffer = 0;
13608         g_parsefile->left_in_line = 0;      /* clear input buffer */
13609         popallfiles();
13610
13611         /* from redir.c: */
13612         unwindredir(NULL);
13613
13614         /* from var.c: */
13615         unwindlocalvars(NULL);
13616 }
13617
13618 #if PROFILE
13619 static short profile_buf[16384];
13620 extern int etext();
13621 #endif
13622
13623 /*
13624  * Main routine.  We initialize things, parse the arguments, execute
13625  * profiles if we're a login shell, and then call cmdloop to execute
13626  * commands.  The setjmp call sets up the location to jump to when an
13627  * exception occurs.  When an exception occurs the variable "state"
13628  * is used to figure out how far we had gotten.
13629  */
13630 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13631 int ash_main(int argc UNUSED_PARAM, char **argv)
13632 {
13633         volatile smallint state;
13634         struct jmploc jmploc;
13635         struct stackmark smark;
13636
13637         /* Initialize global data */
13638         INIT_G_misc();
13639         INIT_G_memstack();
13640         INIT_G_var();
13641 #if ENABLE_ASH_ALIAS
13642         INIT_G_alias();
13643 #endif
13644         INIT_G_cmdtable();
13645
13646 #if PROFILE
13647         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13648 #endif
13649
13650 #if ENABLE_FEATURE_EDITING
13651         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13652 #endif
13653         state = 0;
13654         if (setjmp(jmploc.loc)) {
13655                 smallint e;
13656                 smallint s;
13657
13658                 reset();
13659
13660                 e = exception_type;
13661                 s = state;
13662                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13663                         exitshell();
13664                 }
13665                 if (e == EXINT) {
13666                         newline_and_flush(stderr);
13667                 }
13668
13669                 popstackmark(&smark);
13670                 FORCE_INT_ON; /* enable interrupts */
13671                 if (s == 1)
13672                         goto state1;
13673                 if (s == 2)
13674                         goto state2;
13675                 if (s == 3)
13676                         goto state3;
13677                 goto state4;
13678         }
13679         exception_handler = &jmploc;
13680         rootpid = getpid();
13681
13682         init();
13683         setstackmark(&smark);
13684         procargs(argv);
13685 #if DEBUG
13686         TRACE(("Shell args: "));
13687         trace_puts_args(argv);
13688 #endif
13689
13690         if (argv[0] && argv[0][0] == '-')
13691                 isloginsh = 1;
13692         if (isloginsh) {
13693                 const char *hp;
13694
13695                 state = 1;
13696                 read_profile("/etc/profile");
13697  state1:
13698                 state = 2;
13699                 hp = lookupvar("HOME");
13700                 if (hp)
13701                         read_profile("$HOME/.profile");
13702         }
13703  state2:
13704         state = 3;
13705         if (
13706 #ifndef linux
13707          getuid() == geteuid() && getgid() == getegid() &&
13708 #endif
13709          iflag
13710         ) {
13711                 const char *shinit = lookupvar("ENV");
13712                 if (shinit != NULL && *shinit != '\0')
13713                         read_profile(shinit);
13714         }
13715         popstackmark(&smark);
13716  state3:
13717         state = 4;
13718         if (minusc) {
13719                 /* evalstring pushes parsefile stack.
13720                  * Ensure we don't falsely claim that 0 (stdin)
13721                  * is one of stacked source fds.
13722                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13723                 // if (!sflag) g_parsefile->pf_fd = -1;
13724                 // ^^ not necessary since now we special-case fd 0
13725                 // in is_hidden_fd() to not be considered "hidden fd"
13726                 evalstring(minusc, sflag ? 0 : EV_EXIT);
13727         }
13728
13729         if (sflag || minusc == NULL) {
13730 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13731                 if (iflag) {
13732                         const char *hp = lookupvar("HISTFILE");
13733                         if (!hp) {
13734                                 hp = lookupvar("HOME");
13735                                 if (hp) {
13736                                         INT_OFF;
13737                                         hp = concat_path_file(hp, ".ash_history");
13738                                         setvar0("HISTFILE", hp);
13739                                         free((char*)hp);
13740                                         INT_ON;
13741                                         hp = lookupvar("HISTFILE");
13742                                 }
13743                         }
13744                         if (hp)
13745                                 line_input_state->hist_file = hp;
13746 # if ENABLE_FEATURE_SH_HISTFILESIZE
13747                         hp = lookupvar("HISTFILESIZE");
13748                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13749 # endif
13750                 }
13751 #endif
13752  state4: /* XXX ??? - why isn't this before the "if" statement */
13753                 cmdloop(1);
13754         }
13755 #if PROFILE
13756         monitor(0);
13757 #endif
13758 #ifdef GPROF
13759         {
13760                 extern void _mcleanup(void);
13761                 _mcleanup();
13762         }
13763 #endif
13764         TRACE(("End of main reached\n"));
13765         exitshell();
13766         /* NOTREACHED */
13767 }
13768
13769
13770 /*-
13771  * Copyright (c) 1989, 1991, 1993, 1994
13772  *      The Regents of the University of California.  All rights reserved.
13773  *
13774  * This code is derived from software contributed to Berkeley by
13775  * Kenneth Almquist.
13776  *
13777  * Redistribution and use in source and binary forms, with or without
13778  * modification, are permitted provided that the following conditions
13779  * are met:
13780  * 1. Redistributions of source code must retain the above copyright
13781  *    notice, this list of conditions and the following disclaimer.
13782  * 2. Redistributions in binary form must reproduce the above copyright
13783  *    notice, this list of conditions and the following disclaimer in the
13784  *    documentation and/or other materials provided with the distribution.
13785  * 3. Neither the name of the University nor the names of its contributors
13786  *    may be used to endorse or promote products derived from this software
13787  *    without specific prior written permission.
13788  *
13789  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13790  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13791  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13792  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13793  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13794  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13795  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13796  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13797  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13798  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13799  * SUCH DAMAGE.
13800  */