ash: [VAR] Fix poplocalvar leak
[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 static struct strlist *cmdenviron;     /* environment for builtin command */
1254
1255
1256 /* ============ Message printing */
1257
1258 static void
1259 ash_vmsg(const char *msg, va_list ap)
1260 {
1261         fprintf(stderr, "%s: ", arg0);
1262         if (commandname) {
1263                 if (strcmp(arg0, commandname))
1264                         fprintf(stderr, "%s: ", commandname);
1265                 if (!iflag || g_parsefile->pf_fd > 0)
1266                         fprintf(stderr, "line %d: ", startlinno);
1267         }
1268         vfprintf(stderr, msg, ap);
1269         newline_and_flush(stderr);
1270 }
1271
1272 /*
1273  * Exverror is called to raise the error exception.  If the second argument
1274  * is not NULL then error prints an error message using printf style
1275  * formatting.  It then raises the error exception.
1276  */
1277 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1278 static void
1279 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1280 {
1281 #if DEBUG
1282         if (msg) {
1283                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1284                 TRACEV((msg, ap));
1285         } else
1286                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1287         if (msg)
1288 #endif
1289                 ash_vmsg(msg, ap);
1290
1291         flush_stdout_stderr();
1292         raise_exception(cond);
1293         /* NOTREACHED */
1294 }
1295
1296 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1297 static void
1298 ash_msg_and_raise_error(const char *msg, ...)
1299 {
1300         va_list ap;
1301
1302         exitstatus = 2;
1303
1304         va_start(ap, msg);
1305         ash_vmsg_and_raise(EXERROR, msg, ap);
1306         /* NOTREACHED */
1307         va_end(ap);
1308 }
1309
1310 static void raise_error_syntax(const char *) NORETURN;
1311 static void
1312 raise_error_syntax(const char *msg)
1313 {
1314         ash_msg_and_raise_error("syntax error: %s", msg);
1315         /* NOTREACHED */
1316 }
1317
1318 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1319 static void
1320 ash_msg_and_raise(int cond, const char *msg, ...)
1321 {
1322         va_list ap;
1323
1324         va_start(ap, msg);
1325         ash_vmsg_and_raise(cond, msg, ap);
1326         /* NOTREACHED */
1327         va_end(ap);
1328 }
1329
1330 /*
1331  * error/warning routines for external builtins
1332  */
1333 static void
1334 ash_msg(const char *fmt, ...)
1335 {
1336         va_list ap;
1337
1338         va_start(ap, fmt);
1339         ash_vmsg(fmt, ap);
1340         va_end(ap);
1341 }
1342
1343 /*
1344  * Return a string describing an error.  The returned string may be a
1345  * pointer to a static buffer that will be overwritten on the next call.
1346  * Action describes the operation that got the error.
1347  */
1348 static const char *
1349 errmsg(int e, const char *em)
1350 {
1351         if (e == ENOENT || e == ENOTDIR) {
1352                 return em;
1353         }
1354         return strerror(e);
1355 }
1356
1357
1358 /* ============ Memory allocation */
1359
1360 #if 0
1361 /* I consider these wrappers nearly useless:
1362  * ok, they return you to nearest exception handler, but
1363  * how much memory do you leak in the process, making
1364  * memory starvation worse?
1365  */
1366 static void *
1367 ckrealloc(void * p, size_t nbytes)
1368 {
1369         p = realloc(p, nbytes);
1370         if (!p)
1371                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1372         return p;
1373 }
1374
1375 static void *
1376 ckmalloc(size_t nbytes)
1377 {
1378         return ckrealloc(NULL, nbytes);
1379 }
1380
1381 static void *
1382 ckzalloc(size_t nbytes)
1383 {
1384         return memset(ckmalloc(nbytes), 0, nbytes);
1385 }
1386
1387 static char *
1388 ckstrdup(const char *s)
1389 {
1390         char *p = strdup(s);
1391         if (!p)
1392                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1393         return p;
1394 }
1395 #else
1396 /* Using bbox equivalents. They exit if out of memory */
1397 # define ckrealloc xrealloc
1398 # define ckmalloc  xmalloc
1399 # define ckzalloc  xzalloc
1400 # define ckstrdup  xstrdup
1401 #endif
1402
1403 /*
1404  * It appears that grabstackstr() will barf with such alignments
1405  * because stalloc() will return a string allocated in a new stackblock.
1406  */
1407 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1408 enum {
1409         /* Most machines require the value returned from malloc to be aligned
1410          * in some way.  The following macro will get this right
1411          * on many machines.  */
1412         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1413         /* Minimum size of a block */
1414         MINSIZE = SHELL_ALIGN(504),
1415 };
1416
1417 struct stack_block {
1418         struct stack_block *prev;
1419         char space[MINSIZE];
1420 };
1421
1422 struct stackmark {
1423         struct stack_block *stackp;
1424         char *stacknxt;
1425         size_t stacknleft;
1426 };
1427
1428
1429 struct globals_memstack {
1430         struct stack_block *g_stackp; // = &stackbase;
1431         char *g_stacknxt; // = stackbase.space;
1432         char *sstrend; // = stackbase.space + MINSIZE;
1433         size_t g_stacknleft; // = MINSIZE;
1434         struct stack_block stackbase;
1435 };
1436 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1437 #define G_memstack (*ash_ptr_to_globals_memstack)
1438 #define g_stackp     (G_memstack.g_stackp    )
1439 #define g_stacknxt   (G_memstack.g_stacknxt  )
1440 #define sstrend      (G_memstack.sstrend     )
1441 #define g_stacknleft (G_memstack.g_stacknleft)
1442 #define stackbase    (G_memstack.stackbase   )
1443 #define INIT_G_memstack() do { \
1444         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1445         barrier(); \
1446         g_stackp = &stackbase; \
1447         g_stacknxt = stackbase.space; \
1448         g_stacknleft = MINSIZE; \
1449         sstrend = stackbase.space + MINSIZE; \
1450 } while (0)
1451
1452
1453 #define stackblock()     ((void *)g_stacknxt)
1454 #define stackblocksize() g_stacknleft
1455
1456 /*
1457  * Parse trees for commands are allocated in lifo order, so we use a stack
1458  * to make this more efficient, and also to avoid all sorts of exception
1459  * handling code to handle interrupts in the middle of a parse.
1460  *
1461  * The size 504 was chosen because the Ultrix malloc handles that size
1462  * well.
1463  */
1464 static void *
1465 stalloc(size_t nbytes)
1466 {
1467         char *p;
1468         size_t aligned;
1469
1470         aligned = SHELL_ALIGN(nbytes);
1471         if (aligned > g_stacknleft) {
1472                 size_t len;
1473                 size_t blocksize;
1474                 struct stack_block *sp;
1475
1476                 blocksize = aligned;
1477                 if (blocksize < MINSIZE)
1478                         blocksize = MINSIZE;
1479                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1480                 if (len < blocksize)
1481                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1482                 INT_OFF;
1483                 sp = ckmalloc(len);
1484                 sp->prev = g_stackp;
1485                 g_stacknxt = sp->space;
1486                 g_stacknleft = blocksize;
1487                 sstrend = g_stacknxt + blocksize;
1488                 g_stackp = sp;
1489                 INT_ON;
1490         }
1491         p = g_stacknxt;
1492         g_stacknxt += aligned;
1493         g_stacknleft -= aligned;
1494         return p;
1495 }
1496
1497 static void *
1498 stzalloc(size_t nbytes)
1499 {
1500         return memset(stalloc(nbytes), 0, nbytes);
1501 }
1502
1503 static void
1504 stunalloc(void *p)
1505 {
1506 #if DEBUG
1507         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1508                 write(STDERR_FILENO, "stunalloc\n", 10);
1509                 abort();
1510         }
1511 #endif
1512         g_stacknleft += g_stacknxt - (char *)p;
1513         g_stacknxt = p;
1514 }
1515
1516 /*
1517  * Like strdup but works with the ash stack.
1518  */
1519 static char *
1520 sstrdup(const char *p)
1521 {
1522         size_t len = strlen(p) + 1;
1523         return memcpy(stalloc(len), p, len);
1524 }
1525
1526 static inline void
1527 grabstackblock(size_t len)
1528 {
1529         stalloc(len);
1530 }
1531
1532 static void
1533 pushstackmark(struct stackmark *mark, size_t len)
1534 {
1535         mark->stackp = g_stackp;
1536         mark->stacknxt = g_stacknxt;
1537         mark->stacknleft = g_stacknleft;
1538         grabstackblock(len);
1539 }
1540
1541 static void
1542 setstackmark(struct stackmark *mark)
1543 {
1544         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1545 }
1546
1547 static void
1548 popstackmark(struct stackmark *mark)
1549 {
1550         struct stack_block *sp;
1551
1552         if (!mark->stackp)
1553                 return;
1554
1555         INT_OFF;
1556         while (g_stackp != mark->stackp) {
1557                 sp = g_stackp;
1558                 g_stackp = sp->prev;
1559                 free(sp);
1560         }
1561         g_stacknxt = mark->stacknxt;
1562         g_stacknleft = mark->stacknleft;
1563         sstrend = mark->stacknxt + mark->stacknleft;
1564         INT_ON;
1565 }
1566
1567 /*
1568  * When the parser reads in a string, it wants to stick the string on the
1569  * stack and only adjust the stack pointer when it knows how big the
1570  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1571  * of space on top of the stack and stackblocklen returns the length of
1572  * this block.  Growstackblock will grow this space by at least one byte,
1573  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1574  * part of the block that has been used.
1575  */
1576 static void
1577 growstackblock(void)
1578 {
1579         size_t newlen;
1580
1581         newlen = g_stacknleft * 2;
1582         if (newlen < g_stacknleft)
1583                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1584         if (newlen < 128)
1585                 newlen += 128;
1586
1587         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1588                 struct stack_block *sp;
1589                 struct stack_block *prevstackp;
1590                 size_t grosslen;
1591
1592                 INT_OFF;
1593                 sp = g_stackp;
1594                 prevstackp = sp->prev;
1595                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1596                 sp = ckrealloc(sp, grosslen);
1597                 sp->prev = prevstackp;
1598                 g_stackp = sp;
1599                 g_stacknxt = sp->space;
1600                 g_stacknleft = newlen;
1601                 sstrend = sp->space + newlen;
1602                 INT_ON;
1603         } else {
1604                 char *oldspace = g_stacknxt;
1605                 size_t oldlen = g_stacknleft;
1606                 char *p = stalloc(newlen);
1607
1608                 /* free the space we just allocated */
1609                 g_stacknxt = memcpy(p, oldspace, oldlen);
1610                 g_stacknleft += newlen;
1611         }
1612 }
1613
1614 /*
1615  * The following routines are somewhat easier to use than the above.
1616  * The user declares a variable of type STACKSTR, which may be declared
1617  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1618  * the user uses the macro STPUTC to add characters to the string.  In
1619  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1620  * grown as necessary.  When the user is done, she can just leave the
1621  * string there and refer to it using stackblock().  Or she can allocate
1622  * the space for it using grabstackstr().  If it is necessary to allow
1623  * someone else to use the stack temporarily and then continue to grow
1624  * the string, the user should use grabstack to allocate the space, and
1625  * then call ungrabstr(p) to return to the previous mode of operation.
1626  *
1627  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1628  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1629  * is space for at least one character.
1630  */
1631 static void *
1632 growstackstr(void)
1633 {
1634         size_t len = stackblocksize();
1635         growstackblock();
1636         return (char *)stackblock() + len;
1637 }
1638
1639 /*
1640  * Called from CHECKSTRSPACE.
1641  */
1642 static char *
1643 makestrspace(size_t newlen, char *p)
1644 {
1645         size_t len = p - g_stacknxt;
1646         size_t size;
1647
1648         for (;;) {
1649                 size_t nleft;
1650
1651                 size = stackblocksize();
1652                 nleft = size - len;
1653                 if (nleft >= newlen)
1654                         break;
1655                 growstackblock();
1656         }
1657         return (char *)stackblock() + len;
1658 }
1659
1660 static char *
1661 stack_nputstr(const char *s, size_t n, char *p)
1662 {
1663         p = makestrspace(n, p);
1664         p = (char *)mempcpy(p, s, n);
1665         return p;
1666 }
1667
1668 static char *
1669 stack_putstr(const char *s, char *p)
1670 {
1671         return stack_nputstr(s, strlen(s), p);
1672 }
1673
1674 static char *
1675 _STPUTC(int c, char *p)
1676 {
1677         if (p == sstrend)
1678                 p = growstackstr();
1679         *p++ = c;
1680         return p;
1681 }
1682
1683 #define STARTSTACKSTR(p)        ((p) = stackblock())
1684 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1685 #define CHECKSTRSPACE(n, p) do { \
1686         char *q = (p); \
1687         size_t l = (n); \
1688         size_t m = sstrend - q; \
1689         if (l > m) \
1690                 (p) = makestrspace(l, q); \
1691 } while (0)
1692 #define USTPUTC(c, p)           (*(p)++ = (c))
1693 #define STACKSTRNUL(p) do { \
1694         if ((p) == sstrend) \
1695                 (p) = growstackstr(); \
1696         *(p) = '\0'; \
1697 } while (0)
1698 #define STUNPUTC(p)             (--(p))
1699 #define STTOPC(p)               ((p)[-1])
1700 #define STADJUST(amount, p)     ((p) += (amount))
1701
1702 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1703 #define ungrabstackstr(s, p)    stunalloc(s)
1704 #define stackstrend()           ((void *)sstrend)
1705
1706
1707 /* ============ String helpers */
1708
1709 /*
1710  * prefix -- see if pfx is a prefix of string.
1711  */
1712 static char *
1713 prefix(const char *string, const char *pfx)
1714 {
1715         while (*pfx) {
1716                 if (*pfx++ != *string++)
1717                         return NULL;
1718         }
1719         return (char *) string;
1720 }
1721
1722 /*
1723  * Check for a valid number.  This should be elsewhere.
1724  */
1725 static int
1726 is_number(const char *p)
1727 {
1728         do {
1729                 if (!isdigit(*p))
1730                         return 0;
1731         } while (*++p != '\0');
1732         return 1;
1733 }
1734
1735 /*
1736  * Convert a string of digits to an integer, printing an error message on
1737  * failure.
1738  */
1739 static int
1740 number(const char *s)
1741 {
1742         if (!is_number(s))
1743                 ash_msg_and_raise_error(msg_illnum, s);
1744         return atoi(s);
1745 }
1746
1747 /*
1748  * Produce a single quoted string suitable as input to the shell.
1749  * The return string is allocated on the stack.
1750  */
1751 static char *
1752 single_quote(const char *s)
1753 {
1754         char *p;
1755
1756         STARTSTACKSTR(p);
1757
1758         do {
1759                 char *q;
1760                 size_t len;
1761
1762                 len = strchrnul(s, '\'') - s;
1763
1764                 q = p = makestrspace(len + 3, p);
1765
1766                 *q++ = '\'';
1767                 q = (char *)mempcpy(q, s, len);
1768                 *q++ = '\'';
1769                 s += len;
1770
1771                 STADJUST(q - p, p);
1772
1773                 if (*s != '\'')
1774                         break;
1775                 len = 0;
1776                 do len++; while (*++s == '\'');
1777
1778                 q = p = makestrspace(len + 3, p);
1779
1780                 *q++ = '"';
1781                 q = (char *)mempcpy(q, s - len, len);
1782                 *q++ = '"';
1783
1784                 STADJUST(q - p, p);
1785         } while (*s);
1786
1787         USTPUTC('\0', p);
1788
1789         return stackblock();
1790 }
1791
1792 /*
1793  * Produce a possibly single quoted string suitable as input to the shell.
1794  * If quoting was done, the return string is allocated on the stack,
1795  * otherwise a pointer to the original string is returned.
1796  */
1797 static const char *
1798 maybe_single_quote(const char *s)
1799 {
1800         const char *p = s;
1801
1802         while (*p) {
1803                 /* Assuming ACSII */
1804                 /* quote ctrl_chars space !"#$%&'()* */
1805                 if (*p < '+')
1806                         goto need_quoting;
1807                 /* quote ;<=>? */
1808                 if (*p >= ';' && *p <= '?')
1809                         goto need_quoting;
1810                 /* quote `[\ */
1811                 if (*p == '`')
1812                         goto need_quoting;
1813                 if (*p == '[')
1814                         goto need_quoting;
1815                 if (*p == '\\')
1816                         goto need_quoting;
1817                 /* quote {|}~ DEL and high bytes */
1818                 if (*p > 'z')
1819                         goto need_quoting;
1820                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1821                 /* TODO: maybe avoid quoting % */
1822                 p++;
1823         }
1824         return s;
1825
1826  need_quoting:
1827         return single_quote(s);
1828 }
1829
1830
1831 /* ============ nextopt */
1832
1833 static char **argptr;                  /* argument list for builtin commands */
1834 static char *optionarg;                /* set by nextopt (like getopt) */
1835 static char *optptr;                   /* used by nextopt */
1836
1837 /*
1838  * XXX - should get rid of. Have all builtins use getopt(3).
1839  * The library getopt must have the BSD extension static variable
1840  * "optreset", otherwise it can't be used within the shell safely.
1841  *
1842  * Standard option processing (a la getopt) for builtin routines.
1843  * The only argument that is passed to nextopt is the option string;
1844  * the other arguments are unnecessary. It returns the character,
1845  * or '\0' on end of input.
1846  */
1847 static int
1848 nextopt(const char *optstring)
1849 {
1850         char *p;
1851         const char *q;
1852         char c;
1853
1854         p = optptr;
1855         if (p == NULL || *p == '\0') {
1856                 /* We ate entire "-param", take next one */
1857                 p = *argptr;
1858                 if (p == NULL)
1859                         return '\0';
1860                 if (*p != '-')
1861                         return '\0';
1862                 if (*++p == '\0') /* just "-" ? */
1863                         return '\0';
1864                 argptr++;
1865                 if (LONE_DASH(p)) /* "--" ? */
1866                         return '\0';
1867                 /* p => next "-param" */
1868         }
1869         /* p => some option char in the middle of a "-param" */
1870         c = *p++;
1871         for (q = optstring; *q != c;) {
1872                 if (*q == '\0')
1873                         ash_msg_and_raise_error("illegal option -%c", c);
1874                 if (*++q == ':')
1875                         q++;
1876         }
1877         if (*++q == ':') {
1878                 if (*p == '\0') {
1879                         p = *argptr++;
1880                         if (p == NULL)
1881                                 ash_msg_and_raise_error("no arg for -%c option", c);
1882                 }
1883                 optionarg = p;
1884                 p = NULL;
1885         }
1886         optptr = p;
1887         return c;
1888 }
1889
1890
1891 /* ============ Shell variables */
1892
1893 /*
1894  * The parsefile structure pointed to by the global variable parsefile
1895  * contains information about the current file being read.
1896  */
1897 struct shparam {
1898         int nparam;             /* # of positional parameters (without $0) */
1899 #if ENABLE_ASH_GETOPTS
1900         int optind;             /* next parameter to be processed by getopts */
1901         int optoff;             /* used by getopts */
1902 #endif
1903         unsigned char malloced; /* if parameter list dynamically allocated */
1904         char **p;               /* parameter list */
1905 };
1906
1907 /*
1908  * Free the list of positional parameters.
1909  */
1910 static void
1911 freeparam(volatile struct shparam *param)
1912 {
1913         if (param->malloced) {
1914                 char **ap, **ap1;
1915                 ap = ap1 = param->p;
1916                 while (*ap)
1917                         free(*ap++);
1918                 free(ap1);
1919         }
1920 }
1921
1922 #if ENABLE_ASH_GETOPTS
1923 static void FAST_FUNC getoptsreset(const char *value);
1924 #endif
1925
1926 struct var {
1927         struct var *next;               /* next entry in hash list */
1928         int flags;                      /* flags are defined above */
1929         const char *var_text;           /* name=value */
1930         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1931                                         /* the variable gets set/unset */
1932 };
1933
1934 struct localvar {
1935         struct localvar *next;          /* next local variable in list */
1936         struct var *vp;                 /* the variable that was made local */
1937         int flags;                      /* saved flags */
1938         const char *text;               /* saved text */
1939 };
1940
1941 /* flags */
1942 #define VEXPORT         0x01    /* variable is exported */
1943 #define VREADONLY       0x02    /* variable cannot be modified */
1944 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1945 #define VTEXTFIXED      0x08    /* text is statically allocated */
1946 #define VSTACK          0x10    /* text is allocated on the stack */
1947 #define VUNSET          0x20    /* the variable is not set */
1948 #define VNOFUNC         0x40    /* don't call the callback function */
1949 #define VNOSET          0x80    /* do not set variable - just readonly test */
1950 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1951 #if ENABLE_ASH_RANDOM_SUPPORT
1952 # define VDYNAMIC       0x200   /* dynamic variable */
1953 #else
1954 # define VDYNAMIC       0
1955 #endif
1956
1957
1958 /* Need to be before varinit_data[] */
1959 #if ENABLE_LOCALE_SUPPORT
1960 static void FAST_FUNC
1961 change_lc_all(const char *value)
1962 {
1963         if (value && *value != '\0')
1964                 setlocale(LC_ALL, value);
1965 }
1966 static void FAST_FUNC
1967 change_lc_ctype(const char *value)
1968 {
1969         if (value && *value != '\0')
1970                 setlocale(LC_CTYPE, value);
1971 }
1972 #endif
1973 #if ENABLE_ASH_MAIL
1974 static void chkmail(void);
1975 static void changemail(const char *var_value) FAST_FUNC;
1976 #else
1977 # define chkmail()  ((void)0)
1978 #endif
1979 static void changepath(const char *) FAST_FUNC;
1980 #if ENABLE_ASH_RANDOM_SUPPORT
1981 static void change_random(const char *) FAST_FUNC;
1982 #endif
1983
1984 static const struct {
1985         int flags;
1986         const char *var_text;
1987         void (*var_func)(const char *) FAST_FUNC;
1988 } varinit_data[] = {
1989         /*
1990          * Note: VEXPORT would not work correctly here for NOFORK applets:
1991          * some environment strings may be constant.
1992          */
1993         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
1994 #if ENABLE_ASH_MAIL
1995         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
1996         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
1997 #endif
1998         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
1999         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2000         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2001         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2002 #if ENABLE_ASH_GETOPTS
2003         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2004 #endif
2005 #if ENABLE_ASH_RANDOM_SUPPORT
2006         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2007 #endif
2008 #if ENABLE_LOCALE_SUPPORT
2009         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2010         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2011 #endif
2012 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2013         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2014 #endif
2015 };
2016
2017 struct redirtab;
2018
2019 struct globals_var {
2020         struct shparam shellparam;      /* $@ current positional parameters */
2021         struct redirtab *redirlist;
2022         int preverrout_fd;   /* save fd2 before print debug if xflag is set. */
2023         struct var *vartab[VTABSIZE];
2024         struct var varinit[ARRAY_SIZE(varinit_data)];
2025 };
2026 extern struct globals_var *const ash_ptr_to_globals_var;
2027 #define G_var (*ash_ptr_to_globals_var)
2028 #define shellparam    (G_var.shellparam   )
2029 //#define redirlist     (G_var.redirlist    )
2030 #define preverrout_fd (G_var.preverrout_fd)
2031 #define vartab        (G_var.vartab       )
2032 #define varinit       (G_var.varinit      )
2033 #define INIT_G_var() do { \
2034         unsigned i; \
2035         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2036         barrier(); \
2037         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2038                 varinit[i].flags    = varinit_data[i].flags; \
2039                 varinit[i].var_text = varinit_data[i].var_text; \
2040                 varinit[i].var_func = varinit_data[i].var_func; \
2041         } \
2042 } while (0)
2043
2044 #define vifs      varinit[0]
2045 #if ENABLE_ASH_MAIL
2046 # define vmail    (&vifs)[1]
2047 # define vmpath   (&vmail)[1]
2048 # define vpath    (&vmpath)[1]
2049 #else
2050 # define vpath    (&vifs)[1]
2051 #endif
2052 #define vps1      (&vpath)[1]
2053 #define vps2      (&vps1)[1]
2054 #define vps4      (&vps2)[1]
2055 #if ENABLE_ASH_GETOPTS
2056 # define voptind  (&vps4)[1]
2057 # if ENABLE_ASH_RANDOM_SUPPORT
2058 #  define vrandom (&voptind)[1]
2059 # endif
2060 #else
2061 # if ENABLE_ASH_RANDOM_SUPPORT
2062 #  define vrandom (&vps4)[1]
2063 # endif
2064 #endif
2065
2066 /*
2067  * The following macros access the values of the above variables.
2068  * They have to skip over the name.  They return the null string
2069  * for unset variables.
2070  */
2071 #define ifsval()        (vifs.var_text + 4)
2072 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2073 #if ENABLE_ASH_MAIL
2074 # define mailval()      (vmail.var_text + 5)
2075 # define mpathval()     (vmpath.var_text + 9)
2076 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2077 #endif
2078 #define pathval()       (vpath.var_text + 5)
2079 #define ps1val()        (vps1.var_text + 4)
2080 #define ps2val()        (vps2.var_text + 4)
2081 #define ps4val()        (vps4.var_text + 4)
2082 #if ENABLE_ASH_GETOPTS
2083 # define optindval()    (voptind.var_text + 7)
2084 #endif
2085
2086 #if ENABLE_ASH_GETOPTS
2087 static void FAST_FUNC
2088 getoptsreset(const char *value)
2089 {
2090         shellparam.optind = number(value) ?: 1;
2091         shellparam.optoff = -1;
2092 }
2093 #endif
2094
2095 /*
2096  * Compares two strings up to the first = or '\0'.  The first
2097  * string must be terminated by '='; the second may be terminated by
2098  * either '=' or '\0'.
2099  */
2100 static int
2101 varcmp(const char *p, const char *q)
2102 {
2103         int c, d;
2104
2105         while ((c = *p) == (d = *q)) {
2106                 if (c == '\0' || c == '=')
2107                         goto out;
2108                 p++;
2109                 q++;
2110         }
2111         if (c == '=')
2112                 c = '\0';
2113         if (d == '=')
2114                 d = '\0';
2115  out:
2116         return c - d;
2117 }
2118
2119 /*
2120  * Find the appropriate entry in the hash table from the name.
2121  */
2122 static struct var **
2123 hashvar(const char *p)
2124 {
2125         unsigned hashval;
2126
2127         hashval = ((unsigned char) *p) << 4;
2128         while (*p && *p != '=')
2129                 hashval += (unsigned char) *p++;
2130         return &vartab[hashval % VTABSIZE];
2131 }
2132
2133 static int
2134 vpcmp(const void *a, const void *b)
2135 {
2136         return varcmp(*(const char **)a, *(const char **)b);
2137 }
2138
2139 /*
2140  * This routine initializes the builtin variables.
2141  */
2142 static void
2143 initvar(void)
2144 {
2145         struct var *vp;
2146         struct var *end;
2147         struct var **vpp;
2148
2149         /*
2150          * PS1 depends on uid
2151          */
2152 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2153         vps1.var_text = "PS1=\\w \\$ ";
2154 #else
2155         if (!geteuid())
2156                 vps1.var_text = "PS1=# ";
2157 #endif
2158         vp = varinit;
2159         end = vp + ARRAY_SIZE(varinit);
2160         do {
2161                 vpp = hashvar(vp->var_text);
2162                 vp->next = *vpp;
2163                 *vpp = vp;
2164         } while (++vp < end);
2165 }
2166
2167 static struct var **
2168 findvar(struct var **vpp, const char *name)
2169 {
2170         for (; *vpp; vpp = &(*vpp)->next) {
2171                 if (varcmp((*vpp)->var_text, name) == 0) {
2172                         break;
2173                 }
2174         }
2175         return vpp;
2176 }
2177
2178 /*
2179  * Find the value of a variable.  Returns NULL if not set.
2180  */
2181 static const char* FAST_FUNC
2182 lookupvar(const char *name)
2183 {
2184         struct var *v;
2185
2186         v = *findvar(hashvar(name), name);
2187         if (v) {
2188 #if ENABLE_ASH_RANDOM_SUPPORT
2189         /*
2190          * Dynamic variables are implemented roughly the same way they are
2191          * in bash. Namely, they're "special" so long as they aren't unset.
2192          * As soon as they're unset, they're no longer dynamic, and dynamic
2193          * lookup will no longer happen at that point. -- PFM.
2194          */
2195                 if (v->flags & VDYNAMIC)
2196                         v->var_func(NULL);
2197 #endif
2198                 if (!(v->flags & VUNSET))
2199                         return var_end(v->var_text);
2200         }
2201         return NULL;
2202 }
2203
2204 #if ENABLE_UNICODE_SUPPORT
2205 static void
2206 reinit_unicode_for_ash(void)
2207 {
2208         /* Unicode support should be activated even if LANG is set
2209          * _during_ shell execution, not only if it was set when
2210          * shell was started. Therefore, re-check LANG every time:
2211          */
2212         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2213          || ENABLE_UNICODE_USING_LOCALE
2214         ) {
2215                 const char *s = lookupvar("LC_ALL");
2216                 if (!s) s = lookupvar("LC_CTYPE");
2217                 if (!s) s = lookupvar("LANG");
2218                 reinit_unicode(s);
2219         }
2220 }
2221 #else
2222 # define reinit_unicode_for_ash() ((void)0)
2223 #endif
2224
2225 /*
2226  * Search the environment of a builtin command.
2227  */
2228 static const char *
2229 bltinlookup(const char *name)
2230 {
2231         struct strlist *sp;
2232
2233         for (sp = cmdenviron; sp; sp = sp->next) {
2234                 if (varcmp(sp->text, name) == 0)
2235                         return var_end(sp->text);
2236         }
2237         return lookupvar(name);
2238 }
2239
2240 /*
2241  * Same as setvar except that the variable and value are passed in
2242  * the first argument as name=value.  Since the first argument will
2243  * be actually stored in the table, it should not be a string that
2244  * will go away.
2245  * Called with interrupts off.
2246  */
2247 static void
2248 setvareq(char *s, int flags)
2249 {
2250         struct var *vp, **vpp;
2251
2252         vpp = hashvar(s);
2253         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2254         vp = *findvar(vpp, s);
2255         if (vp) {
2256                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2257                         const char *n;
2258
2259                         if (flags & VNOSAVE)
2260                                 free(s);
2261                         n = vp->var_text;
2262                         exitstatus = 1;
2263                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2264                 }
2265
2266                 if (flags & VNOSET)
2267                         return;
2268
2269                 if (vp->var_func && !(flags & VNOFUNC))
2270                         vp->var_func(var_end(s));
2271
2272                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2273                         free((char*)vp->var_text);
2274
2275                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2276                         *vpp = vp->next;
2277                         free(vp);
2278  out_free:
2279                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2280                                 free(s);
2281                         return;
2282                 }
2283
2284                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2285         } else {
2286                 /* variable s is not found */
2287                 if (flags & VNOSET)
2288                         return;
2289                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2290                         goto out_free;
2291                 vp = ckzalloc(sizeof(*vp));
2292                 vp->next = *vpp;
2293                 /*vp->func = NULL; - ckzalloc did it */
2294                 *vpp = vp;
2295         }
2296         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2297                 s = ckstrdup(s);
2298         vp->var_text = s;
2299         vp->flags = flags;
2300 }
2301
2302 /*
2303  * Set the value of a variable.  The flags argument is ored with the
2304  * flags of the variable.  If val is NULL, the variable is unset.
2305  */
2306 static void
2307 setvar(const char *name, const char *val, int flags)
2308 {
2309         const char *q;
2310         char *p;
2311         char *nameeq;
2312         size_t namelen;
2313         size_t vallen;
2314
2315         q = endofname(name);
2316         p = strchrnul(q, '=');
2317         namelen = p - name;
2318         if (!namelen || p != q)
2319                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2320         vallen = 0;
2321         if (val == NULL) {
2322                 flags |= VUNSET;
2323         } else {
2324                 vallen = strlen(val);
2325         }
2326
2327         INT_OFF;
2328         nameeq = ckmalloc(namelen + vallen + 2);
2329         p = mempcpy(nameeq, name, namelen);
2330         if (val) {
2331                 *p++ = '=';
2332                 p = mempcpy(p, val, vallen);
2333         }
2334         *p = '\0';
2335         setvareq(nameeq, flags | VNOSAVE);
2336         INT_ON;
2337 }
2338
2339 static void FAST_FUNC
2340 setvar0(const char *name, const char *val)
2341 {
2342         setvar(name, val, 0);
2343 }
2344
2345 /*
2346  * Unset the specified variable.
2347  */
2348 static void
2349 unsetvar(const char *s)
2350 {
2351         setvar(s, NULL, 0);
2352 }
2353
2354 /*
2355  * Process a linked list of variable assignments.
2356  */
2357 static void
2358 listsetvar(struct strlist *list_set_var, int flags)
2359 {
2360         struct strlist *lp = list_set_var;
2361
2362         if (!lp)
2363                 return;
2364         INT_OFF;
2365         do {
2366                 setvareq(lp->text, flags);
2367                 lp = lp->next;
2368         } while (lp);
2369         INT_ON;
2370 }
2371
2372 /*
2373  * Generate a list of variables satisfying the given conditions.
2374  */
2375 static char **
2376 listvars(int on, int off, char ***end)
2377 {
2378         struct var **vpp;
2379         struct var *vp;
2380         char **ep;
2381         int mask;
2382
2383         STARTSTACKSTR(ep);
2384         vpp = vartab;
2385         mask = on | off;
2386         do {
2387                 for (vp = *vpp; vp; vp = vp->next) {
2388                         if ((vp->flags & mask) == on) {
2389                                 if (ep == stackstrend())
2390                                         ep = growstackstr();
2391                                 *ep++ = (char*)vp->var_text;
2392                         }
2393                 }
2394         } while (++vpp < vartab + VTABSIZE);
2395         if (ep == stackstrend())
2396                 ep = growstackstr();
2397         if (end)
2398                 *end = ep;
2399         *ep++ = NULL;
2400         return grabstackstr(ep);
2401 }
2402
2403
2404 /* ============ Path search helper
2405  *
2406  * The variable path (passed by reference) should be set to the start
2407  * of the path before the first call; path_advance will update
2408  * this value as it proceeds.  Successive calls to path_advance will return
2409  * the possible path expansions in sequence.  If an option (indicated by
2410  * a percent sign) appears in the path entry then the global variable
2411  * pathopt will be set to point to it; otherwise pathopt will be set to
2412  * NULL.
2413  */
2414 static const char *pathopt;     /* set by path_advance */
2415
2416 static char *
2417 path_advance(const char **path, const char *name)
2418 {
2419         const char *p;
2420         char *q;
2421         const char *start;
2422         size_t len;
2423
2424         if (*path == NULL)
2425                 return NULL;
2426         start = *path;
2427         for (p = start; *p && *p != ':' && *p != '%'; p++)
2428                 continue;
2429         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2430         while (stackblocksize() < len)
2431                 growstackblock();
2432         q = stackblock();
2433         if (p != start) {
2434                 q = mempcpy(q, start, p - start);
2435                 *q++ = '/';
2436         }
2437         strcpy(q, name);
2438         pathopt = NULL;
2439         if (*p == '%') {
2440                 pathopt = ++p;
2441                 while (*p && *p != ':')
2442                         p++;
2443         }
2444         if (*p == ':')
2445                 *path = p + 1;
2446         else
2447                 *path = NULL;
2448         return stalloc(len);
2449 }
2450
2451
2452 /* ============ Prompt */
2453
2454 static smallint doprompt;                   /* if set, prompt the user */
2455 static smallint needprompt;                 /* true if interactive and at start of line */
2456
2457 #if ENABLE_FEATURE_EDITING
2458 static line_input_t *line_input_state;
2459 static const char *cmdedit_prompt;
2460 static void
2461 putprompt(const char *s)
2462 {
2463         if (ENABLE_ASH_EXPAND_PRMT) {
2464                 free((char*)cmdedit_prompt);
2465                 cmdedit_prompt = ckstrdup(s);
2466                 return;
2467         }
2468         cmdedit_prompt = s;
2469 }
2470 #else
2471 static void
2472 putprompt(const char *s)
2473 {
2474         out2str(s);
2475 }
2476 #endif
2477
2478 /* expandstr() needs parsing machinery, so it is far away ahead... */
2479 static const char *expandstr(const char *ps);
2480
2481 static void
2482 setprompt_if(smallint do_set, int whichprompt)
2483 {
2484         const char *prompt;
2485         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2486
2487         if (!do_set)
2488                 return;
2489
2490         needprompt = 0;
2491
2492         switch (whichprompt) {
2493         case 1:
2494                 prompt = ps1val();
2495                 break;
2496         case 2:
2497                 prompt = ps2val();
2498                 break;
2499         default:                        /* 0 */
2500                 prompt = nullstr;
2501         }
2502 #if ENABLE_ASH_EXPAND_PRMT
2503         pushstackmark(&smark, stackblocksize());
2504         putprompt(expandstr(prompt));
2505         popstackmark(&smark);
2506 #else
2507         putprompt(prompt);
2508 #endif
2509 }
2510
2511
2512 /* ============ The cd and pwd commands */
2513
2514 #define CD_PHYSICAL 1
2515 #define CD_PRINT 2
2516
2517 static int
2518 cdopt(void)
2519 {
2520         int flags = 0;
2521         int i, j;
2522
2523         j = 'L';
2524         while ((i = nextopt("LP")) != '\0') {
2525                 if (i != j) {
2526                         flags ^= CD_PHYSICAL;
2527                         j = i;
2528                 }
2529         }
2530
2531         return flags;
2532 }
2533
2534 /*
2535  * Update curdir (the name of the current directory) in response to a
2536  * cd command.
2537  */
2538 static const char *
2539 updatepwd(const char *dir)
2540 {
2541         char *new;
2542         char *p;
2543         char *cdcomppath;
2544         const char *lim;
2545
2546         cdcomppath = sstrdup(dir);
2547         STARTSTACKSTR(new);
2548         if (*dir != '/') {
2549                 if (curdir == nullstr)
2550                         return 0;
2551                 new = stack_putstr(curdir, new);
2552         }
2553         new = makestrspace(strlen(dir) + 2, new);
2554         lim = (char *)stackblock() + 1;
2555         if (*dir != '/') {
2556                 if (new[-1] != '/')
2557                         USTPUTC('/', new);
2558                 if (new > lim && *lim == '/')
2559                         lim++;
2560         } else {
2561                 USTPUTC('/', new);
2562                 cdcomppath++;
2563                 if (dir[1] == '/' && dir[2] != '/') {
2564                         USTPUTC('/', new);
2565                         cdcomppath++;
2566                         lim++;
2567                 }
2568         }
2569         p = strtok(cdcomppath, "/");
2570         while (p) {
2571                 switch (*p) {
2572                 case '.':
2573                         if (p[1] == '.' && p[2] == '\0') {
2574                                 while (new > lim) {
2575                                         STUNPUTC(new);
2576                                         if (new[-1] == '/')
2577                                                 break;
2578                                 }
2579                                 break;
2580                         }
2581                         if (p[1] == '\0')
2582                                 break;
2583                         /* fall through */
2584                 default:
2585                         new = stack_putstr(p, new);
2586                         USTPUTC('/', new);
2587                 }
2588                 p = strtok(NULL, "/");
2589         }
2590         if (new > lim)
2591                 STUNPUTC(new);
2592         *new = 0;
2593         return stackblock();
2594 }
2595
2596 /*
2597  * Find out what the current directory is. If we already know the current
2598  * directory, this routine returns immediately.
2599  */
2600 static char *
2601 getpwd(void)
2602 {
2603         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2604         return dir ? dir : nullstr;
2605 }
2606
2607 static void
2608 setpwd(const char *val, int setold)
2609 {
2610         char *oldcur, *dir;
2611
2612         oldcur = dir = curdir;
2613
2614         if (setold) {
2615                 setvar("OLDPWD", oldcur, VEXPORT);
2616         }
2617         INT_OFF;
2618         if (physdir != nullstr) {
2619                 if (physdir != oldcur)
2620                         free(physdir);
2621                 physdir = nullstr;
2622         }
2623         if (oldcur == val || !val) {
2624                 char *s = getpwd();
2625                 physdir = s;
2626                 if (!val)
2627                         dir = s;
2628         } else
2629                 dir = ckstrdup(val);
2630         if (oldcur != dir && oldcur != nullstr) {
2631                 free(oldcur);
2632         }
2633         curdir = dir;
2634         INT_ON;
2635         setvar("PWD", dir, VEXPORT);
2636 }
2637
2638 static void hashcd(void);
2639
2640 /*
2641  * Actually do the chdir.  We also call hashcd to let other routines
2642  * know that the current directory has changed.
2643  */
2644 static int
2645 docd(const char *dest, int flags)
2646 {
2647         const char *dir = NULL;
2648         int err;
2649
2650         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2651
2652         INT_OFF;
2653         if (!(flags & CD_PHYSICAL)) {
2654                 dir = updatepwd(dest);
2655                 if (dir)
2656                         dest = dir;
2657         }
2658         err = chdir(dest);
2659         if (err)
2660                 goto out;
2661         setpwd(dir, 1);
2662         hashcd();
2663  out:
2664         INT_ON;
2665         return err;
2666 }
2667
2668 static int FAST_FUNC
2669 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2670 {
2671         const char *dest;
2672         const char *path;
2673         const char *p;
2674         char c;
2675         struct stat statb;
2676         int flags;
2677
2678         flags = cdopt();
2679         dest = *argptr;
2680         if (!dest)
2681                 dest = bltinlookup("HOME");
2682         else if (LONE_DASH(dest)) {
2683                 dest = bltinlookup("OLDPWD");
2684                 flags |= CD_PRINT;
2685         }
2686         if (!dest)
2687                 dest = nullstr;
2688         if (*dest == '/')
2689                 goto step6;
2690         if (*dest == '.') {
2691                 c = dest[1];
2692  dotdot:
2693                 switch (c) {
2694                 case '\0':
2695                 case '/':
2696                         goto step6;
2697                 case '.':
2698                         c = dest[2];
2699                         if (c != '.')
2700                                 goto dotdot;
2701                 }
2702         }
2703         if (!*dest)
2704                 dest = ".";
2705         path = bltinlookup("CDPATH");
2706         while (path) {
2707                 c = *path;
2708                 p = path_advance(&path, dest);
2709                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2710                         if (c && c != ':')
2711                                 flags |= CD_PRINT;
2712  docd:
2713                         if (!docd(p, flags))
2714                                 goto out;
2715                         goto err;
2716                 }
2717         }
2718
2719  step6:
2720         p = dest;
2721         goto docd;
2722
2723  err:
2724         ash_msg_and_raise_error("can't cd to %s", dest);
2725         /* NOTREACHED */
2726  out:
2727         if (flags & CD_PRINT)
2728                 out1fmt("%s\n", curdir);
2729         return 0;
2730 }
2731
2732 static int FAST_FUNC
2733 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2734 {
2735         int flags;
2736         const char *dir = curdir;
2737
2738         flags = cdopt();
2739         if (flags) {
2740                 if (physdir == nullstr)
2741                         setpwd(dir, 0);
2742                 dir = physdir;
2743         }
2744         out1fmt("%s\n", dir);
2745         return 0;
2746 }
2747
2748
2749 /* ============ ... */
2750
2751
2752 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2753
2754 /* Syntax classes */
2755 #define CWORD     0             /* character is nothing special */
2756 #define CNL       1             /* newline character */
2757 #define CBACK     2             /* a backslash character */
2758 #define CSQUOTE   3             /* single quote */
2759 #define CDQUOTE   4             /* double quote */
2760 #define CENDQUOTE 5             /* a terminating quote */
2761 #define CBQUOTE   6             /* backwards single quote */
2762 #define CVAR      7             /* a dollar sign */
2763 #define CENDVAR   8             /* a '}' character */
2764 #define CLP       9             /* a left paren in arithmetic */
2765 #define CRP      10             /* a right paren in arithmetic */
2766 #define CENDFILE 11             /* end of file */
2767 #define CCTL     12             /* like CWORD, except it must be escaped */
2768 #define CSPCL    13             /* these terminate a word */
2769 #define CIGN     14             /* character should be ignored */
2770
2771 #define PEOF     256
2772 #if ENABLE_ASH_ALIAS
2773 # define PEOA    257
2774 #endif
2775
2776 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2777
2778 #if ENABLE_FEATURE_SH_MATH
2779 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2780 #else
2781 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2782 #endif
2783 static const uint16_t S_I_T[] ALIGN2 = {
2784 #if ENABLE_ASH_ALIAS
2785         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2786 #endif
2787         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2788         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2789         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2790         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2791         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2792         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2793         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2794         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2795         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2796         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2797         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2798 #if !USE_SIT_FUNCTION
2799         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2800         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2801         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2802 #endif
2803 #undef SIT_ITEM
2804 };
2805 /* Constants below must match table above */
2806 enum {
2807 #if ENABLE_ASH_ALIAS
2808         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2809 #endif
2810         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2811         CNL_CNL_CNL_CNL                    , /*  2 */
2812         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2813         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2814         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2815         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2816         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2817         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2818         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2819         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2820         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2821         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2822         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2823         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2824 };
2825
2826 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2827  * caller must ensure proper cast on it if c is *char_ptr!
2828  */
2829 /* Values for syntax param */
2830 #define BASESYNTAX 0    /* not in quotes */
2831 #define DQSYNTAX   1    /* in double quotes */
2832 #define SQSYNTAX   2    /* in single quotes */
2833 #define ARISYNTAX  3    /* in arithmetic */
2834 #define PSSYNTAX   4    /* prompt. never passed to SIT() */
2835
2836 #if USE_SIT_FUNCTION
2837
2838 static int
2839 SIT(int c, int syntax)
2840 {
2841         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2842         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2843         /*
2844          * This causes '/' to be prepended with CTLESC in dquoted string,
2845          * making "./file"* treated incorrectly because we feed
2846          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2847          * The "homegrown" glob implementation is okay with that,
2848          * but glibc one isn't. With '/' always treated as CWORD,
2849          * both work fine.
2850          */
2851 # if ENABLE_ASH_ALIAS
2852         static const uint8_t syntax_index_table[] ALIGN1 = {
2853                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2854                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2855                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2856                 11, 3                           /* "}~" */
2857         };
2858 # else
2859         static const uint8_t syntax_index_table[] ALIGN1 = {
2860                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2861                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2862                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2863                 10, 2                           /* "}~" */
2864         };
2865 # endif
2866         const char *s;
2867         int indx;
2868
2869         if (c == PEOF)
2870                 return CENDFILE;
2871 # if ENABLE_ASH_ALIAS
2872         if (c == PEOA)
2873                 indx = 0;
2874         else
2875 # endif
2876         {
2877                 /* Cast is purely for paranoia here,
2878                  * just in case someone passed signed char to us */
2879                 if ((unsigned char)c >= CTL_FIRST
2880                  && (unsigned char)c <= CTL_LAST
2881                 ) {
2882                         return CCTL;
2883                 }
2884                 s = strchrnul(spec_symbls, c);
2885                 if (*s == '\0')
2886                         return CWORD;
2887                 indx = syntax_index_table[s - spec_symbls];
2888         }
2889         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2890 }
2891
2892 #else   /* !USE_SIT_FUNCTION */
2893
2894 static const uint8_t syntax_index_table[] ALIGN1 = {
2895         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2896         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2897         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2898         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2899         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2900         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2901         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2902         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2903         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2904         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2905         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2906         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2907         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2908         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2909         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2910         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2911         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2912         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2913         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2914         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2915         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2916         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2917         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2918         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2919         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2920         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2921         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2922         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2923         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2924         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2925         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2926         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2927         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2928         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2929         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2930         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2931         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2932         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2933         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2934         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2935         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2936         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2937         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2938         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2939         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2940         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2941         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2942         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2943 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2944         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2945         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2946         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2947         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2948         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2949         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2950         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2951         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2952         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2953         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2954         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2955         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2956         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2957         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2958         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2959         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2960         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2961         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2962         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2963         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2964         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2965         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2966         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2967         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2968         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2969         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2970         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2971         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2972         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2973         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2974         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2975         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2976         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2977         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2978         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2979         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
2980         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
2981         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
2982         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
2983         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
2984         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
2985         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
2986         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
2987         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
2988         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
2989         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
2990         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
2991         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
2992         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
2993         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2994         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
2995         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
2996         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
2997         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
2998         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
2999         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3000         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3001         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3002         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3003         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3004         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3005         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3006         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3007         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3008         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3009         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3010         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3011         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3012         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3013         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3014         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3015         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3016         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3017         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3018         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3019         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3020         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3021         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3022         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3023         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3024         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3025         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3026         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3027         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3028         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3029         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3030         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3031         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3032         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3033         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3034         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3035         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3036         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3037         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3038         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3039         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3040         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3041         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3042         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3043         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3044         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3045         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3046         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3047         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3048         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3049         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3050         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3051         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3052         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3053         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3054         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3150         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3151         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3152         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3153         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3154 # if ENABLE_ASH_ALIAS
3155         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3156 # endif
3157 };
3158
3159 #if 1
3160 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3161 #else /* debug version, caught one signed char bug */
3162 # define SIT(c, syntax) \
3163         ({ \
3164                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3165                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3166                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3167                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3168                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3169         })
3170 #endif
3171
3172 #endif  /* !USE_SIT_FUNCTION */
3173
3174
3175 /* ============ Alias handling */
3176
3177 #if ENABLE_ASH_ALIAS
3178
3179 #define ALIASINUSE 1
3180 #define ALIASDEAD  2
3181
3182 struct alias {
3183         struct alias *next;
3184         char *name;
3185         char *val;
3186         int flag;
3187 };
3188
3189
3190 static struct alias **atab; // [ATABSIZE];
3191 #define INIT_G_alias() do { \
3192         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3193 } while (0)
3194
3195
3196 static struct alias **
3197 __lookupalias(const char *name)
3198 {
3199         unsigned int hashval;
3200         struct alias **app;
3201         const char *p;
3202         unsigned int ch;
3203
3204         p = name;
3205
3206         ch = (unsigned char)*p;
3207         hashval = ch << 4;
3208         while (ch) {
3209                 hashval += ch;
3210                 ch = (unsigned char)*++p;
3211         }
3212         app = &atab[hashval % ATABSIZE];
3213
3214         for (; *app; app = &(*app)->next) {
3215                 if (strcmp(name, (*app)->name) == 0) {
3216                         break;
3217                 }
3218         }
3219
3220         return app;
3221 }
3222
3223 static struct alias *
3224 lookupalias(const char *name, int check)
3225 {
3226         struct alias *ap = *__lookupalias(name);
3227
3228         if (check && ap && (ap->flag & ALIASINUSE))
3229                 return NULL;
3230         return ap;
3231 }
3232
3233 static struct alias *
3234 freealias(struct alias *ap)
3235 {
3236         struct alias *next;
3237
3238         if (ap->flag & ALIASINUSE) {
3239                 ap->flag |= ALIASDEAD;
3240                 return ap;
3241         }
3242
3243         next = ap->next;
3244         free(ap->name);
3245         free(ap->val);
3246         free(ap);
3247         return next;
3248 }
3249
3250 static void
3251 setalias(const char *name, const char *val)
3252 {
3253         struct alias *ap, **app;
3254
3255         app = __lookupalias(name);
3256         ap = *app;
3257         INT_OFF;
3258         if (ap) {
3259                 if (!(ap->flag & ALIASINUSE)) {
3260                         free(ap->val);
3261                 }
3262                 ap->val = ckstrdup(val);
3263                 ap->flag &= ~ALIASDEAD;
3264         } else {
3265                 /* not found */
3266                 ap = ckzalloc(sizeof(struct alias));
3267                 ap->name = ckstrdup(name);
3268                 ap->val = ckstrdup(val);
3269                 /*ap->flag = 0; - ckzalloc did it */
3270                 /*ap->next = NULL;*/
3271                 *app = ap;
3272         }
3273         INT_ON;
3274 }
3275
3276 static int
3277 unalias(const char *name)
3278 {
3279         struct alias **app;
3280
3281         app = __lookupalias(name);
3282
3283         if (*app) {
3284                 INT_OFF;
3285                 *app = freealias(*app);
3286                 INT_ON;
3287                 return 0;
3288         }
3289
3290         return 1;
3291 }
3292
3293 static void
3294 rmaliases(void)
3295 {
3296         struct alias *ap, **app;
3297         int i;
3298
3299         INT_OFF;
3300         for (i = 0; i < ATABSIZE; i++) {
3301                 app = &atab[i];
3302                 for (ap = *app; ap; ap = *app) {
3303                         *app = freealias(*app);
3304                         if (ap == *app) {
3305                                 app = &ap->next;
3306                         }
3307                 }
3308         }
3309         INT_ON;
3310 }
3311
3312 static void
3313 printalias(const struct alias *ap)
3314 {
3315         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3316 }
3317
3318 /*
3319  * TODO - sort output
3320  */
3321 static int FAST_FUNC
3322 aliascmd(int argc UNUSED_PARAM, char **argv)
3323 {
3324         char *n, *v;
3325         int ret = 0;
3326         struct alias *ap;
3327
3328         if (!argv[1]) {
3329                 int i;
3330
3331                 for (i = 0; i < ATABSIZE; i++) {
3332                         for (ap = atab[i]; ap; ap = ap->next) {
3333                                 printalias(ap);
3334                         }
3335                 }
3336                 return 0;
3337         }
3338         while ((n = *++argv) != NULL) {
3339                 v = strchr(n+1, '=');
3340                 if (v == NULL) { /* n+1: funny ksh stuff */
3341                         ap = *__lookupalias(n);
3342                         if (ap == NULL) {
3343                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3344                                 ret = 1;
3345                         } else
3346                                 printalias(ap);
3347                 } else {
3348                         *v++ = '\0';
3349                         setalias(n, v);
3350                 }
3351         }
3352
3353         return ret;
3354 }
3355
3356 static int FAST_FUNC
3357 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3358 {
3359         int i;
3360
3361         while (nextopt("a") != '\0') {
3362                 rmaliases();
3363                 return 0;
3364         }
3365         for (i = 0; *argptr; argptr++) {
3366                 if (unalias(*argptr)) {
3367                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3368                         i = 1;
3369                 }
3370         }
3371
3372         return i;
3373 }
3374
3375 #endif /* ASH_ALIAS */
3376
3377
3378 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3379 #define FORK_FG    0
3380 #define FORK_BG    1
3381 #define FORK_NOJOB 2
3382
3383 /* mode flags for showjob(s) */
3384 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3385 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3386 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3387 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3388
3389 /*
3390  * A job structure contains information about a job.  A job is either a
3391  * single process or a set of processes contained in a pipeline.  In the
3392  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3393  * array of pids.
3394  */
3395 struct procstat {
3396         pid_t   ps_pid;         /* process id */
3397         int     ps_status;      /* last process status from wait() */
3398         char    *ps_cmd;        /* text of command being run */
3399 };
3400
3401 struct job {
3402         struct procstat ps0;    /* status of process */
3403         struct procstat *ps;    /* status or processes when more than one */
3404 #if JOBS
3405         int stopstatus;         /* status of a stopped job */
3406 #endif
3407         unsigned nprocs;        /* number of processes */
3408
3409 #define JOBRUNNING      0       /* at least one proc running */
3410 #define JOBSTOPPED      1       /* all procs are stopped */
3411 #define JOBDONE         2       /* all procs are completed */
3412         unsigned
3413                 state: 8,
3414 #if JOBS
3415                 sigint: 1,      /* job was killed by SIGINT */
3416                 jobctl: 1,      /* job running under job control */
3417 #endif
3418                 waited: 1,      /* true if this entry has been waited for */
3419                 used: 1,        /* true if this entry is in used */
3420                 changed: 1;     /* true if status has changed */
3421         struct job *prev_job;   /* previous job */
3422 };
3423
3424 static struct job *makejob(/*union node *,*/ int);
3425 static int forkshell(struct job *, union node *, int);
3426 static int waitforjob(struct job *);
3427
3428 #if !JOBS
3429 enum { doing_jobctl = 0 };
3430 #define setjobctl(on) do {} while (0)
3431 #else
3432 static smallint doing_jobctl; //references:8
3433 static void setjobctl(int);
3434 #endif
3435
3436 /*
3437  * Ignore a signal.
3438  */
3439 static void
3440 ignoresig(int signo)
3441 {
3442         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3443         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3444                 /* No, need to do it */
3445                 signal(signo, SIG_IGN);
3446         }
3447         sigmode[signo - 1] = S_HARD_IGN;
3448 }
3449
3450 /*
3451  * Only one usage site - in setsignal()
3452  */
3453 static void
3454 signal_handler(int signo)
3455 {
3456         if (signo == SIGCHLD) {
3457                 got_sigchld = 1;
3458                 if (!trap[SIGCHLD])
3459                         return;
3460         }
3461
3462         gotsig[signo - 1] = 1;
3463         pending_sig = signo;
3464
3465         if (signo == SIGINT && !trap[SIGINT]) {
3466                 if (!suppress_int) {
3467                         pending_sig = 0;
3468                         raise_interrupt(); /* does not return */
3469                 }
3470                 pending_int = 1;
3471         }
3472 }
3473
3474 /*
3475  * Set the signal handler for the specified signal.  The routine figures
3476  * out what it should be set to.
3477  */
3478 static void
3479 setsignal(int signo)
3480 {
3481         char *t;
3482         char cur_act, new_act;
3483         struct sigaction act;
3484
3485         t = trap[signo];
3486         new_act = S_DFL;
3487         if (t != NULL) { /* trap for this sig is set */
3488                 new_act = S_CATCH;
3489                 if (t[0] == '\0') /* trap is "": ignore this sig */
3490                         new_act = S_IGN;
3491         }
3492
3493         if (rootshell && new_act == S_DFL) {
3494                 switch (signo) {
3495                 case SIGINT:
3496                         if (iflag || minusc || sflag == 0)
3497                                 new_act = S_CATCH;
3498                         break;
3499                 case SIGQUIT:
3500 #if DEBUG
3501                         if (debug)
3502                                 break;
3503 #endif
3504                         /* man bash:
3505                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3506                          * commands run by bash have signal handlers
3507                          * set to the values inherited by the shell
3508                          * from its parent". */
3509                         new_act = S_IGN;
3510                         break;
3511                 case SIGTERM:
3512                         if (iflag)
3513                                 new_act = S_IGN;
3514                         break;
3515 #if JOBS
3516                 case SIGTSTP:
3517                 case SIGTTOU:
3518                         if (mflag)
3519                                 new_act = S_IGN;
3520                         break;
3521 #endif
3522                 }
3523         }
3524 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3525 //whereas we have to restore it to what shell got on entry
3526 //from the parent. See comment above
3527
3528         if (signo == SIGCHLD)
3529                 new_act = S_CATCH;
3530
3531         t = &sigmode[signo - 1];
3532         cur_act = *t;
3533         if (cur_act == 0) {
3534                 /* current setting is not yet known */
3535                 if (sigaction(signo, NULL, &act)) {
3536                         /* pretend it worked; maybe we should give a warning,
3537                          * but other shells don't. We don't alter sigmode,
3538                          * so we retry every time.
3539                          * btw, in Linux it never fails. --vda */
3540                         return;
3541                 }
3542                 if (act.sa_handler == SIG_IGN) {
3543                         cur_act = S_HARD_IGN;
3544                         if (mflag
3545                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3546                         ) {
3547                                 cur_act = S_IGN;   /* don't hard ignore these */
3548                         }
3549                 }
3550         }
3551         if (cur_act == S_HARD_IGN || cur_act == new_act)
3552                 return;
3553
3554         act.sa_handler = SIG_DFL;
3555         switch (new_act) {
3556         case S_CATCH:
3557                 act.sa_handler = signal_handler;
3558                 break;
3559         case S_IGN:
3560                 act.sa_handler = SIG_IGN;
3561                 break;
3562         }
3563
3564         /* flags and mask matter only if !DFL and !IGN, but we do it
3565          * for all cases for more deterministic behavior:
3566          */
3567         act.sa_flags = 0;
3568         sigfillset(&act.sa_mask);
3569
3570         sigaction_set(signo, &act);
3571
3572         *t = new_act;
3573 }
3574
3575 /* mode flags for set_curjob */
3576 #define CUR_DELETE 2
3577 #define CUR_RUNNING 1
3578 #define CUR_STOPPED 0
3579
3580 #if JOBS
3581 /* pgrp of shell on invocation */
3582 static int initialpgrp; //references:2
3583 static int ttyfd = -1; //5
3584 #endif
3585 /* array of jobs */
3586 static struct job *jobtab; //5
3587 /* size of array */
3588 static unsigned njobs; //4
3589 /* current job */
3590 static struct job *curjob; //lots
3591 /* number of presumed living untracked jobs */
3592 static int jobless; //4
3593
3594 #if 0
3595 /* Bash has a feature: it restores termios after a successful wait for
3596  * a foreground job which had at least one stopped or sigkilled member.
3597  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3598  * properly restoring tty state. Should we do this too?
3599  * A reproducer: ^Z an interactive python:
3600  *
3601  * # python
3602  * Python 2.7.12 (...)
3603  * >>> ^Z
3604  *      { python leaves tty in -icanon -echo state. We do survive that... }
3605  *  [1]+  Stopped                    python
3606  *      { ...however, next program (python #2) does not survive it well: }
3607  * # python
3608  * Python 2.7.12 (...)
3609  * >>> Traceback (most recent call last):
3610  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3611  *   File "<stdin>", line 1, in <module>
3612  * NameError: name 'qwerty' is not defined
3613  *
3614  * The implementation below is modeled on bash code and seems to work.
3615  * However, I'm not sure we should do this. For one: what if I'd fg
3616  * the stopped python instead? It'll be confused by "restored" tty state.
3617  */
3618 static struct termios shell_tty_info;
3619 static void
3620 get_tty_state(void)
3621 {
3622         if (rootshell && ttyfd >= 0)
3623                 tcgetattr(ttyfd, &shell_tty_info);
3624 }
3625 static void
3626 set_tty_state(void)
3627 {
3628         /* if (rootshell) - caller ensures this */
3629         if (ttyfd >= 0)
3630                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3631 }
3632 static int
3633 job_signal_status(struct job *jp)
3634 {
3635         int status;
3636         unsigned i;
3637         struct procstat *ps = jp->ps;
3638         for (i = 0; i < jp->nprocs; i++) {
3639                 status = ps[i].ps_status;
3640                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3641                         return status;
3642         }
3643         return 0;
3644 }
3645 static void
3646 restore_tty_if_stopped_or_signaled(struct job *jp)
3647 {
3648 //TODO: check what happens if we come from waitforjob() in expbackq()
3649         if (rootshell) {
3650                 int s = job_signal_status(jp);
3651                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3652                         set_tty_state();
3653         }
3654 }
3655 #else
3656 # define get_tty_state() ((void)0)
3657 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3658 #endif
3659
3660 static void
3661 set_curjob(struct job *jp, unsigned mode)
3662 {
3663         struct job *jp1;
3664         struct job **jpp, **curp;
3665
3666         /* first remove from list */
3667         jpp = curp = &curjob;
3668         while (1) {
3669                 jp1 = *jpp;
3670                 if (jp1 == jp)
3671                         break;
3672                 jpp = &jp1->prev_job;
3673         }
3674         *jpp = jp1->prev_job;
3675
3676         /* Then re-insert in correct position */
3677         jpp = curp;
3678         switch (mode) {
3679         default:
3680 #if DEBUG
3681                 abort();
3682 #endif
3683         case CUR_DELETE:
3684                 /* job being deleted */
3685                 break;
3686         case CUR_RUNNING:
3687                 /* newly created job or backgrounded job,
3688                  * put after all stopped jobs.
3689                  */
3690                 while (1) {
3691                         jp1 = *jpp;
3692 #if JOBS
3693                         if (!jp1 || jp1->state != JOBSTOPPED)
3694 #endif
3695                                 break;
3696                         jpp = &jp1->prev_job;
3697                 }
3698                 /* FALLTHROUGH */
3699 #if JOBS
3700         case CUR_STOPPED:
3701 #endif
3702                 /* newly stopped job - becomes curjob */
3703                 jp->prev_job = *jpp;
3704                 *jpp = jp;
3705                 break;
3706         }
3707 }
3708
3709 #if JOBS || DEBUG
3710 static int
3711 jobno(const struct job *jp)
3712 {
3713         return jp - jobtab + 1;
3714 }
3715 #endif
3716
3717 /*
3718  * Convert a job name to a job structure.
3719  */
3720 #if !JOBS
3721 #define getjob(name, getctl) getjob(name)
3722 #endif
3723 static struct job *
3724 getjob(const char *name, int getctl)
3725 {
3726         struct job *jp;
3727         struct job *found;
3728         const char *err_msg = "%s: no such job";
3729         unsigned num;
3730         int c;
3731         const char *p;
3732         char *(*match)(const char *, const char *);
3733
3734         jp = curjob;
3735         p = name;
3736         if (!p)
3737                 goto currentjob;
3738
3739         if (*p != '%')
3740                 goto err;
3741
3742         c = *++p;
3743         if (!c)
3744                 goto currentjob;
3745
3746         if (!p[1]) {
3747                 if (c == '+' || c == '%') {
3748  currentjob:
3749                         err_msg = "No current job";
3750                         goto check;
3751                 }
3752                 if (c == '-') {
3753                         if (jp)
3754                                 jp = jp->prev_job;
3755                         err_msg = "No previous job";
3756  check:
3757                         if (!jp)
3758                                 goto err;
3759                         goto gotit;
3760                 }
3761         }
3762
3763         if (is_number(p)) {
3764                 num = atoi(p);
3765                 if (num > 0 && num <= njobs) {
3766                         jp = jobtab + num - 1;
3767                         if (jp->used)
3768                                 goto gotit;
3769                         goto err;
3770                 }
3771         }
3772
3773         match = prefix;
3774         if (*p == '?') {
3775                 match = strstr;
3776                 p++;
3777         }
3778
3779         found = NULL;
3780         while (jp) {
3781                 if (match(jp->ps[0].ps_cmd, p)) {
3782                         if (found)
3783                                 goto err;
3784                         found = jp;
3785                         err_msg = "%s: ambiguous";
3786                 }
3787                 jp = jp->prev_job;
3788         }
3789         if (!found)
3790                 goto err;
3791         jp = found;
3792
3793  gotit:
3794 #if JOBS
3795         err_msg = "job %s not created under job control";
3796         if (getctl && jp->jobctl == 0)
3797                 goto err;
3798 #endif
3799         return jp;
3800  err:
3801         ash_msg_and_raise_error(err_msg, name);
3802 }
3803
3804 /*
3805  * Mark a job structure as unused.
3806  */
3807 static void
3808 freejob(struct job *jp)
3809 {
3810         struct procstat *ps;
3811         int i;
3812
3813         INT_OFF;
3814         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3815                 if (ps->ps_cmd != nullstr)
3816                         free(ps->ps_cmd);
3817         }
3818         if (jp->ps != &jp->ps0)
3819                 free(jp->ps);
3820         jp->used = 0;
3821         set_curjob(jp, CUR_DELETE);
3822         INT_ON;
3823 }
3824
3825 #if JOBS
3826 static void
3827 xtcsetpgrp(int fd, pid_t pgrp)
3828 {
3829         if (tcsetpgrp(fd, pgrp))
3830                 ash_msg_and_raise_error("can't set tty process group (%m)");
3831 }
3832
3833 /*
3834  * Turn job control on and off.
3835  *
3836  * Note:  This code assumes that the third arg to ioctl is a character
3837  * pointer, which is true on Berkeley systems but not System V.  Since
3838  * System V doesn't have job control yet, this isn't a problem now.
3839  *
3840  * Called with interrupts off.
3841  */
3842 static void
3843 setjobctl(int on)
3844 {
3845         int fd;
3846         int pgrp;
3847
3848         if (on == doing_jobctl || rootshell == 0)
3849                 return;
3850         if (on) {
3851                 int ofd;
3852                 ofd = fd = open(_PATH_TTY, O_RDWR);
3853                 if (fd < 0) {
3854         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3855          * That sometimes helps to acquire controlling tty.
3856          * Obviously, a workaround for bugs when someone
3857          * failed to provide a controlling tty to bash! :) */
3858                         fd = 2;
3859                         while (!isatty(fd))
3860                                 if (--fd < 0)
3861                                         goto out;
3862                 }
3863                 /* fd is a tty at this point */
3864                 fd = fcntl(fd, F_DUPFD, 10);
3865                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3866                         close(ofd);
3867                 if (fd < 0)
3868                         goto out; /* F_DUPFD failed */
3869                 close_on_exec_on(fd);
3870                 while (1) { /* while we are in the background */
3871                         pgrp = tcgetpgrp(fd);
3872                         if (pgrp < 0) {
3873  out:
3874                                 ash_msg("can't access tty; job control turned off");
3875                                 mflag = on = 0;
3876                                 goto close;
3877                         }
3878                         if (pgrp == getpgrp())
3879                                 break;
3880                         killpg(0, SIGTTIN);
3881                 }
3882                 initialpgrp = pgrp;
3883
3884                 setsignal(SIGTSTP);
3885                 setsignal(SIGTTOU);
3886                 setsignal(SIGTTIN);
3887                 pgrp = rootpid;
3888                 setpgid(0, pgrp);
3889                 xtcsetpgrp(fd, pgrp);
3890         } else {
3891                 /* turning job control off */
3892                 fd = ttyfd;
3893                 pgrp = initialpgrp;
3894                 /* was xtcsetpgrp, but this can make exiting ash
3895                  * loop forever if pty is already deleted */
3896                 tcsetpgrp(fd, pgrp);
3897                 setpgid(0, pgrp);
3898                 setsignal(SIGTSTP);
3899                 setsignal(SIGTTOU);
3900                 setsignal(SIGTTIN);
3901  close:
3902                 if (fd >= 0)
3903                         close(fd);
3904                 fd = -1;
3905         }
3906         ttyfd = fd;
3907         doing_jobctl = on;
3908 }
3909
3910 static int FAST_FUNC
3911 killcmd(int argc, char **argv)
3912 {
3913         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3914                 int i = 1;
3915                 do {
3916                         if (argv[i][0] == '%') {
3917                                 /*
3918                                  * "kill %N" - job kill
3919                                  * Converting to pgrp / pid kill
3920                                  */
3921                                 struct job *jp;
3922                                 char *dst;
3923                                 int j, n;
3924
3925                                 jp = getjob(argv[i], 0);
3926                                 /*
3927                                  * In jobs started under job control, we signal
3928                                  * entire process group by kill -PGRP_ID.
3929                                  * This happens, f.e., in interactive shell.
3930                                  *
3931                                  * Otherwise, we signal each child via
3932                                  * kill PID1 PID2 PID3.
3933                                  * Testcases:
3934                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3935                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3936                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3937                                  */
3938                                 n = jp->nprocs; /* can't be 0 (I hope) */
3939                                 if (jp->jobctl)
3940                                         n = 1;
3941                                 dst = alloca(n * sizeof(int)*4);
3942                                 argv[i] = dst;
3943                                 for (j = 0; j < n; j++) {
3944                                         struct procstat *ps = &jp->ps[j];
3945                                         /* Skip non-running and not-stopped members
3946                                          * (i.e. dead members) of the job
3947                                          */
3948                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3949                                                 continue;
3950                                         /*
3951                                          * kill_main has matching code to expect
3952                                          * leading space. Needed to not confuse
3953                                          * negative pids with "kill -SIGNAL_NO" syntax
3954                                          */
3955                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3956                                 }
3957                                 *dst = '\0';
3958                         }
3959                 } while (argv[++i]);
3960         }
3961         return kill_main(argc, argv);
3962 }
3963
3964 static void
3965 showpipe(struct job *jp /*, FILE *out*/)
3966 {
3967         struct procstat *ps;
3968         struct procstat *psend;
3969
3970         psend = jp->ps + jp->nprocs;
3971         for (ps = jp->ps + 1; ps < psend; ps++)
3972                 printf(" | %s", ps->ps_cmd);
3973         newline_and_flush(stdout);
3974         flush_stdout_stderr();
3975 }
3976
3977
3978 static int
3979 restartjob(struct job *jp, int mode)
3980 {
3981         struct procstat *ps;
3982         int i;
3983         int status;
3984         pid_t pgid;
3985
3986         INT_OFF;
3987         if (jp->state == JOBDONE)
3988                 goto out;
3989         jp->state = JOBRUNNING;
3990         pgid = jp->ps[0].ps_pid;
3991         if (mode == FORK_FG) {
3992                 get_tty_state();
3993                 xtcsetpgrp(ttyfd, pgid);
3994         }
3995         killpg(pgid, SIGCONT);
3996         ps = jp->ps;
3997         i = jp->nprocs;
3998         do {
3999                 if (WIFSTOPPED(ps->ps_status)) {
4000                         ps->ps_status = -1;
4001                 }
4002                 ps++;
4003         } while (--i);
4004  out:
4005         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4006         INT_ON;
4007         return status;
4008 }
4009
4010 static int FAST_FUNC
4011 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4012 {
4013         struct job *jp;
4014         int mode;
4015         int retval;
4016
4017         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4018         nextopt(nullstr);
4019         argv = argptr;
4020         do {
4021                 jp = getjob(*argv, 1);
4022                 if (mode == FORK_BG) {
4023                         set_curjob(jp, CUR_RUNNING);
4024                         printf("[%d] ", jobno(jp));
4025                 }
4026                 out1str(jp->ps[0].ps_cmd);
4027                 showpipe(jp /*, stdout*/);
4028                 retval = restartjob(jp, mode);
4029         } while (*argv && *++argv);
4030         return retval;
4031 }
4032 #endif
4033
4034 static int
4035 sprint_status48(char *s, int status, int sigonly)
4036 {
4037         int col;
4038         int st;
4039
4040         col = 0;
4041         if (!WIFEXITED(status)) {
4042 #if JOBS
4043                 if (WIFSTOPPED(status))
4044                         st = WSTOPSIG(status);
4045                 else
4046 #endif
4047                         st = WTERMSIG(status);
4048                 if (sigonly) {
4049                         if (st == SIGINT || st == SIGPIPE)
4050                                 goto out;
4051 #if JOBS
4052                         if (WIFSTOPPED(status))
4053                                 goto out;
4054 #endif
4055                 }
4056                 st &= 0x7f;
4057 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4058                 col = fmtstr(s, 32, strsignal(st));
4059                 if (WCOREDUMP(status)) {
4060                         strcpy(s + col, " (core dumped)");
4061                         col += sizeof(" (core dumped)")-1;
4062                 }
4063         } else if (!sigonly) {
4064                 st = WEXITSTATUS(status);
4065                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4066         }
4067  out:
4068         return col;
4069 }
4070
4071 static int
4072 wait_block_or_sig(int *status)
4073 {
4074         int pid;
4075
4076         do {
4077                 sigset_t mask;
4078
4079                 /* Poll all children for changes in their state */
4080                 got_sigchld = 0;
4081                 /* if job control is active, accept stopped processes too */
4082                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4083                 if (pid != 0)
4084                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4085
4086                 /* Children exist, but none are ready. Sleep until interesting signal */
4087 #if 1
4088                 sigfillset(&mask);
4089                 sigprocmask(SIG_SETMASK, &mask, &mask);
4090                 while (!got_sigchld && !pending_sig)
4091                         sigsuspend(&mask);
4092                 sigprocmask(SIG_SETMASK, &mask, NULL);
4093 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4094                 while (!got_sigchld && !pending_sig)
4095                         pause();
4096 #endif
4097
4098                 /* If it was SIGCHLD, poll children again */
4099         } while (got_sigchld);
4100
4101         return pid;
4102 }
4103
4104 #define DOWAIT_NONBLOCK 0
4105 #define DOWAIT_BLOCK    1
4106 #define DOWAIT_BLOCK_OR_SIG 2
4107
4108 static int
4109 dowait(int block, struct job *job)
4110 {
4111         int pid;
4112         int status;
4113         struct job *jp;
4114         struct job *thisjob = NULL;
4115
4116         TRACE(("dowait(0x%x) called\n", block));
4117
4118         /* It's wrong to call waitpid() outside of INT_OFF region:
4119          * signal can arrive just after syscall return and handler can
4120          * longjmp away, losing stop/exit notification processing.
4121          * Thus, for "jobs" builtin, and for waiting for a fg job,
4122          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4123          *
4124          * However, for "wait" builtin it is wrong to simply call waitpid()
4125          * in INT_OFF region: "wait" needs to wait for any running job
4126          * to change state, but should exit on any trap too.
4127          * In INT_OFF region, a signal just before syscall entry can set
4128          * pending_sig variables, but we can't check them, and we would
4129          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4130          *
4131          * Because of this, we run inside INT_OFF, but use a special routine
4132          * which combines waitpid() and sigsuspend().
4133          * This is the reason why we need to have a handler for SIGCHLD:
4134          * SIG_DFL handler does not wake sigsuspend().
4135          */
4136         INT_OFF;
4137         if (block == DOWAIT_BLOCK_OR_SIG) {
4138                 pid = wait_block_or_sig(&status);
4139         } else {
4140                 int wait_flags = 0;
4141                 if (block == DOWAIT_NONBLOCK)
4142                         wait_flags = WNOHANG;
4143                 /* if job control is active, accept stopped processes too */
4144                 if (doing_jobctl)
4145                         wait_flags |= WUNTRACED;
4146                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4147                 pid = waitpid(-1, &status, wait_flags);
4148         }
4149         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4150                                 pid, status, errno, strerror(errno)));
4151         if (pid <= 0)
4152                 goto out;
4153
4154         thisjob = NULL;
4155         for (jp = curjob; jp; jp = jp->prev_job) {
4156                 int jobstate;
4157                 struct procstat *ps;
4158                 struct procstat *psend;
4159                 if (jp->state == JOBDONE)
4160                         continue;
4161                 jobstate = JOBDONE;
4162                 ps = jp->ps;
4163                 psend = ps + jp->nprocs;
4164                 do {
4165                         if (ps->ps_pid == pid) {
4166                                 TRACE(("Job %d: changing status of proc %d "
4167                                         "from 0x%x to 0x%x\n",
4168                                         jobno(jp), pid, ps->ps_status, status));
4169                                 ps->ps_status = status;
4170                                 thisjob = jp;
4171                         }
4172                         if (ps->ps_status == -1)
4173                                 jobstate = JOBRUNNING;
4174 #if JOBS
4175                         if (jobstate == JOBRUNNING)
4176                                 continue;
4177                         if (WIFSTOPPED(ps->ps_status)) {
4178                                 jp->stopstatus = ps->ps_status;
4179                                 jobstate = JOBSTOPPED;
4180                         }
4181 #endif
4182                 } while (++ps < psend);
4183                 if (!thisjob)
4184                         continue;
4185
4186                 /* Found the job where one of its processes changed its state.
4187                  * Is there at least one live and running process in this job? */
4188                 if (jobstate != JOBRUNNING) {
4189                         /* No. All live processes in the job are stopped
4190                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4191                          */
4192                         thisjob->changed = 1;
4193                         if (thisjob->state != jobstate) {
4194                                 TRACE(("Job %d: changing state from %d to %d\n",
4195                                         jobno(thisjob), thisjob->state, jobstate));
4196                                 thisjob->state = jobstate;
4197 #if JOBS
4198                                 if (jobstate == JOBSTOPPED)
4199                                         set_curjob(thisjob, CUR_STOPPED);
4200 #endif
4201                         }
4202                 }
4203                 goto out;
4204         }
4205         /* The process wasn't found in job list */
4206 #if JOBS
4207         if (!WIFSTOPPED(status))
4208                 jobless--;
4209 #endif
4210  out:
4211         INT_ON;
4212
4213         if (thisjob && thisjob == job) {
4214                 char s[48 + 1];
4215                 int len;
4216
4217                 len = sprint_status48(s, status, 1);
4218                 if (len) {
4219                         s[len] = '\n';
4220                         s[len + 1] = '\0';
4221                         out2str(s);
4222                 }
4223         }
4224         return pid;
4225 }
4226
4227 #if JOBS
4228 static void
4229 showjob(struct job *jp, int mode)
4230 {
4231         struct procstat *ps;
4232         struct procstat *psend;
4233         int col;
4234         int indent_col;
4235         char s[16 + 16 + 48];
4236         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4237
4238         ps = jp->ps;
4239
4240         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4241                 /* just output process (group) id of pipeline */
4242                 fprintf(out, "%d\n", ps->ps_pid);
4243                 return;
4244         }
4245
4246         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4247         indent_col = col;
4248
4249         if (jp == curjob)
4250                 s[col - 3] = '+';
4251         else if (curjob && jp == curjob->prev_job)
4252                 s[col - 3] = '-';
4253
4254         if (mode & SHOW_PIDS)
4255                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4256
4257         psend = ps + jp->nprocs;
4258
4259         if (jp->state == JOBRUNNING) {
4260                 strcpy(s + col, "Running");
4261                 col += sizeof("Running") - 1;
4262         } else {
4263                 int status = psend[-1].ps_status;
4264                 if (jp->state == JOBSTOPPED)
4265                         status = jp->stopstatus;
4266                 col += sprint_status48(s + col, status, 0);
4267         }
4268         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4269
4270         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4271          * or prints several "PID             | <cmdN>" lines,
4272          * depending on SHOW_PIDS bit.
4273          * We do not print status of individual processes
4274          * between PID and <cmdN>. bash does it, but not very well:
4275          * first line shows overall job status, not process status,
4276          * making it impossible to know 1st process status.
4277          */
4278         goto start;
4279         do {
4280                 /* for each process */
4281                 s[0] = '\0';
4282                 col = 33;
4283                 if (mode & SHOW_PIDS)
4284                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4285  start:
4286                 fprintf(out, "%s%*c%s%s",
4287                                 s,
4288                                 33 - col >= 0 ? 33 - col : 0, ' ',
4289                                 ps == jp->ps ? "" : "| ",
4290                                 ps->ps_cmd
4291                 );
4292         } while (++ps != psend);
4293         newline_and_flush(out);
4294
4295         jp->changed = 0;
4296
4297         if (jp->state == JOBDONE) {
4298                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4299                 freejob(jp);
4300         }
4301 }
4302
4303 /*
4304  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4305  * statuses have changed since the last call to showjobs.
4306  */
4307 static void
4308 showjobs(int mode)
4309 {
4310         struct job *jp;
4311
4312         TRACE(("showjobs(0x%x) called\n", mode));
4313
4314         /* Handle all finished jobs */
4315         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4316                 continue;
4317
4318         for (jp = curjob; jp; jp = jp->prev_job) {
4319                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4320                         showjob(jp, mode);
4321                 }
4322         }
4323 }
4324
4325 static int FAST_FUNC
4326 jobscmd(int argc UNUSED_PARAM, char **argv)
4327 {
4328         int mode, m;
4329
4330         mode = 0;
4331         while ((m = nextopt("lp")) != '\0') {
4332                 if (m == 'l')
4333                         mode |= SHOW_PIDS;
4334                 else
4335                         mode |= SHOW_ONLY_PGID;
4336         }
4337
4338         argv = argptr;
4339         if (*argv) {
4340                 do
4341                         showjob(getjob(*argv, 0), mode);
4342                 while (*++argv);
4343         } else {
4344                 showjobs(mode);
4345         }
4346
4347         return 0;
4348 }
4349 #endif /* JOBS */
4350
4351 /* Called only on finished or stopped jobs (no members are running) */
4352 static int
4353 getstatus(struct job *job)
4354 {
4355         int status;
4356         int retval;
4357         struct procstat *ps;
4358
4359         /* Fetch last member's status */
4360         ps = job->ps + job->nprocs - 1;
4361         status = ps->ps_status;
4362         if (pipefail) {
4363                 /* "set -o pipefail" mode: use last _nonzero_ status */
4364                 while (status == 0 && --ps >= job->ps)
4365                         status = ps->ps_status;
4366         }
4367
4368         retval = WEXITSTATUS(status);
4369         if (!WIFEXITED(status)) {
4370 #if JOBS
4371                 retval = WSTOPSIG(status);
4372                 if (!WIFSTOPPED(status))
4373 #endif
4374                 {
4375                         /* XXX: limits number of signals */
4376                         retval = WTERMSIG(status);
4377 #if JOBS
4378                         if (retval == SIGINT)
4379                                 job->sigint = 1;
4380 #endif
4381                 }
4382                 retval += 128;
4383         }
4384         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4385                 jobno(job), job->nprocs, status, retval));
4386         return retval;
4387 }
4388
4389 static int FAST_FUNC
4390 waitcmd(int argc UNUSED_PARAM, char **argv)
4391 {
4392         struct job *job;
4393         int retval;
4394         struct job *jp;
4395
4396         nextopt(nullstr);
4397         retval = 0;
4398
4399         argv = argptr;
4400         if (!*argv) {
4401                 /* wait for all jobs */
4402                 for (;;) {
4403                         jp = curjob;
4404                         while (1) {
4405                                 if (!jp) /* no running procs */
4406                                         goto ret;
4407                                 if (jp->state == JOBRUNNING)
4408                                         break;
4409                                 jp->waited = 1;
4410                                 jp = jp->prev_job;
4411                         }
4412         /* man bash:
4413          * "When bash is waiting for an asynchronous command via
4414          * the wait builtin, the reception of a signal for which a trap
4415          * has been set will cause the wait builtin to return immediately
4416          * with an exit status greater than 128, immediately after which
4417          * the trap is executed."
4418          */
4419                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4420         /* if child sends us a signal *and immediately exits*,
4421          * dowait() returns pid > 0. Check this case,
4422          * not "if (dowait() < 0)"!
4423          */
4424                         if (pending_sig)
4425                                 goto sigout;
4426                 }
4427         }
4428
4429         retval = 127;
4430         do {
4431                 if (**argv != '%') {
4432                         pid_t pid = number(*argv);
4433                         job = curjob;
4434                         while (1) {
4435                                 if (!job)
4436                                         goto repeat;
4437                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4438                                         break;
4439                                 job = job->prev_job;
4440                         }
4441                 } else {
4442                         job = getjob(*argv, 0);
4443                 }
4444                 /* loop until process terminated or stopped */
4445                 while (job->state == JOBRUNNING) {
4446                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4447                         if (pending_sig)
4448                                 goto sigout;
4449                 }
4450                 job->waited = 1;
4451                 retval = getstatus(job);
4452  repeat: ;
4453         } while (*++argv);
4454
4455  ret:
4456         return retval;
4457  sigout:
4458         retval = 128 + pending_sig;
4459         return retval;
4460 }
4461
4462 static struct job *
4463 growjobtab(void)
4464 {
4465         size_t len;
4466         ptrdiff_t offset;
4467         struct job *jp, *jq;
4468
4469         len = njobs * sizeof(*jp);
4470         jq = jobtab;
4471         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4472
4473         offset = (char *)jp - (char *)jq;
4474         if (offset) {
4475                 /* Relocate pointers */
4476                 size_t l = len;
4477
4478                 jq = (struct job *)((char *)jq + l);
4479                 while (l) {
4480                         l -= sizeof(*jp);
4481                         jq--;
4482 #define joff(p) ((struct job *)((char *)(p) + l))
4483 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4484                         if (joff(jp)->ps == &jq->ps0)
4485                                 jmove(joff(jp)->ps);
4486                         if (joff(jp)->prev_job)
4487                                 jmove(joff(jp)->prev_job);
4488                 }
4489                 if (curjob)
4490                         jmove(curjob);
4491 #undef joff
4492 #undef jmove
4493         }
4494
4495         njobs += 4;
4496         jobtab = jp;
4497         jp = (struct job *)((char *)jp + len);
4498         jq = jp + 3;
4499         do {
4500                 jq->used = 0;
4501         } while (--jq >= jp);
4502         return jp;
4503 }
4504
4505 /*
4506  * Return a new job structure.
4507  * Called with interrupts off.
4508  */
4509 static struct job *
4510 makejob(/*union node *node,*/ int nprocs)
4511 {
4512         int i;
4513         struct job *jp;
4514
4515         for (i = njobs, jp = jobtab; ; jp++) {
4516                 if (--i < 0) {
4517                         jp = growjobtab();
4518                         break;
4519                 }
4520                 if (jp->used == 0)
4521                         break;
4522                 if (jp->state != JOBDONE || !jp->waited)
4523                         continue;
4524 #if JOBS
4525                 if (doing_jobctl)
4526                         continue;
4527 #endif
4528                 freejob(jp);
4529                 break;
4530         }
4531         memset(jp, 0, sizeof(*jp));
4532 #if JOBS
4533         /* jp->jobctl is a bitfield.
4534          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4535         if (doing_jobctl)
4536                 jp->jobctl = 1;
4537 #endif
4538         jp->prev_job = curjob;
4539         curjob = jp;
4540         jp->used = 1;
4541         jp->ps = &jp->ps0;
4542         if (nprocs > 1) {
4543                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4544         }
4545         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4546                                 jobno(jp)));
4547         return jp;
4548 }
4549
4550 #if JOBS
4551 /*
4552  * Return a string identifying a command (to be printed by the
4553  * jobs command).
4554  */
4555 static char *cmdnextc;
4556
4557 static void
4558 cmdputs(const char *s)
4559 {
4560         static const char vstype[VSTYPE + 1][3] = {
4561                 "", "}", "-", "+", "?", "=",
4562                 "%", "%%", "#", "##"
4563                 IF_BASH_SUBSTR(, ":")
4564                 IF_BASH_PATTERN_SUBST(, "/", "//")
4565         };
4566
4567         const char *p, *str;
4568         char cc[2];
4569         char *nextc;
4570         unsigned char c;
4571         unsigned char subtype = 0;
4572         int quoted = 0;
4573
4574         cc[1] = '\0';
4575         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4576         p = s;
4577         while ((c = *p++) != '\0') {
4578                 str = NULL;
4579                 switch (c) {
4580                 case CTLESC:
4581                         c = *p++;
4582                         break;
4583                 case CTLVAR:
4584                         subtype = *p++;
4585                         if ((subtype & VSTYPE) == VSLENGTH)
4586                                 str = "${#";
4587                         else
4588                                 str = "${";
4589                         goto dostr;
4590                 case CTLENDVAR:
4591                         str = "\"}" + !(quoted & 1);
4592                         quoted >>= 1;
4593                         subtype = 0;
4594                         goto dostr;
4595                 case CTLBACKQ:
4596                         str = "$(...)";
4597                         goto dostr;
4598 #if ENABLE_FEATURE_SH_MATH
4599                 case CTLARI:
4600                         str = "$((";
4601                         goto dostr;
4602                 case CTLENDARI:
4603                         str = "))";
4604                         goto dostr;
4605 #endif
4606                 case CTLQUOTEMARK:
4607                         quoted ^= 1;
4608                         c = '"';
4609                         break;
4610                 case '=':
4611                         if (subtype == 0)
4612                                 break;
4613                         if ((subtype & VSTYPE) != VSNORMAL)
4614                                 quoted <<= 1;
4615                         str = vstype[subtype & VSTYPE];
4616                         if (subtype & VSNUL)
4617                                 c = ':';
4618                         else
4619                                 goto checkstr;
4620                         break;
4621                 case '\'':
4622                 case '\\':
4623                 case '"':
4624                 case '$':
4625                         /* These can only happen inside quotes */
4626                         cc[0] = c;
4627                         str = cc;
4628                         c = '\\';
4629                         break;
4630                 default:
4631                         break;
4632                 }
4633                 USTPUTC(c, nextc);
4634  checkstr:
4635                 if (!str)
4636                         continue;
4637  dostr:
4638                 while ((c = *str++) != '\0') {
4639                         USTPUTC(c, nextc);
4640                 }
4641         } /* while *p++ not NUL */
4642
4643         if (quoted & 1) {
4644                 USTPUTC('"', nextc);
4645         }
4646         *nextc = 0;
4647         cmdnextc = nextc;
4648 }
4649
4650 /* cmdtxt() and cmdlist() call each other */
4651 static void cmdtxt(union node *n);
4652
4653 static void
4654 cmdlist(union node *np, int sep)
4655 {
4656         for (; np; np = np->narg.next) {
4657                 if (!sep)
4658                         cmdputs(" ");
4659                 cmdtxt(np);
4660                 if (sep && np->narg.next)
4661                         cmdputs(" ");
4662         }
4663 }
4664
4665 static void
4666 cmdtxt(union node *n)
4667 {
4668         union node *np;
4669         struct nodelist *lp;
4670         const char *p;
4671
4672         if (!n)
4673                 return;
4674         switch (n->type) {
4675         default:
4676 #if DEBUG
4677                 abort();
4678 #endif
4679         case NPIPE:
4680                 lp = n->npipe.cmdlist;
4681                 for (;;) {
4682                         cmdtxt(lp->n);
4683                         lp = lp->next;
4684                         if (!lp)
4685                                 break;
4686                         cmdputs(" | ");
4687                 }
4688                 break;
4689         case NSEMI:
4690                 p = "; ";
4691                 goto binop;
4692         case NAND:
4693                 p = " && ";
4694                 goto binop;
4695         case NOR:
4696                 p = " || ";
4697  binop:
4698                 cmdtxt(n->nbinary.ch1);
4699                 cmdputs(p);
4700                 n = n->nbinary.ch2;
4701                 goto donode;
4702         case NREDIR:
4703         case NBACKGND:
4704                 n = n->nredir.n;
4705                 goto donode;
4706         case NNOT:
4707                 cmdputs("!");
4708                 n = n->nnot.com;
4709  donode:
4710                 cmdtxt(n);
4711                 break;
4712         case NIF:
4713                 cmdputs("if ");
4714                 cmdtxt(n->nif.test);
4715                 cmdputs("; then ");
4716                 if (n->nif.elsepart) {
4717                         cmdtxt(n->nif.ifpart);
4718                         cmdputs("; else ");
4719                         n = n->nif.elsepart;
4720                 } else {
4721                         n = n->nif.ifpart;
4722                 }
4723                 p = "; fi";
4724                 goto dotail;
4725         case NSUBSHELL:
4726                 cmdputs("(");
4727                 n = n->nredir.n;
4728                 p = ")";
4729                 goto dotail;
4730         case NWHILE:
4731                 p = "while ";
4732                 goto until;
4733         case NUNTIL:
4734                 p = "until ";
4735  until:
4736                 cmdputs(p);
4737                 cmdtxt(n->nbinary.ch1);
4738                 n = n->nbinary.ch2;
4739                 p = "; done";
4740  dodo:
4741                 cmdputs("; do ");
4742  dotail:
4743                 cmdtxt(n);
4744                 goto dotail2;
4745         case NFOR:
4746                 cmdputs("for ");
4747                 cmdputs(n->nfor.var);
4748                 cmdputs(" in ");
4749                 cmdlist(n->nfor.args, 1);
4750                 n = n->nfor.body;
4751                 p = "; done";
4752                 goto dodo;
4753         case NDEFUN:
4754                 cmdputs(n->narg.text);
4755                 p = "() { ... }";
4756                 goto dotail2;
4757         case NCMD:
4758                 cmdlist(n->ncmd.args, 1);
4759                 cmdlist(n->ncmd.redirect, 0);
4760                 break;
4761         case NARG:
4762                 p = n->narg.text;
4763  dotail2:
4764                 cmdputs(p);
4765                 break;
4766         case NHERE:
4767         case NXHERE:
4768                 p = "<<...";
4769                 goto dotail2;
4770         case NCASE:
4771                 cmdputs("case ");
4772                 cmdputs(n->ncase.expr->narg.text);
4773                 cmdputs(" in ");
4774                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4775                         cmdtxt(np->nclist.pattern);
4776                         cmdputs(") ");
4777                         cmdtxt(np->nclist.body);
4778                         cmdputs(";; ");
4779                 }
4780                 p = "esac";
4781                 goto dotail2;
4782         case NTO:
4783                 p = ">";
4784                 goto redir;
4785         case NCLOBBER:
4786                 p = ">|";
4787                 goto redir;
4788         case NAPPEND:
4789                 p = ">>";
4790                 goto redir;
4791 #if BASH_REDIR_OUTPUT
4792         case NTO2:
4793 #endif
4794         case NTOFD:
4795                 p = ">&";
4796                 goto redir;
4797         case NFROM:
4798                 p = "<";
4799                 goto redir;
4800         case NFROMFD:
4801                 p = "<&";
4802                 goto redir;
4803         case NFROMTO:
4804                 p = "<>";
4805  redir:
4806                 cmdputs(utoa(n->nfile.fd));
4807                 cmdputs(p);
4808                 if (n->type == NTOFD || n->type == NFROMFD) {
4809                         cmdputs(utoa(n->ndup.dupfd));
4810                         break;
4811                 }
4812                 n = n->nfile.fname;
4813                 goto donode;
4814         }
4815 }
4816
4817 static char *
4818 commandtext(union node *n)
4819 {
4820         char *name;
4821
4822         STARTSTACKSTR(cmdnextc);
4823         cmdtxt(n);
4824         name = stackblock();
4825         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4826         return ckstrdup(name);
4827 }
4828 #endif /* JOBS */
4829
4830 /*
4831  * Fork off a subshell.  If we are doing job control, give the subshell its
4832  * own process group.  Jp is a job structure that the job is to be added to.
4833  * N is the command that will be evaluated by the child.  Both jp and n may
4834  * be NULL.  The mode parameter can be one of the following:
4835  *      FORK_FG - Fork off a foreground process.
4836  *      FORK_BG - Fork off a background process.
4837  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4838  *                   process group even if job control is on.
4839  *
4840  * When job control is turned off, background processes have their standard
4841  * input redirected to /dev/null (except for the second and later processes
4842  * in a pipeline).
4843  *
4844  * Called with interrupts off.
4845  */
4846 /*
4847  * Clear traps on a fork.
4848  */
4849 static void
4850 clear_traps(void)
4851 {
4852         char **tp;
4853
4854         INT_OFF;
4855         for (tp = trap; tp < &trap[NSIG]; tp++) {
4856                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4857                         if (trap_ptr == trap)
4858                                 free(*tp);
4859                         /* else: it "belongs" to trap_ptr vector, don't free */
4860                         *tp = NULL;
4861                         if ((tp - trap) != 0)
4862                                 setsignal(tp - trap);
4863                 }
4864         }
4865         may_have_traps = 0;
4866         INT_ON;
4867 }
4868
4869 /* Lives far away from here, needed for forkchild */
4870 static void closescript(void);
4871
4872 /* Called after fork(), in child */
4873 /* jp and n are NULL when called by openhere() for heredoc support */
4874 static NOINLINE void
4875 forkchild(struct job *jp, union node *n, int mode)
4876 {
4877         int oldlvl;
4878
4879         TRACE(("Child shell %d\n", getpid()));
4880         oldlvl = shlvl;
4881         shlvl++;
4882
4883         /* man bash: "Non-builtin commands run by bash have signal handlers
4884          * set to the values inherited by the shell from its parent".
4885          * Do we do it correctly? */
4886
4887         closescript();
4888
4889         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4890          && n && n->type == NCMD        /* is it single cmd? */
4891         /* && n->ncmd.args->type == NARG - always true? */
4892          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4893          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4894         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4895         ) {
4896                 TRACE(("Trap hack\n"));
4897                 /* Awful hack for `trap` or $(trap).
4898                  *
4899                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4900                  * contains an example where "trap" is executed in a subshell:
4901                  *
4902                  * save_traps=$(trap)
4903                  * ...
4904                  * eval "$save_traps"
4905                  *
4906                  * Standard does not say that "trap" in subshell shall print
4907                  * parent shell's traps. It only says that its output
4908                  * must have suitable form, but then, in the above example
4909                  * (which is not supposed to be normative), it implies that.
4910                  *
4911                  * bash (and probably other shell) does implement it
4912                  * (traps are reset to defaults, but "trap" still shows them),
4913                  * but as a result, "trap" logic is hopelessly messed up:
4914                  *
4915                  * # trap
4916                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4917                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4918                  * # true | trap   <--- trap is in subshell - no output (ditto)
4919                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4920                  * trap -- 'echo Ho' SIGWINCH
4921                  * # echo `(trap)`         <--- in subshell in subshell - output
4922                  * trap -- 'echo Ho' SIGWINCH
4923                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4924                  * trap -- 'echo Ho' SIGWINCH
4925                  *
4926                  * The rules when to forget and when to not forget traps
4927                  * get really complex and nonsensical.
4928                  *
4929                  * Our solution: ONLY bare $(trap) or `trap` is special.
4930                  */
4931                 /* Save trap handler strings for trap builtin to print */
4932                 trap_ptr = xmemdup(trap, sizeof(trap));
4933                 /* Fall through into clearing traps */
4934         }
4935         clear_traps();
4936 #if JOBS
4937         /* do job control only in root shell */
4938         doing_jobctl = 0;
4939         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4940                 pid_t pgrp;
4941
4942                 if (jp->nprocs == 0)
4943                         pgrp = getpid();
4944                 else
4945                         pgrp = jp->ps[0].ps_pid;
4946                 /* this can fail because we are doing it in the parent also */
4947                 setpgid(0, pgrp);
4948                 if (mode == FORK_FG)
4949                         xtcsetpgrp(ttyfd, pgrp);
4950                 setsignal(SIGTSTP);
4951                 setsignal(SIGTTOU);
4952         } else
4953 #endif
4954         if (mode == FORK_BG) {
4955                 /* man bash: "When job control is not in effect,
4956                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4957                 ignoresig(SIGINT);
4958                 ignoresig(SIGQUIT);
4959                 if (jp->nprocs == 0) {
4960                         close(0);
4961                         if (open(bb_dev_null, O_RDONLY) != 0)
4962                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4963                 }
4964         }
4965         if (oldlvl == 0) {
4966                 if (iflag) { /* why if iflag only? */
4967                         setsignal(SIGINT);
4968                         setsignal(SIGTERM);
4969                 }
4970                 /* man bash:
4971                  * "In all cases, bash ignores SIGQUIT. Non-builtin
4972                  * commands run by bash have signal handlers
4973                  * set to the values inherited by the shell
4974                  * from its parent".
4975                  * Take care of the second rule: */
4976                 setsignal(SIGQUIT);
4977         }
4978 #if JOBS
4979         if (n && n->type == NCMD
4980          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
4981         ) {
4982                 TRACE(("Job hack\n"));
4983                 /* "jobs": we do not want to clear job list for it,
4984                  * instead we remove only _its_ own_ job from job list.
4985                  * This makes "jobs .... | cat" more useful.
4986                  */
4987                 freejob(curjob);
4988                 return;
4989         }
4990 #endif
4991         for (jp = curjob; jp; jp = jp->prev_job)
4992                 freejob(jp);
4993         jobless = 0;
4994 }
4995
4996 /* Called after fork(), in parent */
4997 #if !JOBS
4998 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
4999 #endif
5000 static void
5001 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5002 {
5003         TRACE(("In parent shell: child = %d\n", pid));
5004         if (!jp) {
5005                 /* jp is NULL when called by openhere() for heredoc support */
5006                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5007                         continue;
5008                 jobless++;
5009                 return;
5010         }
5011 #if JOBS
5012         if (mode != FORK_NOJOB && jp->jobctl) {
5013                 int pgrp;
5014
5015                 if (jp->nprocs == 0)
5016                         pgrp = pid;
5017                 else
5018                         pgrp = jp->ps[0].ps_pid;
5019                 /* This can fail because we are doing it in the child also */
5020                 setpgid(pid, pgrp);
5021         }
5022 #endif
5023         if (mode == FORK_BG) {
5024                 backgndpid = pid;               /* set $! */
5025                 set_curjob(jp, CUR_RUNNING);
5026         }
5027         if (jp) {
5028                 struct procstat *ps = &jp->ps[jp->nprocs++];
5029                 ps->ps_pid = pid;
5030                 ps->ps_status = -1;
5031                 ps->ps_cmd = nullstr;
5032 #if JOBS
5033                 if (doing_jobctl && n)
5034                         ps->ps_cmd = commandtext(n);
5035 #endif
5036         }
5037 }
5038
5039 /* jp and n are NULL when called by openhere() for heredoc support */
5040 static int
5041 forkshell(struct job *jp, union node *n, int mode)
5042 {
5043         int pid;
5044
5045         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5046         pid = fork();
5047         if (pid < 0) {
5048                 TRACE(("Fork failed, errno=%d", errno));
5049                 if (jp)
5050                         freejob(jp);
5051                 ash_msg_and_raise_error("can't fork");
5052         }
5053         if (pid == 0) {
5054                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5055                 forkchild(jp, n, mode);
5056         } else {
5057                 forkparent(jp, n, mode, pid);
5058         }
5059         return pid;
5060 }
5061
5062 /*
5063  * Wait for job to finish.
5064  *
5065  * Under job control we have the problem that while a child process
5066  * is running interrupts generated by the user are sent to the child
5067  * but not to the shell.  This means that an infinite loop started by
5068  * an interactive user may be hard to kill.  With job control turned off,
5069  * an interactive user may place an interactive program inside a loop.
5070  * If the interactive program catches interrupts, the user doesn't want
5071  * these interrupts to also abort the loop.  The approach we take here
5072  * is to have the shell ignore interrupt signals while waiting for a
5073  * foreground process to terminate, and then send itself an interrupt
5074  * signal if the child process was terminated by an interrupt signal.
5075  * Unfortunately, some programs want to do a bit of cleanup and then
5076  * exit on interrupt; unless these processes terminate themselves by
5077  * sending a signal to themselves (instead of calling exit) they will
5078  * confuse this approach.
5079  *
5080  * Called with interrupts off.
5081  */
5082 static int
5083 waitforjob(struct job *jp)
5084 {
5085         int st;
5086
5087         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5088
5089         INT_OFF;
5090         while (jp->state == JOBRUNNING) {
5091                 /* In non-interactive shells, we _can_ get
5092                  * a keyboard signal here and be EINTRed,
5093                  * but we just loop back, waiting for command to complete.
5094                  *
5095                  * man bash:
5096                  * "If bash is waiting for a command to complete and receives
5097                  * a signal for which a trap has been set, the trap
5098                  * will not be executed until the command completes."
5099                  *
5100                  * Reality is that even if trap is not set, bash
5101                  * will not act on the signal until command completes.
5102                  * Try this. sleep5intoff.c:
5103                  * #include <signal.h>
5104                  * #include <unistd.h>
5105                  * int main() {
5106                  *         sigset_t set;
5107                  *         sigemptyset(&set);
5108                  *         sigaddset(&set, SIGINT);
5109                  *         sigaddset(&set, SIGQUIT);
5110                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5111                  *         sleep(5);
5112                  *         return 0;
5113                  * }
5114                  * $ bash -c './sleep5intoff; echo hi'
5115                  * ^C^C^C^C <--- pressing ^C once a second
5116                  * $ _
5117                  * $ bash -c './sleep5intoff; echo hi'
5118                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5119                  * $ _
5120                  */
5121                 dowait(DOWAIT_BLOCK, jp);
5122         }
5123         INT_ON;
5124
5125         st = getstatus(jp);
5126 #if JOBS
5127         if (jp->jobctl) {
5128                 xtcsetpgrp(ttyfd, rootpid);
5129                 restore_tty_if_stopped_or_signaled(jp);
5130
5131                 /*
5132                  * This is truly gross.
5133                  * If we're doing job control, then we did a TIOCSPGRP which
5134                  * caused us (the shell) to no longer be in the controlling
5135                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5136                  * intuit from the subprocess exit status whether a SIGINT
5137                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5138                  */
5139                 if (jp->sigint) /* TODO: do the same with all signals */
5140                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5141         }
5142         if (jp->state == JOBDONE)
5143 #endif
5144                 freejob(jp);
5145         return st;
5146 }
5147
5148 /*
5149  * return 1 if there are stopped jobs, otherwise 0
5150  */
5151 static int
5152 stoppedjobs(void)
5153 {
5154         struct job *jp;
5155         int retval;
5156
5157         retval = 0;
5158         if (job_warning)
5159                 goto out;
5160         jp = curjob;
5161         if (jp && jp->state == JOBSTOPPED) {
5162                 out2str("You have stopped jobs.\n");
5163                 job_warning = 2;
5164                 retval++;
5165         }
5166  out:
5167         return retval;
5168 }
5169
5170
5171 /*
5172  * Code for dealing with input/output redirection.
5173  */
5174
5175 #undef EMPTY
5176 #undef CLOSED
5177 #define EMPTY -2                /* marks an unused slot in redirtab */
5178 #define CLOSED -3               /* marks a slot of previously-closed fd */
5179
5180 /*
5181  * Handle here documents.  Normally we fork off a process to write the
5182  * data to a pipe.  If the document is short, we can stuff the data in
5183  * the pipe without forking.
5184  */
5185 /* openhere needs this forward reference */
5186 static void expandhere(union node *arg, int fd);
5187 static int
5188 openhere(union node *redir)
5189 {
5190         int pip[2];
5191         size_t len = 0;
5192
5193         if (pipe(pip) < 0)
5194                 ash_msg_and_raise_error("pipe call failed");
5195         if (redir->type == NHERE) {
5196                 len = strlen(redir->nhere.doc->narg.text);
5197                 if (len <= PIPE_BUF) {
5198                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5199                         goto out;
5200                 }
5201         }
5202         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5203                 /* child */
5204                 close(pip[0]);
5205                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5206                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5207                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5208                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5209                 signal(SIGPIPE, SIG_DFL);
5210                 if (redir->type == NHERE)
5211                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5212                 else /* NXHERE */
5213                         expandhere(redir->nhere.doc, pip[1]);
5214                 _exit(EXIT_SUCCESS);
5215         }
5216  out:
5217         close(pip[1]);
5218         return pip[0];
5219 }
5220
5221 static int
5222 openredirect(union node *redir)
5223 {
5224         struct stat sb;
5225         char *fname;
5226         int f;
5227
5228         switch (redir->nfile.type) {
5229 /* Can't happen, our single caller does this itself */
5230 //      case NTOFD:
5231 //      case NFROMFD:
5232 //              return -1;
5233         case NHERE:
5234         case NXHERE:
5235                 return openhere(redir);
5236         }
5237
5238         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5239          * allocated space. Do it only when we know it is safe.
5240          */
5241         fname = redir->nfile.expfname;
5242
5243         switch (redir->nfile.type) {
5244         default:
5245 #if DEBUG
5246                 abort();
5247 #endif
5248         case NFROM:
5249                 f = open(fname, O_RDONLY);
5250                 if (f < 0)
5251                         goto eopen;
5252                 break;
5253         case NFROMTO:
5254                 f = open(fname, O_RDWR|O_CREAT, 0666);
5255                 if (f < 0)
5256                         goto ecreate;
5257                 break;
5258         case NTO:
5259 #if BASH_REDIR_OUTPUT
5260         case NTO2:
5261 #endif
5262                 /* Take care of noclobber mode. */
5263                 if (Cflag) {
5264                         if (stat(fname, &sb) < 0) {
5265                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5266                                 if (f < 0)
5267                                         goto ecreate;
5268                         } else if (!S_ISREG(sb.st_mode)) {
5269                                 f = open(fname, O_WRONLY, 0666);
5270                                 if (f < 0)
5271                                         goto ecreate;
5272                                 if (fstat(f, &sb) < 0 && S_ISREG(sb.st_mode)) {
5273                                         close(f);
5274                                         errno = EEXIST;
5275                                         goto ecreate;
5276                                 }
5277                         } else {
5278                                 errno = EEXIST;
5279                                 goto ecreate;
5280                         }
5281                         break;
5282                 }
5283                 /* FALLTHROUGH */
5284         case NCLOBBER:
5285                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5286                 if (f < 0)
5287                         goto ecreate;
5288                 break;
5289         case NAPPEND:
5290                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5291                 if (f < 0)
5292                         goto ecreate;
5293                 break;
5294         }
5295
5296         return f;
5297  ecreate:
5298         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5299  eopen:
5300         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5301 }
5302
5303 /*
5304  * Copy a file descriptor to be >= 10. Throws exception on error.
5305  */
5306 static int
5307 savefd(int from)
5308 {
5309         int newfd;
5310         int err;
5311
5312         newfd = fcntl(from, F_DUPFD, 10);
5313         err = newfd < 0 ? errno : 0;
5314         if (err != EBADF) {
5315                 if (err)
5316                         ash_msg_and_raise_error("%d: %m", from);
5317                 close(from);
5318                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5319         }
5320
5321         return newfd;
5322 }
5323 static int
5324 dup2_or_raise(int from, int to)
5325 {
5326         int newfd;
5327
5328         newfd = (from != to) ? dup2(from, to) : to;
5329         if (newfd < 0) {
5330                 /* Happens when source fd is not open: try "echo >&99" */
5331                 ash_msg_and_raise_error("%d: %m", from);
5332         }
5333         return newfd;
5334 }
5335
5336 /* Struct def and variable are moved down to the first usage site */
5337 struct two_fd_t {
5338         int orig, copy;
5339 };
5340 struct redirtab {
5341         struct redirtab *next;
5342         int pair_count;
5343         struct two_fd_t two_fd[];
5344 };
5345 #define redirlist (G_var.redirlist)
5346 enum {
5347         COPYFD_RESTORE = (int)~(INT_MAX),
5348 };
5349
5350 static int
5351 need_to_remember(struct redirtab *rp, int fd)
5352 {
5353         int i;
5354
5355         if (!rp) /* remembering was not requested */
5356                 return 0;
5357
5358         for (i = 0; i < rp->pair_count; i++) {
5359                 if (rp->two_fd[i].orig == fd) {
5360                         /* already remembered */
5361                         return 0;
5362                 }
5363         }
5364         return 1;
5365 }
5366
5367 /* "hidden" fd is a fd used to read scripts, or a copy of such */
5368 static int
5369 is_hidden_fd(struct redirtab *rp, int fd)
5370 {
5371         int i;
5372         struct parsefile *pf;
5373
5374         if (fd == -1)
5375                 return 0;
5376         /* Check open scripts' fds */
5377         pf = g_parsefile;
5378         while (pf) {
5379                 /* We skip pf_fd == 0 case because of the following case:
5380                  * $ ash  # running ash interactively
5381                  * $ . ./script.sh
5382                  * and in script.sh: "exec 9>&0".
5383                  * Even though top-level pf_fd _is_ 0,
5384                  * it's still ok to use it: "read" builtin uses it,
5385                  * why should we cripple "exec" builtin?
5386                  */
5387                 if (pf->pf_fd > 0 && fd == pf->pf_fd) {
5388                         return 1;
5389                 }
5390                 pf = pf->prev;
5391         }
5392
5393         if (!rp)
5394                 return 0;
5395         /* Check saved fds of redirects */
5396         fd |= COPYFD_RESTORE;
5397         for (i = 0; i < rp->pair_count; i++) {
5398                 if (rp->two_fd[i].copy == fd) {
5399                         return 1;
5400                 }
5401         }
5402         return 0;
5403 }
5404
5405 /*
5406  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5407  * old file descriptors are stashed away so that the redirection can be
5408  * undone by calling popredir.
5409  */
5410 /* flags passed to redirect */
5411 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5412 #define REDIR_SAVEFD2 03        /* set preverrout */
5413 static void
5414 redirect(union node *redir, int flags)
5415 {
5416         struct redirtab *sv;
5417         int sv_pos;
5418         int i;
5419         int fd;
5420         int newfd;
5421         int copied_fd2 = -1;
5422
5423         if (!redir) {
5424                 return;
5425         }
5426
5427         sv = NULL;
5428         sv_pos = 0;
5429         INT_OFF;
5430         if (flags & REDIR_PUSH) {
5431                 union node *tmp = redir;
5432                 do {
5433                         sv_pos++;
5434 #if BASH_REDIR_OUTPUT
5435                         if (tmp->nfile.type == NTO2)
5436                                 sv_pos++;
5437 #endif
5438                         tmp = tmp->nfile.next;
5439                 } while (tmp);
5440                 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5441                 sv->next = redirlist;
5442                 sv->pair_count = sv_pos;
5443                 redirlist = sv;
5444                 while (sv_pos > 0) {
5445                         sv_pos--;
5446                         sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5447                 }
5448         }
5449
5450         do {
5451                 int right_fd = -1;
5452                 fd = redir->nfile.fd;
5453                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5454                         right_fd = redir->ndup.dupfd;
5455                         //bb_error_msg("doing %d > %d", fd, right_fd);
5456                         /* redirect from/to same file descriptor? */
5457                         if (right_fd == fd)
5458                                 continue;
5459                         /* "echo >&10" and 10 is a fd opened to a sh script? */
5460                         if (is_hidden_fd(sv, right_fd)) {
5461                                 errno = EBADF; /* as if it is closed */
5462                                 ash_msg_and_raise_error("%d: %m", right_fd);
5463                         }
5464                         newfd = -1;
5465                 } else {
5466                         newfd = openredirect(redir); /* always >= 0 */
5467                         if (fd == newfd) {
5468                                 /* Descriptor wasn't open before redirect.
5469                                  * Mark it for close in the future */
5470                                 if (need_to_remember(sv, fd)) {
5471                                         goto remember_to_close;
5472                                 }
5473                                 continue;
5474                         }
5475                 }
5476 #if BASH_REDIR_OUTPUT
5477  redirect_more:
5478 #endif
5479                 if (need_to_remember(sv, fd)) {
5480                         /* Copy old descriptor */
5481                         /* Careful to not accidentally "save"
5482                          * to the same fd as right side fd in N>&M */
5483                         int minfd = right_fd < 10 ? 10 : right_fd + 1;
5484 #if defined(F_DUPFD_CLOEXEC)
5485                         i = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
5486 #else
5487                         i = fcntl(fd, F_DUPFD, minfd);
5488 #endif
5489                         if (i == -1) {
5490                                 i = errno;
5491                                 if (i != EBADF) {
5492                                         /* Strange error (e.g. "too many files" EMFILE?) */
5493                                         if (newfd >= 0)
5494                                                 close(newfd);
5495                                         errno = i;
5496                                         ash_msg_and_raise_error("%d: %m", fd);
5497                                         /* NOTREACHED */
5498                                 }
5499                                 /* EBADF: it is not open - good, remember to close it */
5500  remember_to_close:
5501                                 i = CLOSED;
5502                         } else { /* fd is open, save its copy */
5503 #if !defined(F_DUPFD_CLOEXEC)
5504                                 fcntl(i, F_SETFD, FD_CLOEXEC);
5505 #endif
5506                                 /* "exec fd>&-" should not close fds
5507                                  * which point to script file(s).
5508                                  * Force them to be restored afterwards */
5509                                 if (is_hidden_fd(sv, fd))
5510                                         i |= COPYFD_RESTORE;
5511                         }
5512                         if (fd == 2)
5513                                 copied_fd2 = i;
5514                         sv->two_fd[sv_pos].orig = fd;
5515                         sv->two_fd[sv_pos].copy = i;
5516                         sv_pos++;
5517                 }
5518                 if (newfd < 0) {
5519                         /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5520                         if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5521                                 /* Don't want to trigger debugging */
5522                                 if (fd != -1)
5523                                         close(fd);
5524                         } else {
5525                                 dup2_or_raise(redir->ndup.dupfd, fd);
5526                         }
5527                 } else if (fd != newfd) { /* move newfd to fd */
5528                         dup2_or_raise(newfd, fd);
5529 #if BASH_REDIR_OUTPUT
5530                         if (!(redir->nfile.type == NTO2 && fd == 2))
5531 #endif
5532                                 close(newfd);
5533                 }
5534 #if BASH_REDIR_OUTPUT
5535                 if (redir->nfile.type == NTO2 && fd == 1) {
5536                         /* We already redirected it to fd 1, now copy it to 2 */
5537                         newfd = 1;
5538                         fd = 2;
5539                         goto redirect_more;
5540                 }
5541 #endif
5542         } while ((redir = redir->nfile.next) != NULL);
5543
5544         INT_ON;
5545         if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5546                 preverrout_fd = copied_fd2;
5547 }
5548
5549 /*
5550  * Undo the effects of the last redirection.
5551  */
5552 static void
5553 popredir(int drop, int restore)
5554 {
5555         struct redirtab *rp;
5556         int i;
5557
5558         if (redirlist == NULL)
5559                 return;
5560         INT_OFF;
5561         rp = redirlist;
5562         for (i = 0; i < rp->pair_count; i++) {
5563                 int fd = rp->two_fd[i].orig;
5564                 int copy = rp->two_fd[i].copy;
5565                 if (copy == CLOSED) {
5566                         if (!drop)
5567                                 close(fd);
5568                         continue;
5569                 }
5570                 if (copy != EMPTY) {
5571                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5572                                 copy &= ~COPYFD_RESTORE;
5573                                 /*close(fd);*/
5574                                 dup2_or_raise(copy, fd);
5575                         }
5576                         close(copy & ~COPYFD_RESTORE);
5577                 }
5578         }
5579         redirlist = rp->next;
5580         free(rp);
5581         INT_ON;
5582 }
5583
5584 /*
5585  * Undo all redirections.  Called on error or interrupt.
5586  */
5587
5588 static int
5589 redirectsafe(union node *redir, int flags)
5590 {
5591         int err;
5592         volatile int saveint;
5593         struct jmploc *volatile savehandler = exception_handler;
5594         struct jmploc jmploc;
5595
5596         SAVE_INT(saveint);
5597         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5598         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5599         if (!err) {
5600                 exception_handler = &jmploc;
5601                 redirect(redir, flags);
5602         }
5603         exception_handler = savehandler;
5604         if (err && exception_type != EXERROR)
5605                 longjmp(exception_handler->loc, 1);
5606         RESTORE_INT(saveint);
5607         return err;
5608 }
5609
5610
5611 /* ============ Routines to expand arguments to commands
5612  *
5613  * We have to deal with backquotes, shell variables, and file metacharacters.
5614  */
5615
5616 #if ENABLE_FEATURE_SH_MATH
5617 static arith_t
5618 ash_arith(const char *s)
5619 {
5620         arith_state_t math_state;
5621         arith_t result;
5622
5623         math_state.lookupvar = lookupvar;
5624         math_state.setvar    = setvar0;
5625         //math_state.endofname = endofname;
5626
5627         INT_OFF;
5628         result = arith(&math_state, s);
5629         if (math_state.errmsg)
5630                 ash_msg_and_raise_error(math_state.errmsg);
5631         INT_ON;
5632
5633         return result;
5634 }
5635 #endif
5636
5637 /*
5638  * expandarg flags
5639  */
5640 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5641 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5642 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5643 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5644 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5645  * POSIX says for this case:
5646  *  Pathname expansion shall not be performed on the word by a
5647  *  non-interactive shell; an interactive shell may perform it, but shall
5648  *  do so only when the expansion would result in one word.
5649  * Currently, our code complies to the above rule by never globbing
5650  * redirection filenames.
5651  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5652  * (this means that on a typical Linux distro, bash almost always
5653  * performs globbing, and thus diverges from what we do).
5654  */
5655 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5656 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5657 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5658 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5659 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5660 /*
5661  * rmescape() flags
5662  */
5663 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5664 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5665 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5666 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5667 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5668
5669 /* Add CTLESC when necessary. */
5670 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT)
5671 /* Do not skip NUL characters. */
5672 #define QUOTES_KEEPNUL EXP_TILDE
5673
5674 /*
5675  * Structure specifying which parts of the string should be searched
5676  * for IFS characters.
5677  */
5678 struct ifsregion {
5679         struct ifsregion *next; /* next region in list */
5680         int begoff;             /* offset of start of region */
5681         int endoff;             /* offset of end of region */
5682         int nulonly;            /* search for nul bytes only */
5683 };
5684
5685 struct arglist {
5686         struct strlist *list;
5687         struct strlist **lastp;
5688 };
5689
5690 /* output of current string */
5691 static char *expdest;
5692 /* list of back quote expressions */
5693 static struct nodelist *argbackq;
5694 /* first struct in list of ifs regions */
5695 static struct ifsregion ifsfirst;
5696 /* last struct in list */
5697 static struct ifsregion *ifslastp;
5698 /* holds expanded arg list */
5699 static struct arglist exparg;
5700
5701 /*
5702  * Our own itoa().
5703  * cvtnum() is used even if math support is off (to prepare $? values and such).
5704  */
5705 static int
5706 cvtnum(arith_t num)
5707 {
5708         int len;
5709
5710         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5711         len = sizeof(arith_t) * 3;
5712         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5713         if (sizeof(arith_t) < 4) len += 2;
5714
5715         expdest = makestrspace(len, expdest);
5716         len = fmtstr(expdest, len, ARITH_FMT, num);
5717         STADJUST(len, expdest);
5718         return len;
5719 }
5720
5721 /*
5722  * Break the argument string into pieces based upon IFS and add the
5723  * strings to the argument list.  The regions of the string to be
5724  * searched for IFS characters have been stored by recordregion.
5725  */
5726 static void
5727 ifsbreakup(char *string, struct arglist *arglist)
5728 {
5729         struct ifsregion *ifsp;
5730         struct strlist *sp;
5731         char *start;
5732         char *p;
5733         char *q;
5734         const char *ifs, *realifs;
5735         int ifsspc;
5736         int nulonly;
5737
5738         start = string;
5739         if (ifslastp != NULL) {
5740                 ifsspc = 0;
5741                 nulonly = 0;
5742                 realifs = ifsset() ? ifsval() : defifs;
5743                 ifsp = &ifsfirst;
5744                 do {
5745                         p = string + ifsp->begoff;
5746                         nulonly = ifsp->nulonly;
5747                         ifs = nulonly ? nullstr : realifs;
5748                         ifsspc = 0;
5749                         while (p < string + ifsp->endoff) {
5750                                 q = p;
5751                                 if ((unsigned char)*p == CTLESC)
5752                                         p++;
5753                                 if (!strchr(ifs, *p)) {
5754                                         p++;
5755                                         continue;
5756                                 }
5757                                 if (!nulonly)
5758                                         ifsspc = (strchr(defifs, *p) != NULL);
5759                                 /* Ignore IFS whitespace at start */
5760                                 if (q == start && ifsspc) {
5761                                         p++;
5762                                         start = p;
5763                                         continue;
5764                                 }
5765                                 *q = '\0';
5766                                 sp = stzalloc(sizeof(*sp));
5767                                 sp->text = start;
5768                                 *arglist->lastp = sp;
5769                                 arglist->lastp = &sp->next;
5770                                 p++;
5771                                 if (!nulonly) {
5772                                         for (;;) {
5773                                                 if (p >= string + ifsp->endoff) {
5774                                                         break;
5775                                                 }
5776                                                 q = p;
5777                                                 if ((unsigned char)*p == CTLESC)
5778                                                         p++;
5779                                                 if (strchr(ifs, *p) == NULL) {
5780                                                         p = q;
5781                                                         break;
5782                                                 }
5783                                                 if (strchr(defifs, *p) == NULL) {
5784                                                         if (ifsspc) {
5785                                                                 p++;
5786                                                                 ifsspc = 0;
5787                                                         } else {
5788                                                                 p = q;
5789                                                                 break;
5790                                                         }
5791                                                 } else
5792                                                         p++;
5793                                         }
5794                                 }
5795                                 start = p;
5796                         } /* while */
5797                         ifsp = ifsp->next;
5798                 } while (ifsp != NULL);
5799                 if (nulonly)
5800                         goto add;
5801         }
5802
5803         if (!*start)
5804                 return;
5805
5806  add:
5807         sp = stzalloc(sizeof(*sp));
5808         sp->text = start;
5809         *arglist->lastp = sp;
5810         arglist->lastp = &sp->next;
5811 }
5812
5813 static void
5814 ifsfree(void)
5815 {
5816         struct ifsregion *p = ifsfirst.next;
5817
5818         if (!p)
5819                 goto out;
5820
5821         INT_OFF;
5822         do {
5823                 struct ifsregion *ifsp;
5824                 ifsp = p->next;
5825                 free(p);
5826                 p = ifsp;
5827         } while (p);
5828         ifsfirst.next = NULL;
5829         INT_ON;
5830  out:
5831         ifslastp = NULL;
5832 }
5833
5834 static size_t
5835 esclen(const char *start, const char *p)
5836 {
5837         size_t esc = 0;
5838
5839         while (p > start && (unsigned char)*--p == CTLESC) {
5840                 esc++;
5841         }
5842         return esc;
5843 }
5844
5845 /*
5846  * Remove any CTLESC characters from a string.
5847  */
5848 static char *
5849 rmescapes(char *str, int flag)
5850 {
5851         static const char qchars[] ALIGN1 = {
5852                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5853
5854         char *p, *q, *r;
5855         unsigned inquotes;
5856         unsigned protect_against_glob;
5857         unsigned globbing;
5858         IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5859
5860         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5861         if (!p)
5862                 return str;
5863
5864         q = p;
5865         r = str;
5866         if (flag & RMESCAPE_ALLOC) {
5867                 size_t len = p - str;
5868                 size_t fulllen = len + strlen(p) + 1;
5869
5870                 if (flag & RMESCAPE_GROW) {
5871                         int strloc = str - (char *)stackblock();
5872                         r = makestrspace(fulllen, expdest);
5873                         /* p and str may be invalidated by makestrspace */
5874                         str = (char *)stackblock() + strloc;
5875                         p = str + len;
5876                 } else if (flag & RMESCAPE_HEAP) {
5877                         r = ckmalloc(fulllen);
5878                 } else {
5879                         r = stalloc(fulllen);
5880                 }
5881                 q = r;
5882                 if (len > 0) {
5883                         q = (char *)mempcpy(q, str, len);
5884                 }
5885         }
5886
5887         inquotes = 0;
5888         globbing = flag & RMESCAPE_GLOB;
5889         protect_against_glob = globbing;
5890         while (*p) {
5891                 if ((unsigned char)*p == CTLQUOTEMARK) {
5892 // Note: both inquotes and protect_against_glob only affect whether
5893 // CTLESC,<ch> gets converted to <ch> or to \<ch>
5894                         inquotes = ~inquotes;
5895                         p++;
5896                         protect_against_glob = globbing;
5897                         continue;
5898                 }
5899                 if ((unsigned char)*p == CTLESC) {
5900                         p++;
5901 #if DEBUG
5902                         if (*p == '\0')
5903                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
5904 #endif
5905                         if (protect_against_glob) {
5906                                 /*
5907                                  * We used to trust glob() and fnmatch() to eat
5908                                  * superfluous escapes (\z where z has no
5909                                  * special meaning anyway). But this causes
5910                                  * bugs such as string of one greek letter rho
5911                                  * (unicode-encoded as two bytes "cf,81")
5912                                  * getting encoded as "cf,CTLESC,81"
5913                                  * and here, converted to "cf,\,81" -
5914                                  * which does not go well with some flavors
5915                                  * of fnmatch() in unicode locales
5916                                  * (for example, glibc <= 2.22).
5917                                  *
5918                                  * Lets add "\" only on the chars which need it.
5919                                  * Testcases for less obvious chars are shown.
5920                                  */
5921                                 if (*p == '*'
5922                                  || *p == '?'
5923                                  || *p == '['
5924                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
5925                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
5926                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
5927                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
5928                                 /* Some libc support [^negate], that's why "^" also needs love */
5929                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
5930                                 ) {
5931                                         *q++ = '\\';
5932                                 }
5933                         }
5934                 } else if (*p == '\\' && !inquotes) {
5935                         /* naked back slash */
5936                         protect_against_glob = 0;
5937                         goto copy;
5938                 }
5939 #if BASH_PATTERN_SUBST
5940                 else if (*p == '/' && slash) {
5941                         /* stop handling globbing and mark location of slash */
5942                         globbing = slash = 0;
5943                         *p = CTLESC;
5944                 }
5945 #endif
5946                 protect_against_glob = globbing;
5947  copy:
5948                 *q++ = *p++;
5949         }
5950         *q = '\0';
5951         if (flag & RMESCAPE_GROW) {
5952                 expdest = r;
5953                 STADJUST(q - r + 1, expdest);
5954         }
5955         return r;
5956 }
5957 #define pmatch(a, b) !fnmatch((a), (b), 0)
5958
5959 /*
5960  * Prepare a pattern for a expmeta (internal glob(3)) call.
5961  *
5962  * Returns an stalloced string.
5963  */
5964 static char *
5965 preglob(const char *pattern, int flag)
5966 {
5967         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
5968 }
5969
5970 /*
5971  * Put a string on the stack.
5972  */
5973 static void
5974 memtodest(const char *p, size_t len, int syntax, int quotes)
5975 {
5976         char *q;
5977
5978         if (!len)
5979                 return;
5980
5981         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
5982
5983         do {
5984                 unsigned char c = *p++;
5985                 if (c) {
5986                         if (quotes & QUOTES_ESC) {
5987                                 int n = SIT(c, syntax);
5988                                 if (n == CCTL
5989                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
5990                                      && n == CBACK
5991                                     )
5992                                 ) {
5993                                         USTPUTC(CTLESC, q);
5994                                 }
5995                         }
5996                 } else if (!(quotes & QUOTES_KEEPNUL))
5997                         continue;
5998                 USTPUTC(c, q);
5999         } while (--len);
6000
6001         expdest = q;
6002 }
6003
6004 static size_t
6005 strtodest(const char *p, int syntax, int quotes)
6006 {
6007         size_t len = strlen(p);
6008         memtodest(p, len, syntax, quotes);
6009         return len;
6010 }
6011
6012 /*
6013  * Record the fact that we have to scan this region of the
6014  * string for IFS characters.
6015  */
6016 static void
6017 recordregion(int start, int end, int nulonly)
6018 {
6019         struct ifsregion *ifsp;
6020
6021         if (ifslastp == NULL) {
6022                 ifsp = &ifsfirst;
6023         } else {
6024                 INT_OFF;
6025                 ifsp = ckzalloc(sizeof(*ifsp));
6026                 /*ifsp->next = NULL; - ckzalloc did it */
6027                 ifslastp->next = ifsp;
6028                 INT_ON;
6029         }
6030         ifslastp = ifsp;
6031         ifslastp->begoff = start;
6032         ifslastp->endoff = end;
6033         ifslastp->nulonly = nulonly;
6034 }
6035
6036 static void
6037 removerecordregions(int endoff)
6038 {
6039         if (ifslastp == NULL)
6040                 return;
6041
6042         if (ifsfirst.endoff > endoff) {
6043                 while (ifsfirst.next) {
6044                         struct ifsregion *ifsp;
6045                         INT_OFF;
6046                         ifsp = ifsfirst.next->next;
6047                         free(ifsfirst.next);
6048                         ifsfirst.next = ifsp;
6049                         INT_ON;
6050                 }
6051                 if (ifsfirst.begoff > endoff) {
6052                         ifslastp = NULL;
6053                 } else {
6054                         ifslastp = &ifsfirst;
6055                         ifsfirst.endoff = endoff;
6056                 }
6057                 return;
6058         }
6059
6060         ifslastp = &ifsfirst;
6061         while (ifslastp->next && ifslastp->next->begoff < endoff)
6062                 ifslastp = ifslastp->next;
6063         while (ifslastp->next) {
6064                 struct ifsregion *ifsp;
6065                 INT_OFF;
6066                 ifsp = ifslastp->next->next;
6067                 free(ifslastp->next);
6068                 ifslastp->next = ifsp;
6069                 INT_ON;
6070         }
6071         if (ifslastp->endoff > endoff)
6072                 ifslastp->endoff = endoff;
6073 }
6074
6075 static char *
6076 exptilde(char *startp, char *p, int flags)
6077 {
6078         unsigned char c;
6079         char *name;
6080         struct passwd *pw;
6081         const char *home;
6082         int quotes = flags & QUOTES_ESC;
6083
6084         name = p + 1;
6085
6086         while ((c = *++p) != '\0') {
6087                 switch (c) {
6088                 case CTLESC:
6089                         return startp;
6090                 case CTLQUOTEMARK:
6091                         return startp;
6092                 case ':':
6093                         if (flags & EXP_VARTILDE)
6094                                 goto done;
6095                         break;
6096                 case '/':
6097                 case CTLENDVAR:
6098                         goto done;
6099                 }
6100         }
6101  done:
6102         *p = '\0';
6103         if (*name == '\0') {
6104                 home = lookupvar("HOME");
6105         } else {
6106                 pw = getpwnam(name);
6107                 if (pw == NULL)
6108                         goto lose;
6109                 home = pw->pw_dir;
6110         }
6111         if (!home || !*home)
6112                 goto lose;
6113         *p = c;
6114         strtodest(home, SQSYNTAX, quotes);
6115         return p;
6116  lose:
6117         *p = c;
6118         return startp;
6119 }
6120
6121 /*
6122  * Execute a command inside back quotes.  If it's a builtin command, we
6123  * want to save its output in a block obtained from malloc.  Otherwise
6124  * we fork off a subprocess and get the output of the command via a pipe.
6125  * Should be called with interrupts off.
6126  */
6127 struct backcmd {                /* result of evalbackcmd */
6128         int fd;                 /* file descriptor to read from */
6129         int nleft;              /* number of chars in buffer */
6130         char *buf;              /* buffer */
6131         struct job *jp;         /* job structure for command */
6132 };
6133
6134 /* These forward decls are needed to use "eval" code for backticks handling: */
6135 /* flags in argument to evaltree */
6136 #define EV_EXIT    01           /* exit after evaluating tree */
6137 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6138 static int evaltree(union node *, int);
6139
6140 static void FAST_FUNC
6141 evalbackcmd(union node *n, struct backcmd *result)
6142 {
6143         int pip[2];
6144         struct job *jp;
6145
6146         result->fd = -1;
6147         result->buf = NULL;
6148         result->nleft = 0;
6149         result->jp = NULL;
6150         if (n == NULL) {
6151                 goto out;
6152         }
6153
6154         if (pipe(pip) < 0)
6155                 ash_msg_and_raise_error("pipe call failed");
6156         jp = makejob(/*n,*/ 1);
6157         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6158                 /* child */
6159                 FORCE_INT_ON;
6160                 close(pip[0]);
6161                 if (pip[1] != 1) {
6162                         /*close(1);*/
6163                         dup2_or_raise(pip[1], 1);
6164                         close(pip[1]);
6165                 }
6166 /* TODO: eflag clearing makes the following not abort:
6167  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6168  * which is what bash does (unless it is in POSIX mode).
6169  * dash deleted "eflag = 0" line in the commit
6170  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6171  *  [EVAL] Don't clear eflag in evalbackcmd
6172  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6173  */
6174                 eflag = 0;
6175                 ifsfree();
6176                 evaltree(n, EV_EXIT); /* actually evaltreenr... */
6177                 /* NOTREACHED */
6178         }
6179         /* parent */
6180         close(pip[1]);
6181         result->fd = pip[0];
6182         result->jp = jp;
6183
6184  out:
6185         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6186                 result->fd, result->buf, result->nleft, result->jp));
6187 }
6188
6189 /*
6190  * Expand stuff in backwards quotes.
6191  */
6192 static void
6193 expbackq(union node *cmd, int flag)
6194 {
6195         struct backcmd in;
6196         int i;
6197         char buf[128];
6198         char *p;
6199         char *dest;
6200         int startloc;
6201         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6202         struct stackmark smark;
6203
6204         INT_OFF;
6205         startloc = expdest - (char *)stackblock();
6206         pushstackmark(&smark, startloc);
6207         evalbackcmd(cmd, &in);
6208         popstackmark(&smark);
6209
6210         p = in.buf;
6211         i = in.nleft;
6212         if (i == 0)
6213                 goto read;
6214         for (;;) {
6215                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6216  read:
6217                 if (in.fd < 0)
6218                         break;
6219                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6220                 TRACE(("expbackq: read returns %d\n", i));
6221                 if (i <= 0)
6222                         break;
6223                 p = buf;
6224         }
6225
6226         free(in.buf);
6227         if (in.fd >= 0) {
6228                 close(in.fd);
6229                 back_exitstatus = waitforjob(in.jp);
6230         }
6231         INT_ON;
6232
6233         /* Eat all trailing newlines */
6234         dest = expdest;
6235         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6236                 STUNPUTC(dest);
6237         expdest = dest;
6238
6239         if (!(flag & EXP_QUOTED))
6240                 recordregion(startloc, dest - (char *)stackblock(), 0);
6241         TRACE(("evalbackq: size:%d:'%.*s'\n",
6242                 (int)((dest - (char *)stackblock()) - startloc),
6243                 (int)((dest - (char *)stackblock()) - startloc),
6244                 stackblock() + startloc));
6245 }
6246
6247 #if ENABLE_FEATURE_SH_MATH
6248 /*
6249  * Expand arithmetic expression.  Backup to start of expression,
6250  * evaluate, place result in (backed up) result, adjust string position.
6251  */
6252 static void
6253 expari(int flag)
6254 {
6255         char *p, *start;
6256         int begoff;
6257         int len;
6258
6259         /* ifsfree(); */
6260
6261         /*
6262          * This routine is slightly over-complicated for
6263          * efficiency.  Next we scan backwards looking for the
6264          * start of arithmetic.
6265          */
6266         start = stackblock();
6267         p = expdest - 1;
6268         *p = '\0';
6269         p--;
6270         while (1) {
6271                 int esc;
6272
6273                 while ((unsigned char)*p != CTLARI) {
6274                         p--;
6275 #if DEBUG
6276                         if (p < start) {
6277                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6278                         }
6279 #endif
6280                 }
6281
6282                 esc = esclen(start, p);
6283                 if (!(esc % 2)) {
6284                         break;
6285                 }
6286
6287                 p -= esc + 1;
6288         }
6289
6290         begoff = p - start;
6291
6292         removerecordregions(begoff);
6293
6294         expdest = p;
6295
6296         if (flag & QUOTES_ESC)
6297                 rmescapes(p + 1, 0);
6298
6299         len = cvtnum(ash_arith(p + 1));
6300
6301         if (!(flag & EXP_QUOTED))
6302                 recordregion(begoff, begoff + len, 0);
6303 }
6304 #endif
6305
6306 /* argstr needs it */
6307 static char *evalvar(char *p, int flags, struct strlist *var_str_list);
6308
6309 /*
6310  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6311  * characters to allow for further processing.  Otherwise treat
6312  * $@ like $* since no splitting will be performed.
6313  *
6314  * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
6315  * over shell variables. Needed for "A=a B=$A; echo $B" case - we use it
6316  * for correct expansion of "B=$A" word.
6317  */
6318 static void
6319 argstr(char *p, int flags, struct strlist *var_str_list)
6320 {
6321         static const char spclchars[] ALIGN1 = {
6322                 '=',
6323                 ':',
6324                 CTLQUOTEMARK,
6325                 CTLENDVAR,
6326                 CTLESC,
6327                 CTLVAR,
6328                 CTLBACKQ,
6329 #if ENABLE_FEATURE_SH_MATH
6330                 CTLENDARI,
6331 #endif
6332                 '\0'
6333         };
6334         const char *reject = spclchars;
6335         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6336         int inquotes;
6337         size_t length;
6338         int startloc;
6339
6340         if (!(flags & EXP_VARTILDE)) {
6341                 reject += 2;
6342         } else if (flags & EXP_VARTILDE2) {
6343                 reject++;
6344         }
6345         inquotes = 0;
6346         length = 0;
6347         if (flags & EXP_TILDE) {
6348                 char *q;
6349
6350                 flags &= ~EXP_TILDE;
6351  tilde:
6352                 q = p;
6353                 if (*q == '~')
6354                         p = exptilde(p, q, flags);
6355         }
6356  start:
6357         startloc = expdest - (char *)stackblock();
6358         for (;;) {
6359                 unsigned char c;
6360
6361                 length += strcspn(p + length, reject);
6362                 c = p[length];
6363                 if (c) {
6364                         if (!(c & 0x80)
6365                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6366                         ) {
6367                                 /* c == '=' || c == ':' || c == CTLENDARI */
6368                                 length++;
6369                         }
6370                 }
6371                 if (length > 0) {
6372                         int newloc;
6373                         expdest = stack_nputstr(p, length, expdest);
6374                         newloc = expdest - (char *)stackblock();
6375                         if (breakall && !inquotes && newloc > startloc) {
6376                                 recordregion(startloc, newloc, 0);
6377                         }
6378                         startloc = newloc;
6379                 }
6380                 p += length + 1;
6381                 length = 0;
6382
6383                 switch (c) {
6384                 case '\0':
6385                         goto breakloop;
6386                 case '=':
6387                         if (flags & EXP_VARTILDE2) {
6388                                 p--;
6389                                 continue;
6390                         }
6391                         flags |= EXP_VARTILDE2;
6392                         reject++;
6393                         /* fall through */
6394                 case ':':
6395                         /*
6396                          * sort of a hack - expand tildes in variable
6397                          * assignments (after the first '=' and after ':'s).
6398                          */
6399                         if (*--p == '~') {
6400                                 goto tilde;
6401                         }
6402                         continue;
6403                 }
6404
6405                 switch (c) {
6406                 case CTLENDVAR: /* ??? */
6407                         goto breakloop;
6408                 case CTLQUOTEMARK:
6409                         inquotes ^= EXP_QUOTED;
6410                         /* "$@" syntax adherence hack */
6411                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6412                                 p = evalvar(p + 1, flags | inquotes, /* var_str_list: */ NULL) + 1;
6413                                 goto start;
6414                         }
6415  addquote:
6416                         if (flags & QUOTES_ESC) {
6417                                 p--;
6418                                 length++;
6419                                 startloc++;
6420                         }
6421                         break;
6422                 case CTLESC:
6423                         startloc++;
6424                         length++;
6425
6426                         /*
6427                          * Quoted parameter expansion pattern: remove quote
6428                          * unless inside inner quotes or we have a literal
6429                          * backslash.
6430                          */
6431                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6432                             EXP_QPAT && *p != '\\')
6433                                 break;
6434
6435                         goto addquote;
6436                 case CTLVAR:
6437                         TRACE(("argstr: evalvar('%s')\n", p));
6438                         p = evalvar(p, flags | inquotes, var_str_list);
6439                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6440                         goto start;
6441                 case CTLBACKQ:
6442                         expbackq(argbackq->n, flags | inquotes);
6443                         argbackq = argbackq->next;
6444                         goto start;
6445 #if ENABLE_FEATURE_SH_MATH
6446                 case CTLENDARI:
6447                         p--;
6448                         expari(flags | inquotes);
6449                         goto start;
6450 #endif
6451                 }
6452         }
6453  breakloop: ;
6454 }
6455
6456 static char *
6457 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6458                 char *pattern, int quotes, int zero)
6459 {
6460         char *loc, *loc2;
6461         char c;
6462
6463         loc = startp;
6464         loc2 = rmesc;
6465         do {
6466                 int match;
6467                 const char *s = loc2;
6468
6469                 c = *loc2;
6470                 if (zero) {
6471                         *loc2 = '\0';
6472                         s = rmesc;
6473                 }
6474                 match = pmatch(pattern, s);
6475
6476                 *loc2 = c;
6477                 if (match)
6478                         return loc;
6479                 if (quotes && (unsigned char)*loc == CTLESC)
6480                         loc++;
6481                 loc++;
6482                 loc2++;
6483         } while (c);
6484         return NULL;
6485 }
6486
6487 static char *
6488 scanright(char *startp, char *rmesc, char *rmescend,
6489                 char *pattern, int quotes, int match_at_start)
6490 {
6491 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6492         int try2optimize = match_at_start;
6493 #endif
6494         int esc = 0;
6495         char *loc;
6496         char *loc2;
6497
6498         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6499          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6500          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6501          * Logic:
6502          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6503          * and on each iteration they go back two/one char until they reach the beginning.
6504          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6505          */
6506         /* TODO: document in what other circumstances we are called. */
6507
6508         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6509                 int match;
6510                 char c = *loc2;
6511                 const char *s = loc2;
6512                 if (match_at_start) {
6513                         *loc2 = '\0';
6514                         s = rmesc;
6515                 }
6516                 match = pmatch(pattern, s);
6517                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6518                 *loc2 = c;
6519                 if (match)
6520                         return loc;
6521 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6522                 if (try2optimize) {
6523                         /* Maybe we can optimize this:
6524                          * if pattern ends with unescaped *, we can avoid checking
6525                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6526                          * it won't match truncated "raw_value_of_" strings too.
6527                          */
6528                         unsigned plen = strlen(pattern);
6529                         /* Does it end with "*"? */
6530                         if (plen != 0 && pattern[--plen] == '*') {
6531                                 /* "xxxx*" is not escaped */
6532                                 /* "xxx\*" is escaped */
6533                                 /* "xx\\*" is not escaped */
6534                                 /* "x\\\*" is escaped */
6535                                 int slashes = 0;
6536                                 while (plen != 0 && pattern[--plen] == '\\')
6537                                         slashes++;
6538                                 if (!(slashes & 1))
6539                                         break; /* ends with unescaped "*" */
6540                         }
6541                         try2optimize = 0;
6542                 }
6543 #endif
6544                 loc--;
6545                 if (quotes) {
6546                         if (--esc < 0) {
6547                                 esc = esclen(startp, loc);
6548                         }
6549                         if (esc % 2) {
6550                                 esc--;
6551                                 loc--;
6552                         }
6553                 }
6554         }
6555         return NULL;
6556 }
6557
6558 static void varunset(const char *, const char *, const char *, int) NORETURN;
6559 static void
6560 varunset(const char *end, const char *var, const char *umsg, int varflags)
6561 {
6562         const char *msg;
6563         const char *tail;
6564
6565         tail = nullstr;
6566         msg = "parameter not set";
6567         if (umsg) {
6568                 if ((unsigned char)*end == CTLENDVAR) {
6569                         if (varflags & VSNUL)
6570                                 tail = " or null";
6571                 } else {
6572                         msg = umsg;
6573                 }
6574         }
6575         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6576 }
6577
6578 static const char *
6579 subevalvar(char *p, char *varname, int strloc, int subtype,
6580                 int startloc, int varflags, int flag, struct strlist *var_str_list)
6581 {
6582         struct nodelist *saveargbackq = argbackq;
6583         int quotes = flag & QUOTES_ESC;
6584         char *startp;
6585         char *loc;
6586         char *rmesc, *rmescend;
6587         char *str;
6588         int amount, resetloc;
6589         IF_BASH_PATTERN_SUBST(int workloc;)
6590         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6591         int zero;
6592         char *(*scan)(char*, char*, char*, char*, int, int);
6593
6594         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6595         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6596
6597         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6598                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0),
6599                         var_str_list);
6600         STPUTC('\0', expdest);
6601         argbackq = saveargbackq;
6602         startp = (char *)stackblock() + startloc;
6603
6604         switch (subtype) {
6605         case VSASSIGN:
6606                 setvar0(varname, startp);
6607                 amount = startp - expdest;
6608                 STADJUST(amount, expdest);
6609                 return startp;
6610
6611         case VSQUESTION:
6612                 varunset(p, varname, startp, varflags);
6613                 /* NOTREACHED */
6614
6615 #if BASH_SUBSTR
6616         case VSSUBSTR: {
6617                 int pos, len, orig_len;
6618                 char *colon;
6619
6620                 loc = str = stackblock() + strloc;
6621
6622 # if !ENABLE_FEATURE_SH_MATH
6623 #  define ash_arith number
6624 # endif
6625                 /* Read POS in ${var:POS:LEN} */
6626                 colon = strchr(loc, ':');
6627                 if (colon) *colon = '\0';
6628                 pos = ash_arith(loc);
6629                 if (colon) *colon = ':';
6630
6631                 /* Read LEN in ${var:POS:LEN} */
6632                 len = str - startp - 1;
6633                 /* *loc != '\0', guaranteed by parser */
6634                 if (quotes) {
6635                         char *ptr;
6636
6637                         /* Adjust the length by the number of escapes */
6638                         for (ptr = startp; ptr < (str - 1); ptr++) {
6639                                 if ((unsigned char)*ptr == CTLESC) {
6640                                         len--;
6641                                         ptr++;
6642                                 }
6643                         }
6644                 }
6645                 orig_len = len;
6646                 if (*loc++ == ':') {
6647                         /* ${var::LEN} */
6648                         len = ash_arith(loc);
6649                 } else {
6650                         /* Skip POS in ${var:POS:LEN} */
6651                         len = orig_len;
6652                         while (*loc && *loc != ':') {
6653                                 loc++;
6654                         }
6655                         if (*loc++ == ':') {
6656                                 len = ash_arith(loc);
6657                         }
6658                 }
6659 #  undef ash_arith
6660
6661                 if (pos < 0) {
6662                         /* ${VAR:$((-n)):l} starts n chars from the end */
6663                         pos = orig_len + pos;
6664                 }
6665                 if ((unsigned)pos >= orig_len) {
6666                         /* apart from obvious ${VAR:999999:l},
6667                          * covers ${VAR:$((-9999999)):l} - result is ""
6668                          * (bash compat)
6669                          */
6670                         pos = 0;
6671                         len = 0;
6672                 }
6673                 if (len < 0) {
6674                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6675                         len = (orig_len - pos) + len;
6676                 }
6677                 if ((unsigned)len > (orig_len - pos))
6678                         len = orig_len - pos;
6679
6680                 for (str = startp; pos; str++, pos--) {
6681                         if (quotes && (unsigned char)*str == CTLESC)
6682                                 str++;
6683                 }
6684                 for (loc = startp; len; len--) {
6685                         if (quotes && (unsigned char)*str == CTLESC)
6686                                 *loc++ = *str++;
6687                         *loc++ = *str++;
6688                 }
6689                 *loc = '\0';
6690                 amount = loc - expdest;
6691                 STADJUST(amount, expdest);
6692                 return loc;
6693         }
6694 #endif /* BASH_SUBSTR */
6695         }
6696
6697         resetloc = expdest - (char *)stackblock();
6698
6699 #if BASH_PATTERN_SUBST
6700         /* We'll comeback here if we grow the stack while handling
6701          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6702          * stack will need rebasing, and we'll need to remove our work
6703          * areas each time
6704          */
6705  restart:
6706 #endif
6707
6708         amount = expdest - ((char *)stackblock() + resetloc);
6709         STADJUST(-amount, expdest);
6710         startp = (char *)stackblock() + startloc;
6711
6712         rmesc = startp;
6713         rmescend = (char *)stackblock() + strloc;
6714         if (quotes) {
6715                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6716                 if (rmesc != startp) {
6717                         rmescend = expdest;
6718                         startp = (char *)stackblock() + startloc;
6719                 }
6720         }
6721         rmescend--;
6722         str = (char *)stackblock() + strloc;
6723         /*
6724          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6725          * The result is a_\_z_c (not a\_\_z_c)!
6726          *
6727          * The search pattern and replace string treat backslashes differently!
6728          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6729          * and string.  It's only used on the first call.
6730          */
6731         preglob(str, IF_BASH_PATTERN_SUBST(
6732                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6733                         RMESCAPE_SLASH : ) 0);
6734
6735 #if BASH_PATTERN_SUBST
6736         workloc = expdest - (char *)stackblock();
6737         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6738                 int len;
6739                 char *idx, *end;
6740
6741                 if (!repl) {
6742                         repl = strchr(str, CTLESC);
6743                         if (repl)
6744                                 *repl++ = '\0';
6745                         else
6746                                 repl = nullstr;
6747                 }
6748                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6749
6750                 /* If there's no pattern to match, return the expansion unmolested */
6751                 if (str[0] == '\0')
6752                         return NULL;
6753
6754                 len = 0;
6755                 idx = startp;
6756                 end = str - 1;
6757                 while (idx < end) {
6758  try_to_match:
6759                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6760                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6761                         if (!loc) {
6762                                 /* No match, advance */
6763                                 char *restart_detect = stackblock();
6764  skip_matching:
6765                                 STPUTC(*idx, expdest);
6766                                 if (quotes && (unsigned char)*idx == CTLESC) {
6767                                         idx++;
6768                                         len++;
6769                                         STPUTC(*idx, expdest);
6770                                 }
6771                                 if (stackblock() != restart_detect)
6772                                         goto restart;
6773                                 idx++;
6774                                 len++;
6775                                 rmesc++;
6776                                 /* continue; - prone to quadratic behavior, smarter code: */
6777                                 if (idx >= end)
6778                                         break;
6779                                 if (str[0] == '*') {
6780                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6781                                          * it would never match "ong_string" etc, no point in trying.
6782                                          */
6783                                         goto skip_matching;
6784                                 }
6785                                 goto try_to_match;
6786                         }
6787
6788                         if (subtype == VSREPLACEALL) {
6789                                 while (idx < loc) {
6790                                         if (quotes && (unsigned char)*idx == CTLESC)
6791                                                 idx++;
6792                                         idx++;
6793                                         rmesc++;
6794                                 }
6795                         } else {
6796                                 idx = loc;
6797                         }
6798
6799                         //bb_error_msg("repl:'%s'", repl);
6800                         for (loc = (char*)repl; *loc; loc++) {
6801                                 char *restart_detect = stackblock();
6802                                 if (quotes && *loc == '\\') {
6803                                         STPUTC(CTLESC, expdest);
6804                                         len++;
6805                                 }
6806                                 STPUTC(*loc, expdest);
6807                                 if (stackblock() != restart_detect)
6808                                         goto restart;
6809                                 len++;
6810                         }
6811
6812                         if (subtype == VSREPLACE) {
6813                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6814                                 while (*idx) {
6815                                         char *restart_detect = stackblock();
6816                                         STPUTC(*idx, expdest);
6817                                         if (stackblock() != restart_detect)
6818                                                 goto restart;
6819                                         len++;
6820                                         idx++;
6821                                 }
6822                                 break;
6823                         }
6824                 }
6825
6826                 /* We've put the replaced text into a buffer at workloc, now
6827                  * move it to the right place and adjust the stack.
6828                  */
6829                 STPUTC('\0', expdest);
6830                 startp = (char *)stackblock() + startloc;
6831                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6832                 //bb_error_msg("startp:'%s'", startp);
6833                 amount = expdest - (startp + len);
6834                 STADJUST(-amount, expdest);
6835                 return startp;
6836         }
6837 #endif /* BASH_PATTERN_SUBST */
6838
6839         subtype -= VSTRIMRIGHT;
6840 #if DEBUG
6841         if (subtype < 0 || subtype > 7)
6842                 abort();
6843 #endif
6844         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6845         zero = subtype >> 1;
6846         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6847         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6848
6849         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6850         if (loc) {
6851                 if (zero) {
6852                         memmove(startp, loc, str - loc);
6853                         loc = startp + (str - loc) - 1;
6854                 }
6855                 *loc = '\0';
6856                 amount = loc - expdest;
6857                 STADJUST(amount, expdest);
6858         }
6859         return loc;
6860 }
6861
6862 /*
6863  * Add the value of a specialized variable to the stack string.
6864  * name parameter (examples):
6865  * ash -c 'echo $1'      name:'1='
6866  * ash -c 'echo $qwe'    name:'qwe='
6867  * ash -c 'echo $$'      name:'$='
6868  * ash -c 'echo ${$}'    name:'$='
6869  * ash -c 'echo ${$##q}' name:'$=q'
6870  * ash -c 'echo ${#$}'   name:'$='
6871  * note: examples with bad shell syntax:
6872  * ash -c 'echo ${#$1}'  name:'$=1'
6873  * ash -c 'echo ${#1#}'  name:'1=#'
6874  */
6875 static NOINLINE ssize_t
6876 varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int *quotedp)
6877 {
6878         const char *p;
6879         int num;
6880         int i;
6881         ssize_t len = 0;
6882         int sep;
6883         int quoted = *quotedp;
6884         int subtype = varflags & VSTYPE;
6885         int discard = subtype == VSPLUS || subtype == VSLENGTH;
6886         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
6887         int syntax;
6888
6889         sep = (flags & EXP_FULL) << CHAR_BIT;
6890         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6891
6892         switch (*name) {
6893         case '$':
6894                 num = rootpid;
6895                 goto numvar;
6896         case '?':
6897                 num = exitstatus;
6898                 goto numvar;
6899         case '#':
6900                 num = shellparam.nparam;
6901                 goto numvar;
6902         case '!':
6903                 num = backgndpid;
6904                 if (num == 0)
6905                         return -1;
6906  numvar:
6907                 len = cvtnum(num);
6908                 goto check_1char_name;
6909         case '-':
6910                 expdest = makestrspace(NOPTS, expdest);
6911                 for (i = NOPTS - 1; i >= 0; i--) {
6912                         if (optlist[i]) {
6913                                 USTPUTC(optletters(i), expdest);
6914                                 len++;
6915                         }
6916                 }
6917  check_1char_name:
6918 #if 0
6919                 /* handles cases similar to ${#$1} */
6920                 if (name[2] != '\0')
6921                         raise_error_syntax("bad substitution");
6922 #endif
6923                 break;
6924         case '@':
6925                 if (quoted && sep)
6926                         goto param;
6927                 /* fall through */
6928         case '*': {
6929                 char **ap;
6930                 char sepc;
6931
6932                 if (quoted)
6933                         sep = 0;
6934                 sep |= ifsset() ? ifsval()[0] : ' ';
6935  param:
6936                 sepc = sep;
6937                 *quotedp = !sepc;
6938                 ap = shellparam.p;
6939                 if (!ap)
6940                         return -1;
6941                 while ((p = *ap++) != NULL) {
6942                         len += strtodest(p, syntax, quotes);
6943
6944                         if (*ap && sep) {
6945                                 len++;
6946                                 memtodest(&sepc, 1, syntax, quotes);
6947                         }
6948                 }
6949                 break;
6950         } /* case '*' */
6951         case '0':
6952         case '1':
6953         case '2':
6954         case '3':
6955         case '4':
6956         case '5':
6957         case '6':
6958         case '7':
6959         case '8':
6960         case '9':
6961                 num = atoi(name); /* number(name) fails on ${N#str} etc */
6962                 if (num < 0 || num > shellparam.nparam)
6963                         return -1;
6964                 p = num ? shellparam.p[num - 1] : arg0;
6965                 goto value;
6966         default:
6967                 /* NB: name has form "VAR=..." */
6968
6969                 /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
6970                  * which should be considered before we check variables. */
6971                 if (var_str_list) {
6972                         unsigned name_len = (strchrnul(name, '=') - name) + 1;
6973                         p = NULL;
6974                         do {
6975                                 char *str, *eq;
6976                                 str = var_str_list->text;
6977                                 eq = strchr(str, '=');
6978                                 if (!eq) /* stop at first non-assignment */
6979                                         break;
6980                                 eq++;
6981                                 if (name_len == (unsigned)(eq - str)
6982                                  && strncmp(str, name, name_len) == 0
6983                                 ) {
6984                                         p = eq;
6985                                         /* goto value; - WRONG! */
6986                                         /* think "A=1 A=2 B=$A" */
6987                                 }
6988                                 var_str_list = var_str_list->next;
6989                         } while (var_str_list);
6990                         if (p)
6991                                 goto value;
6992                 }
6993                 p = lookupvar(name);
6994  value:
6995                 if (!p)
6996                         return -1;
6997
6998                 len = strtodest(p, syntax, quotes);
6999 #if ENABLE_UNICODE_SUPPORT
7000                 if (subtype == VSLENGTH && len > 0) {
7001                         reinit_unicode_for_ash();
7002                         if (unicode_status == UNICODE_ON) {
7003                                 STADJUST(-len, expdest);
7004                                 discard = 0;
7005                                 len = unicode_strlen(p);
7006                         }
7007                 }
7008 #endif
7009                 break;
7010         }
7011
7012         if (discard)
7013                 STADJUST(-len, expdest);
7014         return len;
7015 }
7016
7017 /*
7018  * Expand a variable, and return a pointer to the next character in the
7019  * input string.
7020  */
7021 static char *
7022 evalvar(char *p, int flag, struct strlist *var_str_list)
7023 {
7024         char varflags;
7025         char subtype;
7026         int quoted;
7027         char easy;
7028         char *var;
7029         int patloc;
7030         int startloc;
7031         ssize_t varlen;
7032
7033         varflags = (unsigned char) *p++;
7034         subtype = varflags & VSTYPE;
7035
7036         if (!subtype)
7037                 raise_error_syntax("bad substitution");
7038
7039         quoted = flag & EXP_QUOTED;
7040         var = p;
7041         easy = (!quoted || (*var == '@' && shellparam.nparam));
7042         startloc = expdest - (char *)stackblock();
7043         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7044
7045  again:
7046         varlen = varvalue(var, varflags, flag, var_str_list, &quoted);
7047         if (varflags & VSNUL)
7048                 varlen--;
7049
7050         if (subtype == VSPLUS) {
7051                 varlen = -1 - varlen;
7052                 goto vsplus;
7053         }
7054
7055         if (subtype == VSMINUS) {
7056  vsplus:
7057                 if (varlen < 0) {
7058                         argstr(
7059                                 p,
7060                                 flag | EXP_TILDE | EXP_WORD,
7061                                 var_str_list
7062                         );
7063                         goto end;
7064                 }
7065                 goto record;
7066         }
7067
7068         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7069                 if (varlen >= 0)
7070                         goto record;
7071
7072                 subevalvar(p, var, 0, subtype, startloc, varflags,
7073                            flag & ~QUOTES_ESC, var_str_list);
7074                 varflags &= ~VSNUL;
7075                 /*
7076                  * Remove any recorded regions beyond
7077                  * start of variable
7078                  */
7079                 removerecordregions(startloc);
7080                 goto again;
7081         }
7082
7083         if (varlen < 0 && uflag)
7084                 varunset(p, var, 0, 0);
7085
7086         if (subtype == VSLENGTH) {
7087                 cvtnum(varlen > 0 ? varlen : 0);
7088                 goto record;
7089         }
7090
7091         if (subtype == VSNORMAL) {
7092  record:
7093                 if (!easy)
7094                         goto end;
7095                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7096                 goto end;
7097         }
7098
7099 #if DEBUG
7100         switch (subtype) {
7101         case VSTRIMLEFT:
7102         case VSTRIMLEFTMAX:
7103         case VSTRIMRIGHT:
7104         case VSTRIMRIGHTMAX:
7105 #if BASH_SUBSTR
7106         case VSSUBSTR:
7107 #endif
7108 #if BASH_PATTERN_SUBST
7109         case VSREPLACE:
7110         case VSREPLACEALL:
7111 #endif
7112                 break;
7113         default:
7114                 abort();
7115         }
7116 #endif
7117
7118         if (varlen >= 0) {
7119                 /*
7120                  * Terminate the string and start recording the pattern
7121                  * right after it
7122                  */
7123                 STPUTC('\0', expdest);
7124                 patloc = expdest - (char *)stackblock();
7125                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7126                                 startloc, varflags, flag, var_str_list)) {
7127                         int amount = expdest - (
7128                                 (char *)stackblock() + patloc - 1
7129                         );
7130                         STADJUST(-amount, expdest);
7131                 }
7132                 /* Remove any recorded regions beyond start of variable */
7133                 removerecordregions(startloc);
7134                 goto record;
7135         }
7136
7137  end:
7138         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7139                 int nesting = 1;
7140                 for (;;) {
7141                         unsigned char c = *p++;
7142                         if (c == CTLESC)
7143                                 p++;
7144                         else if (c == CTLBACKQ) {
7145                                 if (varlen >= 0)
7146                                         argbackq = argbackq->next;
7147                         } else if (c == CTLVAR) {
7148                                 if ((*p++ & VSTYPE) != VSNORMAL)
7149                                         nesting++;
7150                         } else if (c == CTLENDVAR) {
7151                                 if (--nesting == 0)
7152                                         break;
7153                         }
7154                 }
7155         }
7156         return p;
7157 }
7158
7159 /*
7160  * Add a file name to the list.
7161  */
7162 static void
7163 addfname(const char *name)
7164 {
7165         struct strlist *sp;
7166
7167         sp = stzalloc(sizeof(*sp));
7168         sp->text = sstrdup(name);
7169         *exparg.lastp = sp;
7170         exparg.lastp = &sp->next;
7171 }
7172
7173 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7174 static int
7175 hasmeta(const char *p)
7176 {
7177         static const char chars[] ALIGN1 = {
7178                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7179         };
7180
7181         for (;;) {
7182                 p = strpbrk(p, chars);
7183                 if (!p)
7184                         break;
7185                 switch ((unsigned char) *p) {
7186                 case CTLQUOTEMARK:
7187                         for (;;) {
7188                                 p++;
7189                                 if (*p == CTLQUOTEMARK)
7190                                         break;
7191                                 if (*p == CTLESC)
7192                                         p++;
7193                                 if (*p == '\0') /* huh? */
7194                                         return 0;
7195                         }
7196                         break;
7197                 case '\\':
7198                 case CTLESC:
7199                         p++;
7200                         if (*p == '\0')
7201                                 return 0;
7202                         break;
7203                 case '[':
7204                         if (!strchr(p + 1, ']')) {
7205                                 /* It's not a properly closed [] pattern,
7206                                  * but other metas may follow. Continue checking.
7207                                  * my[file* _is_ globbed by bash
7208                                  * and matches filenames like "my[file1".
7209                                  */
7210                                 break;
7211                         }
7212                         /* fallthrough */
7213                 default:
7214                 /* case '*': */
7215                 /* case '?': */
7216                         return 1;
7217                 }
7218                 p++;
7219         }
7220
7221         return 0;
7222 }
7223
7224 /* If we want to use glob() from libc... */
7225 #if !ENABLE_ASH_INTERNAL_GLOB
7226
7227 /* Add the result of glob() to the list */
7228 static void
7229 addglob(const glob_t *pglob)
7230 {
7231         char **p = pglob->gl_pathv;
7232
7233         do {
7234                 addfname(*p);
7235         } while (*++p);
7236 }
7237 static void
7238 expandmeta(struct strlist *str /*, int flag*/)
7239 {
7240         /* TODO - EXP_REDIR */
7241
7242         while (str) {
7243                 char *p;
7244                 glob_t pglob;
7245                 int i;
7246
7247                 if (fflag)
7248                         goto nometa;
7249
7250                 if (!hasmeta(str->text))
7251                         goto nometa;
7252
7253                 INT_OFF;
7254                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7255 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7256 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7257 //
7258 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7259 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7260 // Which means you need to unescape the string, right? Not so fast:
7261 // if there _is_ a file named "file\?" (with backslash), it is returned
7262 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7263 // You DON'T KNOW by looking at the result whether you need to unescape it.
7264 //
7265 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7266 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7267 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7268 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7269 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7270 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7271                 i = glob(p, 0, NULL, &pglob);
7272                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7273                 if (p != str->text)
7274                         free(p);
7275                 switch (i) {
7276                 case 0:
7277 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7278                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7279                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7280                                 goto nometa2;
7281 #endif
7282                         addglob(&pglob);
7283                         globfree(&pglob);
7284                         INT_ON;
7285                         break;
7286                 case GLOB_NOMATCH:
7287  //nometa2:
7288                         globfree(&pglob);
7289                         INT_ON;
7290  nometa:
7291                         *exparg.lastp = str;
7292                         rmescapes(str->text, 0);
7293                         exparg.lastp = &str->next;
7294                         break;
7295                 default:        /* GLOB_NOSPACE */
7296                         globfree(&pglob);
7297                         INT_ON;
7298                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7299                 }
7300                 str = str->next;
7301         }
7302 }
7303
7304 #else
7305 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7306
7307 /*
7308  * Do metacharacter (i.e. *, ?, [...]) expansion.
7309  */
7310 static void
7311 expmeta(char *expdir, char *enddir, char *name)
7312 {
7313         char *p;
7314         const char *cp;
7315         char *start;
7316         char *endname;
7317         int metaflag;
7318         struct stat statb;
7319         DIR *dirp;
7320         struct dirent *dp;
7321         int atend;
7322         int matchdot;
7323         int esc;
7324
7325         metaflag = 0;
7326         start = name;
7327         for (p = name; esc = 0, *p; p += esc + 1) {
7328                 if (*p == '*' || *p == '?')
7329                         metaflag = 1;
7330                 else if (*p == '[') {
7331                         char *q = p + 1;
7332                         if (*q == '!')
7333                                 q++;
7334                         for (;;) {
7335                                 if (*q == '\\')
7336                                         q++;
7337                                 if (*q == '/' || *q == '\0')
7338                                         break;
7339                                 if (*++q == ']') {
7340                                         metaflag = 1;
7341                                         break;
7342                                 }
7343                         }
7344                 } else {
7345                         if (*p == '\\')
7346                                 esc++;
7347                         if (p[esc] == '/') {
7348                                 if (metaflag)
7349                                         break;
7350                                 start = p + esc + 1;
7351                         }
7352                 }
7353         }
7354         if (metaflag == 0) {    /* we've reached the end of the file name */
7355                 if (enddir != expdir)
7356                         metaflag++;
7357                 p = name;
7358                 do {
7359                         if (*p == '\\')
7360                                 p++;
7361                         *enddir++ = *p;
7362                 } while (*p++);
7363                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7364                         addfname(expdir);
7365                 return;
7366         }
7367         endname = p;
7368         if (name < start) {
7369                 p = name;
7370                 do {
7371                         if (*p == '\\')
7372                                 p++;
7373                         *enddir++ = *p++;
7374                 } while (p < start);
7375         }
7376         if (enddir == expdir) {
7377                 cp = ".";
7378         } else if (enddir == expdir + 1 && *expdir == '/') {
7379                 cp = "/";
7380         } else {
7381                 cp = expdir;
7382                 enddir[-1] = '\0';
7383         }
7384         dirp = opendir(cp);
7385         if (dirp == NULL)
7386                 return;
7387         if (enddir != expdir)
7388                 enddir[-1] = '/';
7389         if (*endname == 0) {
7390                 atend = 1;
7391         } else {
7392                 atend = 0;
7393                 *endname = '\0';
7394                 endname += esc + 1;
7395         }
7396         matchdot = 0;
7397         p = start;
7398         if (*p == '\\')
7399                 p++;
7400         if (*p == '.')
7401                 matchdot++;
7402         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7403                 if (dp->d_name[0] == '.' && !matchdot)
7404                         continue;
7405                 if (pmatch(start, dp->d_name)) {
7406                         if (atend) {
7407                                 strcpy(enddir, dp->d_name);
7408                                 addfname(expdir);
7409                         } else {
7410                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7411                                         continue;
7412                                 p[-1] = '/';
7413                                 expmeta(expdir, p, endname);
7414                         }
7415                 }
7416         }
7417         closedir(dirp);
7418         if (!atend)
7419                 endname[-esc - 1] = esc ? '\\' : '/';
7420 }
7421
7422 static struct strlist *
7423 msort(struct strlist *list, int len)
7424 {
7425         struct strlist *p, *q = NULL;
7426         struct strlist **lpp;
7427         int half;
7428         int n;
7429
7430         if (len <= 1)
7431                 return list;
7432         half = len >> 1;
7433         p = list;
7434         for (n = half; --n >= 0;) {
7435                 q = p;
7436                 p = p->next;
7437         }
7438         q->next = NULL;                 /* terminate first half of list */
7439         q = msort(list, half);          /* sort first half of list */
7440         p = msort(p, len - half);               /* sort second half */
7441         lpp = &list;
7442         for (;;) {
7443 #if ENABLE_LOCALE_SUPPORT
7444                 if (strcoll(p->text, q->text) < 0)
7445 #else
7446                 if (strcmp(p->text, q->text) < 0)
7447 #endif
7448                                                 {
7449                         *lpp = p;
7450                         lpp = &p->next;
7451                         p = *lpp;
7452                         if (p == NULL) {
7453                                 *lpp = q;
7454                                 break;
7455                         }
7456                 } else {
7457                         *lpp = q;
7458                         lpp = &q->next;
7459                         q = *lpp;
7460                         if (q == NULL) {
7461                                 *lpp = p;
7462                                 break;
7463                         }
7464                 }
7465         }
7466         return list;
7467 }
7468
7469 /*
7470  * Sort the results of file name expansion.  It calculates the number of
7471  * strings to sort and then calls msort (short for merge sort) to do the
7472  * work.
7473  */
7474 static struct strlist *
7475 expsort(struct strlist *str)
7476 {
7477         int len;
7478         struct strlist *sp;
7479
7480         len = 0;
7481         for (sp = str; sp; sp = sp->next)
7482                 len++;
7483         return msort(str, len);
7484 }
7485
7486 static void
7487 expandmeta(struct strlist *str /*, int flag*/)
7488 {
7489         /* TODO - EXP_REDIR */
7490
7491         while (str) {
7492                 char *expdir;
7493                 struct strlist **savelastp;
7494                 struct strlist *sp;
7495                 char *p;
7496
7497                 if (fflag)
7498                         goto nometa;
7499                 if (!hasmeta(str->text))
7500                         goto nometa;
7501                 savelastp = exparg.lastp;
7502
7503                 INT_OFF;
7504                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7505                 {
7506                         int i = strlen(str->text);
7507 //BUGGY estimation of how long expanded name can be
7508                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7509                 }
7510                 expmeta(expdir, expdir, p);
7511                 free(expdir);
7512                 if (p != str->text)
7513                         free(p);
7514                 INT_ON;
7515                 if (exparg.lastp == savelastp) {
7516                         /*
7517                          * no matches
7518                          */
7519  nometa:
7520                         *exparg.lastp = str;
7521                         rmescapes(str->text, 0);
7522                         exparg.lastp = &str->next;
7523                 } else {
7524                         *exparg.lastp = NULL;
7525                         *savelastp = sp = expsort(*savelastp);
7526                         while (sp->next != NULL)
7527                                 sp = sp->next;
7528                         exparg.lastp = &sp->next;
7529                 }
7530                 str = str->next;
7531         }
7532 }
7533 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7534
7535 /*
7536  * Perform variable substitution and command substitution on an argument,
7537  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7538  * perform splitting and file name expansion.  When arglist is NULL, perform
7539  * here document expansion.
7540  */
7541 static void
7542 expandarg(union node *arg, struct arglist *arglist, int flag)
7543 {
7544         struct strlist *sp;
7545         char *p;
7546
7547         argbackq = arg->narg.backquote;
7548         STARTSTACKSTR(expdest);
7549         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7550         argstr(arg->narg.text, flag,
7551                         /* var_str_list: */ arglist ? arglist->list : NULL);
7552         p = _STPUTC('\0', expdest);
7553         expdest = p - 1;
7554         if (arglist == NULL) {
7555                 /* here document expanded */
7556                 goto out;
7557         }
7558         p = grabstackstr(p);
7559         TRACE(("expandarg: p:'%s'\n", p));
7560         exparg.lastp = &exparg.list;
7561         /*
7562          * TODO - EXP_REDIR
7563          */
7564         if (flag & EXP_FULL) {
7565                 ifsbreakup(p, &exparg);
7566                 *exparg.lastp = NULL;
7567                 exparg.lastp = &exparg.list;
7568                 expandmeta(exparg.list /*, flag*/);
7569         } else {
7570                 sp = stzalloc(sizeof(*sp));
7571                 sp->text = p;
7572                 *exparg.lastp = sp;
7573                 exparg.lastp = &sp->next;
7574         }
7575         *exparg.lastp = NULL;
7576         if (exparg.list) {
7577                 *arglist->lastp = exparg.list;
7578                 arglist->lastp = exparg.lastp;
7579         }
7580
7581  out:
7582         ifsfree();
7583 }
7584
7585 /*
7586  * Expand shell variables and backquotes inside a here document.
7587  */
7588 static void
7589 expandhere(union node *arg, int fd)
7590 {
7591         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7592         full_write(fd, stackblock(), expdest - (char *)stackblock());
7593 }
7594
7595 /*
7596  * Returns true if the pattern matches the string.
7597  */
7598 static int
7599 patmatch(char *pattern, const char *string)
7600 {
7601         char *p = preglob(pattern, 0);
7602         //bb_error_msg("fnmatch(pattern:'%s',str:'%s')", p, string);
7603         return pmatch(p, string);
7604 }
7605
7606 /*
7607  * See if a pattern matches in a case statement.
7608  */
7609 static int
7610 casematch(union node *pattern, char *val)
7611 {
7612         struct stackmark smark;
7613         int result;
7614
7615         setstackmark(&smark);
7616         argbackq = pattern->narg.backquote;
7617         STARTSTACKSTR(expdest);
7618         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
7619                         /* var_str_list: */ NULL);
7620         STACKSTRNUL(expdest);
7621         ifsfree();
7622         result = patmatch(stackblock(), val);
7623         popstackmark(&smark);
7624         return result;
7625 }
7626
7627
7628 /* ============ find_command */
7629
7630 struct builtincmd {
7631         const char *name;
7632         int (*builtin)(int, char **) FAST_FUNC;
7633         /* unsigned flags; */
7634 };
7635 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7636 /* "regular" builtins always take precedence over commands,
7637  * regardless of PATH=....%builtin... position */
7638 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7639 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7640
7641 struct cmdentry {
7642         smallint cmdtype;       /* CMDxxx */
7643         union param {
7644                 int index;
7645                 /* index >= 0 for commands without path (slashes) */
7646                 /* (TODO: what exactly does the value mean? PATH position?) */
7647                 /* index == -1 for commands with slashes */
7648                 /* index == (-2 - applet_no) for NOFORK applets */
7649                 const struct builtincmd *cmd;
7650                 struct funcnode *func;
7651         } u;
7652 };
7653 /* values of cmdtype */
7654 #define CMDUNKNOWN      -1      /* no entry in table for command */
7655 #define CMDNORMAL       0       /* command is an executable program */
7656 #define CMDFUNCTION     1       /* command is a shell function */
7657 #define CMDBUILTIN      2       /* command is a shell builtin */
7658
7659 /* action to find_command() */
7660 #define DO_ERR          0x01    /* prints errors */
7661 #define DO_ABS          0x02    /* checks absolute paths */
7662 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7663 #define DO_ALTPATH      0x08    /* using alternate path */
7664 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7665
7666 static void find_command(char *, struct cmdentry *, int, const char *);
7667
7668
7669 /* ============ Hashing commands */
7670
7671 /*
7672  * When commands are first encountered, they are entered in a hash table.
7673  * This ensures that a full path search will not have to be done for them
7674  * on each invocation.
7675  *
7676  * We should investigate converting to a linear search, even though that
7677  * would make the command name "hash" a misnomer.
7678  */
7679
7680 struct tblentry {
7681         struct tblentry *next;  /* next entry in hash chain */
7682         union param param;      /* definition of builtin function */
7683         smallint cmdtype;       /* CMDxxx */
7684         char rehash;            /* if set, cd done since entry created */
7685         char cmdname[1];        /* name of command */
7686 };
7687
7688 static struct tblentry **cmdtable;
7689 #define INIT_G_cmdtable() do { \
7690         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7691 } while (0)
7692
7693 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7694
7695
7696 static void
7697 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7698 {
7699 #if ENABLE_FEATURE_SH_STANDALONE
7700         if (applet_no >= 0) {
7701                 if (APPLET_IS_NOEXEC(applet_no)) {
7702                         clearenv();
7703                         while (*envp)
7704                                 putenv(*envp++);
7705                         popredir(/*drop:*/ 1, /*restore:*/ 0);
7706                         run_applet_no_and_exit(applet_no, cmd, argv);
7707                 }
7708                 /* re-exec ourselves with the new arguments */
7709                 execve(bb_busybox_exec_path, argv, envp);
7710                 /* If they called chroot or otherwise made the binary no longer
7711                  * executable, fall through */
7712         }
7713 #endif
7714
7715  repeat:
7716 #ifdef SYSV
7717         do {
7718                 execve(cmd, argv, envp);
7719         } while (errno == EINTR);
7720 #else
7721         execve(cmd, argv, envp);
7722 #endif
7723         if (cmd != (char*) bb_busybox_exec_path && errno == ENOEXEC) {
7724                 /* Run "cmd" as a shell script:
7725                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7726                  * "If the execve() function fails with ENOEXEC, the shell
7727                  * shall execute a command equivalent to having a shell invoked
7728                  * with the command name as its first operand,
7729                  * with any remaining arguments passed to the new shell"
7730                  *
7731                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7732                  * just call ourselves.
7733                  *
7734                  * Note that bash reads ~80 chars of the file, and if it sees
7735                  * a zero byte before it sees newline, it doesn't try to
7736                  * interpret it, but fails with "cannot execute binary file"
7737                  * message and exit code 126. For one, this prevents attempts
7738                  * to interpret foreign ELF binaries as shell scripts.
7739                  */
7740                 argv[0] = cmd;
7741                 cmd = (char*) bb_busybox_exec_path;
7742                 /* NB: this is only possible because all callers of shellexec()
7743                  * ensure that the argv[-1] slot exists!
7744                  */
7745                 argv--;
7746                 argv[0] = (char*) "ash";
7747                 goto repeat;
7748         }
7749 }
7750
7751 /*
7752  * Exec a program.  Never returns.  If you change this routine, you may
7753  * have to change the find_command routine as well.
7754  * argv[-1] must exist and be writable! See tryexec() for why.
7755  */
7756 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7757 static void shellexec(char *prog, char **argv, const char *path, int idx)
7758 {
7759         char *cmdname;
7760         int e;
7761         char **envp;
7762         int exerrno;
7763         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7764
7765         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7766         if (strchr(prog, '/') != NULL
7767 #if ENABLE_FEATURE_SH_STANDALONE
7768          || (applet_no = find_applet_by_name(prog)) >= 0
7769 #endif
7770         ) {
7771                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7772                 if (applet_no >= 0) {
7773                         /* We tried execing ourself, but it didn't work.
7774                          * Maybe /proc/self/exe doesn't exist?
7775                          * Try $PATH search.
7776                          */
7777                         goto try_PATH;
7778                 }
7779                 e = errno;
7780         } else {
7781  try_PATH:
7782                 e = ENOENT;
7783                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7784                         if (--idx < 0 && pathopt == NULL) {
7785                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7786                                 if (errno != ENOENT && errno != ENOTDIR)
7787                                         e = errno;
7788                         }
7789                         stunalloc(cmdname);
7790                 }
7791         }
7792
7793         /* Map to POSIX errors */
7794         switch (e) {
7795         case EACCES:
7796                 exerrno = 126;
7797                 break;
7798         case ENOENT:
7799                 exerrno = 127;
7800                 break;
7801         default:
7802                 exerrno = 2;
7803                 break;
7804         }
7805         exitstatus = exerrno;
7806         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7807                 prog, e, suppress_int));
7808         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7809         /* NOTREACHED */
7810 }
7811
7812 static void
7813 printentry(struct tblentry *cmdp)
7814 {
7815         int idx;
7816         const char *path;
7817         char *name;
7818
7819         idx = cmdp->param.index;
7820         path = pathval();
7821         do {
7822                 name = path_advance(&path, cmdp->cmdname);
7823                 stunalloc(name);
7824         } while (--idx >= 0);
7825         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7826 }
7827
7828 /*
7829  * Clear out command entries.  The argument specifies the first entry in
7830  * PATH which has changed.
7831  */
7832 static void
7833 clearcmdentry(int firstchange)
7834 {
7835         struct tblentry **tblp;
7836         struct tblentry **pp;
7837         struct tblentry *cmdp;
7838
7839         INT_OFF;
7840         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7841                 pp = tblp;
7842                 while ((cmdp = *pp) != NULL) {
7843                         if ((cmdp->cmdtype == CMDNORMAL &&
7844                              cmdp->param.index >= firstchange)
7845                          || (cmdp->cmdtype == CMDBUILTIN &&
7846                              builtinloc >= firstchange)
7847                         ) {
7848                                 *pp = cmdp->next;
7849                                 free(cmdp);
7850                         } else {
7851                                 pp = &cmdp->next;
7852                         }
7853                 }
7854         }
7855         INT_ON;
7856 }
7857
7858 /*
7859  * Locate a command in the command hash table.  If "add" is nonzero,
7860  * add the command to the table if it is not already present.  The
7861  * variable "lastcmdentry" is set to point to the address of the link
7862  * pointing to the entry, so that delete_cmd_entry can delete the
7863  * entry.
7864  *
7865  * Interrupts must be off if called with add != 0.
7866  */
7867 static struct tblentry **lastcmdentry;
7868
7869 static struct tblentry *
7870 cmdlookup(const char *name, int add)
7871 {
7872         unsigned int hashval;
7873         const char *p;
7874         struct tblentry *cmdp;
7875         struct tblentry **pp;
7876
7877         p = name;
7878         hashval = (unsigned char)*p << 4;
7879         while (*p)
7880                 hashval += (unsigned char)*p++;
7881         hashval &= 0x7FFF;
7882         pp = &cmdtable[hashval % CMDTABLESIZE];
7883         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7884                 if (strcmp(cmdp->cmdname, name) == 0)
7885                         break;
7886                 pp = &cmdp->next;
7887         }
7888         if (add && cmdp == NULL) {
7889                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7890                                 + strlen(name)
7891                                 /* + 1 - already done because
7892                                  * tblentry::cmdname is char[1] */);
7893                 /*cmdp->next = NULL; - ckzalloc did it */
7894                 cmdp->cmdtype = CMDUNKNOWN;
7895                 strcpy(cmdp->cmdname, name);
7896         }
7897         lastcmdentry = pp;
7898         return cmdp;
7899 }
7900
7901 /*
7902  * Delete the command entry returned on the last lookup.
7903  */
7904 static void
7905 delete_cmd_entry(void)
7906 {
7907         struct tblentry *cmdp;
7908
7909         INT_OFF;
7910         cmdp = *lastcmdentry;
7911         *lastcmdentry = cmdp->next;
7912         if (cmdp->cmdtype == CMDFUNCTION)
7913                 freefunc(cmdp->param.func);
7914         free(cmdp);
7915         INT_ON;
7916 }
7917
7918 /*
7919  * Add a new command entry, replacing any existing command entry for
7920  * the same name - except special builtins.
7921  */
7922 static void
7923 addcmdentry(char *name, struct cmdentry *entry)
7924 {
7925         struct tblentry *cmdp;
7926
7927         cmdp = cmdlookup(name, 1);
7928         if (cmdp->cmdtype == CMDFUNCTION) {
7929                 freefunc(cmdp->param.func);
7930         }
7931         cmdp->cmdtype = entry->cmdtype;
7932         cmdp->param = entry->u;
7933         cmdp->rehash = 0;
7934 }
7935
7936 static int FAST_FUNC
7937 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7938 {
7939         struct tblentry **pp;
7940         struct tblentry *cmdp;
7941         int c;
7942         struct cmdentry entry;
7943         char *name;
7944
7945         if (nextopt("r") != '\0') {
7946                 clearcmdentry(0);
7947                 return 0;
7948         }
7949
7950         if (*argptr == NULL) {
7951                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7952                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7953                                 if (cmdp->cmdtype == CMDNORMAL)
7954                                         printentry(cmdp);
7955                         }
7956                 }
7957                 return 0;
7958         }
7959
7960         c = 0;
7961         while ((name = *argptr) != NULL) {
7962                 cmdp = cmdlookup(name, 0);
7963                 if (cmdp != NULL
7964                  && (cmdp->cmdtype == CMDNORMAL
7965                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7966                 ) {
7967                         delete_cmd_entry();
7968                 }
7969                 find_command(name, &entry, DO_ERR, pathval());
7970                 if (entry.cmdtype == CMDUNKNOWN)
7971                         c = 1;
7972                 argptr++;
7973         }
7974         return c;
7975 }
7976
7977 /*
7978  * Called when a cd is done.  Marks all commands so the next time they
7979  * are executed they will be rehashed.
7980  */
7981 static void
7982 hashcd(void)
7983 {
7984         struct tblentry **pp;
7985         struct tblentry *cmdp;
7986
7987         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7988                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7989                         if (cmdp->cmdtype == CMDNORMAL
7990                          || (cmdp->cmdtype == CMDBUILTIN
7991                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7992                              && builtinloc > 0)
7993                         ) {
7994                                 cmdp->rehash = 1;
7995                         }
7996                 }
7997         }
7998 }
7999
8000 /*
8001  * Fix command hash table when PATH changed.
8002  * Called before PATH is changed.  The argument is the new value of PATH;
8003  * pathval() still returns the old value at this point.
8004  * Called with interrupts off.
8005  */
8006 static void FAST_FUNC
8007 changepath(const char *new)
8008 {
8009         const char *old;
8010         int firstchange;
8011         int idx;
8012         int idx_bltin;
8013
8014         old = pathval();
8015         firstchange = 9999;     /* assume no change */
8016         idx = 0;
8017         idx_bltin = -1;
8018         for (;;) {
8019                 if (*old != *new) {
8020                         firstchange = idx;
8021                         if ((*old == '\0' && *new == ':')
8022                          || (*old == ':' && *new == '\0')
8023                         ) {
8024                                 firstchange++;
8025                         }
8026                         old = new;      /* ignore subsequent differences */
8027                 }
8028                 if (*new == '\0')
8029                         break;
8030                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8031                         idx_bltin = idx;
8032                 if (*new == ':')
8033                         idx++;
8034                 new++;
8035                 old++;
8036         }
8037         if (builtinloc < 0 && idx_bltin >= 0)
8038                 builtinloc = idx_bltin;             /* zap builtins */
8039         if (builtinloc >= 0 && idx_bltin < 0)
8040                 firstchange = 0;
8041         clearcmdentry(firstchange);
8042         builtinloc = idx_bltin;
8043 }
8044 enum {
8045         TEOF,
8046         TNL,
8047         TREDIR,
8048         TWORD,
8049         TSEMI,
8050         TBACKGND,
8051         TAND,
8052         TOR,
8053         TPIPE,
8054         TLP,
8055         TRP,
8056         TENDCASE,
8057         TENDBQUOTE,
8058         TNOT,
8059         TCASE,
8060         TDO,
8061         TDONE,
8062         TELIF,
8063         TELSE,
8064         TESAC,
8065         TFI,
8066         TFOR,
8067 #if BASH_FUNCTION
8068         TFUNCTION,
8069 #endif
8070         TIF,
8071         TIN,
8072         TTHEN,
8073         TUNTIL,
8074         TWHILE,
8075         TBEGIN,
8076         TEND
8077 };
8078 typedef smallint token_id_t;
8079
8080 /* Nth bit indicates if token marks the end of a list */
8081 enum {
8082         tokendlist = 0
8083         /*  0 */ | (1u << TEOF)
8084         /*  1 */ | (0u << TNL)
8085         /*  2 */ | (0u << TREDIR)
8086         /*  3 */ | (0u << TWORD)
8087         /*  4 */ | (0u << TSEMI)
8088         /*  5 */ | (0u << TBACKGND)
8089         /*  6 */ | (0u << TAND)
8090         /*  7 */ | (0u << TOR)
8091         /*  8 */ | (0u << TPIPE)
8092         /*  9 */ | (0u << TLP)
8093         /* 10 */ | (1u << TRP)
8094         /* 11 */ | (1u << TENDCASE)
8095         /* 12 */ | (1u << TENDBQUOTE)
8096         /* 13 */ | (0u << TNOT)
8097         /* 14 */ | (0u << TCASE)
8098         /* 15 */ | (1u << TDO)
8099         /* 16 */ | (1u << TDONE)
8100         /* 17 */ | (1u << TELIF)
8101         /* 18 */ | (1u << TELSE)
8102         /* 19 */ | (1u << TESAC)
8103         /* 20 */ | (1u << TFI)
8104         /* 21 */ | (0u << TFOR)
8105 #if BASH_FUNCTION
8106         /* 22 */ | (0u << TFUNCTION)
8107 #endif
8108         /* 23 */ | (0u << TIF)
8109         /* 24 */ | (0u << TIN)
8110         /* 25 */ | (1u << TTHEN)
8111         /* 26 */ | (0u << TUNTIL)
8112         /* 27 */ | (0u << TWHILE)
8113         /* 28 */ | (0u << TBEGIN)
8114         /* 29 */ | (1u << TEND)
8115         , /* thus far 29 bits used */
8116 };
8117
8118 static const char *const tokname_array[] = {
8119         "end of file",
8120         "newline",
8121         "redirection",
8122         "word",
8123         ";",
8124         "&",
8125         "&&",
8126         "||",
8127         "|",
8128         "(",
8129         ")",
8130         ";;",
8131         "`",
8132 #define KWDOFFSET 13
8133         /* the following are keywords */
8134         "!",
8135         "case",
8136         "do",
8137         "done",
8138         "elif",
8139         "else",
8140         "esac",
8141         "fi",
8142         "for",
8143 #if BASH_FUNCTION
8144         "function",
8145 #endif
8146         "if",
8147         "in",
8148         "then",
8149         "until",
8150         "while",
8151         "{",
8152         "}",
8153 };
8154
8155 /* Wrapper around strcmp for qsort/bsearch/... */
8156 static int
8157 pstrcmp(const void *a, const void *b)
8158 {
8159         return strcmp((char*)a, *(char**)b);
8160 }
8161
8162 static const char *const *
8163 findkwd(const char *s)
8164 {
8165         return bsearch(s, tokname_array + KWDOFFSET,
8166                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8167                         sizeof(tokname_array[0]), pstrcmp);
8168 }
8169
8170 /*
8171  * Locate and print what a word is...
8172  */
8173 static int
8174 describe_command(char *command, const char *path, int describe_command_verbose)
8175 {
8176         struct cmdentry entry;
8177 #if ENABLE_ASH_ALIAS
8178         const struct alias *ap;
8179 #endif
8180
8181         path = path ? path : pathval();
8182
8183         if (describe_command_verbose) {
8184                 out1str(command);
8185         }
8186
8187         /* First look at the keywords */
8188         if (findkwd(command)) {
8189                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8190                 goto out;
8191         }
8192
8193 #if ENABLE_ASH_ALIAS
8194         /* Then look at the aliases */
8195         ap = lookupalias(command, 0);
8196         if (ap != NULL) {
8197                 if (!describe_command_verbose) {
8198                         out1str("alias ");
8199                         printalias(ap);
8200                         return 0;
8201                 }
8202                 out1fmt(" is an alias for %s", ap->val);
8203                 goto out;
8204         }
8205 #endif
8206         /* Brute force */
8207         find_command(command, &entry, DO_ABS, path);
8208
8209         switch (entry.cmdtype) {
8210         case CMDNORMAL: {
8211                 int j = entry.u.index;
8212                 char *p;
8213                 if (j < 0) {
8214                         p = command;
8215                 } else {
8216                         do {
8217                                 p = path_advance(&path, command);
8218                                 stunalloc(p);
8219                         } while (--j >= 0);
8220                 }
8221                 if (describe_command_verbose) {
8222                         out1fmt(" is %s", p);
8223                 } else {
8224                         out1str(p);
8225                 }
8226                 break;
8227         }
8228
8229         case CMDFUNCTION:
8230                 if (describe_command_verbose) {
8231                         out1str(" is a shell function");
8232                 } else {
8233                         out1str(command);
8234                 }
8235                 break;
8236
8237         case CMDBUILTIN:
8238                 if (describe_command_verbose) {
8239                         out1fmt(" is a %sshell builtin",
8240                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8241                                         "special " : nullstr
8242                         );
8243                 } else {
8244                         out1str(command);
8245                 }
8246                 break;
8247
8248         default:
8249                 if (describe_command_verbose) {
8250                         out1str(": not found\n");
8251                 }
8252                 return 127;
8253         }
8254  out:
8255         out1str("\n");
8256         return 0;
8257 }
8258
8259 static int FAST_FUNC
8260 typecmd(int argc UNUSED_PARAM, char **argv)
8261 {
8262         int i = 1;
8263         int err = 0;
8264         int verbose = 1;
8265
8266         /* type -p ... ? (we don't bother checking for 'p') */
8267         if (argv[1] && argv[1][0] == '-') {
8268                 i++;
8269                 verbose = 0;
8270         }
8271         while (argv[i]) {
8272                 err |= describe_command(argv[i++], NULL, verbose);
8273         }
8274         return err;
8275 }
8276
8277 #if ENABLE_ASH_CMDCMD
8278 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8279 static char **
8280 parse_command_args(char **argv, const char **path)
8281 {
8282         char *cp, c;
8283
8284         for (;;) {
8285                 cp = *++argv;
8286                 if (!cp)
8287                         return NULL;
8288                 if (*cp++ != '-')
8289                         break;
8290                 c = *cp++;
8291                 if (!c)
8292                         break;
8293                 if (c == '-' && !*cp) {
8294                         if (!*++argv)
8295                                 return NULL;
8296                         break;
8297                 }
8298                 do {
8299                         switch (c) {
8300                         case 'p':
8301                                 *path = bb_default_path;
8302                                 break;
8303                         default:
8304                                 /* run 'typecmd' for other options */
8305                                 return NULL;
8306                         }
8307                         c = *cp++;
8308                 } while (c);
8309         }
8310         return argv;
8311 }
8312
8313 static int FAST_FUNC
8314 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8315 {
8316         char *cmd;
8317         int c;
8318         enum {
8319                 VERIFY_BRIEF = 1,
8320                 VERIFY_VERBOSE = 2,
8321         } verify = 0;
8322         const char *path = NULL;
8323
8324         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8325          * never reaches this function.
8326          */
8327
8328         while ((c = nextopt("pvV")) != '\0')
8329                 if (c == 'V')
8330                         verify |= VERIFY_VERBOSE;
8331                 else if (c == 'v')
8332                         /*verify |= VERIFY_BRIEF*/;
8333 #if DEBUG
8334                 else if (c != 'p')
8335                         abort();
8336 #endif
8337                 else
8338                         path = bb_default_path;
8339
8340         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8341         cmd = *argptr;
8342         if (/*verify && */ cmd)
8343                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8344
8345         return 0;
8346 }
8347 #endif
8348
8349
8350 /*static int funcblocksize;     // size of structures in function */
8351 /*static int funcstringsize;    // size of strings in node */
8352 static void *funcblock;         /* block to allocate function from */
8353 static char *funcstring_end;    /* end of block to allocate strings from */
8354
8355 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8356         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8357         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8358         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8359         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8360         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8361         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8362         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8363         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8364         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8365         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8366         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8367         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8368         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8369         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8370         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8371         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8372         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8373 #if BASH_REDIR_OUTPUT
8374         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8375 #endif
8376         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8377         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8378         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8379         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8380         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8381         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8382         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8383         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8384         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8385 };
8386
8387 static int calcsize(int funcblocksize, union node *n);
8388
8389 static int
8390 sizenodelist(int funcblocksize, struct nodelist *lp)
8391 {
8392         while (lp) {
8393                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8394                 funcblocksize = calcsize(funcblocksize, lp->n);
8395                 lp = lp->next;
8396         }
8397         return funcblocksize;
8398 }
8399
8400 static int
8401 calcsize(int funcblocksize, union node *n)
8402 {
8403         if (n == NULL)
8404                 return funcblocksize;
8405         funcblocksize += nodesize[n->type];
8406         switch (n->type) {
8407         case NCMD:
8408                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8409                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8410                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8411                 break;
8412         case NPIPE:
8413                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8414                 break;
8415         case NREDIR:
8416         case NBACKGND:
8417         case NSUBSHELL:
8418                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8419                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8420                 break;
8421         case NAND:
8422         case NOR:
8423         case NSEMI:
8424         case NWHILE:
8425         case NUNTIL:
8426                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8427                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8428                 break;
8429         case NIF:
8430                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8431                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8432                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8433                 break;
8434         case NFOR:
8435                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8436                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8437                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8438                 break;
8439         case NCASE:
8440                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8441                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8442                 break;
8443         case NCLIST:
8444                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8445                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8446                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8447                 break;
8448         case NDEFUN:
8449         case NARG:
8450                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8451                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8452                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8453                 break;
8454         case NTO:
8455 #if BASH_REDIR_OUTPUT
8456         case NTO2:
8457 #endif
8458         case NCLOBBER:
8459         case NFROM:
8460         case NFROMTO:
8461         case NAPPEND:
8462                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8463                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8464                 break;
8465         case NTOFD:
8466         case NFROMFD:
8467                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8468                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8469         break;
8470         case NHERE:
8471         case NXHERE:
8472                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8473                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8474                 break;
8475         case NNOT:
8476                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8477                 break;
8478         };
8479         return funcblocksize;
8480 }
8481
8482 static char *
8483 nodeckstrdup(char *s)
8484 {
8485         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8486         return strcpy(funcstring_end, s);
8487 }
8488
8489 static union node *copynode(union node *);
8490
8491 static struct nodelist *
8492 copynodelist(struct nodelist *lp)
8493 {
8494         struct nodelist *start;
8495         struct nodelist **lpp;
8496
8497         lpp = &start;
8498         while (lp) {
8499                 *lpp = funcblock;
8500                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8501                 (*lpp)->n = copynode(lp->n);
8502                 lp = lp->next;
8503                 lpp = &(*lpp)->next;
8504         }
8505         *lpp = NULL;
8506         return start;
8507 }
8508
8509 static union node *
8510 copynode(union node *n)
8511 {
8512         union node *new;
8513
8514         if (n == NULL)
8515                 return NULL;
8516         new = funcblock;
8517         funcblock = (char *) funcblock + nodesize[n->type];
8518
8519         switch (n->type) {
8520         case NCMD:
8521                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8522                 new->ncmd.args = copynode(n->ncmd.args);
8523                 new->ncmd.assign = copynode(n->ncmd.assign);
8524                 break;
8525         case NPIPE:
8526                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8527                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8528                 break;
8529         case NREDIR:
8530         case NBACKGND:
8531         case NSUBSHELL:
8532                 new->nredir.redirect = copynode(n->nredir.redirect);
8533                 new->nredir.n = copynode(n->nredir.n);
8534                 break;
8535         case NAND:
8536         case NOR:
8537         case NSEMI:
8538         case NWHILE:
8539         case NUNTIL:
8540                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8541                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8542                 break;
8543         case NIF:
8544                 new->nif.elsepart = copynode(n->nif.elsepart);
8545                 new->nif.ifpart = copynode(n->nif.ifpart);
8546                 new->nif.test = copynode(n->nif.test);
8547                 break;
8548         case NFOR:
8549                 new->nfor.var = nodeckstrdup(n->nfor.var);
8550                 new->nfor.body = copynode(n->nfor.body);
8551                 new->nfor.args = copynode(n->nfor.args);
8552                 break;
8553         case NCASE:
8554                 new->ncase.cases = copynode(n->ncase.cases);
8555                 new->ncase.expr = copynode(n->ncase.expr);
8556                 break;
8557         case NCLIST:
8558                 new->nclist.body = copynode(n->nclist.body);
8559                 new->nclist.pattern = copynode(n->nclist.pattern);
8560                 new->nclist.next = copynode(n->nclist.next);
8561                 break;
8562         case NDEFUN:
8563         case NARG:
8564                 new->narg.backquote = copynodelist(n->narg.backquote);
8565                 new->narg.text = nodeckstrdup(n->narg.text);
8566                 new->narg.next = copynode(n->narg.next);
8567                 break;
8568         case NTO:
8569 #if BASH_REDIR_OUTPUT
8570         case NTO2:
8571 #endif
8572         case NCLOBBER:
8573         case NFROM:
8574         case NFROMTO:
8575         case NAPPEND:
8576                 new->nfile.fname = copynode(n->nfile.fname);
8577                 new->nfile.fd = n->nfile.fd;
8578                 new->nfile.next = copynode(n->nfile.next);
8579                 break;
8580         case NTOFD:
8581         case NFROMFD:
8582                 new->ndup.vname = copynode(n->ndup.vname);
8583                 new->ndup.dupfd = n->ndup.dupfd;
8584                 new->ndup.fd = n->ndup.fd;
8585                 new->ndup.next = copynode(n->ndup.next);
8586                 break;
8587         case NHERE:
8588         case NXHERE:
8589                 new->nhere.doc = copynode(n->nhere.doc);
8590                 new->nhere.fd = n->nhere.fd;
8591                 new->nhere.next = copynode(n->nhere.next);
8592                 break;
8593         case NNOT:
8594                 new->nnot.com = copynode(n->nnot.com);
8595                 break;
8596         };
8597         new->type = n->type;
8598         return new;
8599 }
8600
8601 /*
8602  * Make a copy of a parse tree.
8603  */
8604 static struct funcnode *
8605 copyfunc(union node *n)
8606 {
8607         struct funcnode *f;
8608         size_t blocksize;
8609
8610         /*funcstringsize = 0;*/
8611         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8612         f = ckzalloc(blocksize /* + funcstringsize */);
8613         funcblock = (char *) f + offsetof(struct funcnode, n);
8614         funcstring_end = (char *) f + blocksize;
8615         copynode(n);
8616         /* f->count = 0; - ckzalloc did it */
8617         return f;
8618 }
8619
8620 /*
8621  * Define a shell function.
8622  */
8623 static void
8624 defun(union node *func)
8625 {
8626         struct cmdentry entry;
8627
8628         INT_OFF;
8629         entry.cmdtype = CMDFUNCTION;
8630         entry.u.func = copyfunc(func);
8631         addcmdentry(func->narg.text, &entry);
8632         INT_ON;
8633 }
8634
8635 /* Reasons for skipping commands (see comment on breakcmd routine) */
8636 #define SKIPBREAK      (1 << 0)
8637 #define SKIPCONT       (1 << 1)
8638 #define SKIPFUNC       (1 << 2)
8639 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8640 static int skipcount;           /* number of levels to skip */
8641 static int funcnest;            /* depth of function calls */
8642 static int loopnest;            /* current loop nesting level */
8643
8644 /* Forward decl way out to parsing code - dotrap needs it */
8645 static int evalstring(char *s, int flags);
8646
8647 /* Called to execute a trap.
8648  * Single callsite - at the end of evaltree().
8649  * If we return non-zero, evaltree raises EXEXIT exception.
8650  *
8651  * Perhaps we should avoid entering new trap handlers
8652  * while we are executing a trap handler. [is it a TODO?]
8653  */
8654 static void
8655 dotrap(void)
8656 {
8657         uint8_t *g;
8658         int sig;
8659         uint8_t last_status;
8660
8661         if (!pending_sig)
8662                 return;
8663
8664         last_status = exitstatus;
8665         pending_sig = 0;
8666         barrier();
8667
8668         TRACE(("dotrap entered\n"));
8669         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8670                 char *p;
8671
8672                 if (!*g)
8673                         continue;
8674
8675                 if (evalskip) {
8676                         pending_sig = sig;
8677                         break;
8678                 }
8679
8680                 p = trap[sig];
8681                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8682                  * don't upset it by resetting gotsig[SIGINT-1] */
8683                 if (sig == SIGINT && !p)
8684                         continue;
8685
8686                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8687                 *g = 0;
8688                 if (!p)
8689                         continue;
8690                 evalstring(p, 0);
8691         }
8692         exitstatus = last_status;
8693         TRACE(("dotrap returns\n"));
8694 }
8695
8696 /* forward declarations - evaluation is fairly recursive business... */
8697 static int evalloop(union node *, int);
8698 static int evalfor(union node *, int);
8699 static int evalcase(union node *, int);
8700 static int evalsubshell(union node *, int);
8701 static void expredir(union node *);
8702 static int evalpipe(union node *, int);
8703 static int evalcommand(union node *, int);
8704 static int evalbltin(const struct builtincmd *, int, char **, int);
8705 static void prehash(union node *);
8706
8707 /*
8708  * Evaluate a parse tree.  The value is left in the global variable
8709  * exitstatus.
8710  */
8711 static int
8712 evaltree(union node *n, int flags)
8713 {
8714         int checkexit = 0;
8715         int (*evalfn)(union node *, int);
8716         int status = 0;
8717
8718         if (n == NULL) {
8719                 TRACE(("evaltree(NULL) called\n"));
8720                 goto out;
8721         }
8722         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8723
8724         dotrap();
8725
8726         switch (n->type) {
8727         default:
8728 #if DEBUG
8729                 out1fmt("Node type = %d\n", n->type);
8730                 fflush_all();
8731                 break;
8732 #endif
8733         case NNOT:
8734                 status = !evaltree(n->nnot.com, EV_TESTED);
8735                 goto setstatus;
8736         case NREDIR:
8737                 expredir(n->nredir.redirect);
8738                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8739                 if (!status) {
8740                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8741                 }
8742                 if (n->nredir.redirect)
8743                         popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8744                 goto setstatus;
8745         case NCMD:
8746                 evalfn = evalcommand;
8747  checkexit:
8748                 if (eflag && !(flags & EV_TESTED))
8749                         checkexit = ~0;
8750                 goto calleval;
8751         case NFOR:
8752                 evalfn = evalfor;
8753                 goto calleval;
8754         case NWHILE:
8755         case NUNTIL:
8756                 evalfn = evalloop;
8757                 goto calleval;
8758         case NSUBSHELL:
8759         case NBACKGND:
8760                 evalfn = evalsubshell;
8761                 goto checkexit;
8762         case NPIPE:
8763                 evalfn = evalpipe;
8764                 goto checkexit;
8765         case NCASE:
8766                 evalfn = evalcase;
8767                 goto calleval;
8768         case NAND:
8769         case NOR:
8770         case NSEMI: {
8771
8772 #if NAND + 1 != NOR
8773 #error NAND + 1 != NOR
8774 #endif
8775 #if NOR + 1 != NSEMI
8776 #error NOR + 1 != NSEMI
8777 #endif
8778                 unsigned is_or = n->type - NAND;
8779                 status = evaltree(
8780                         n->nbinary.ch1,
8781                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8782                 );
8783                 if ((!status) == is_or || evalskip)
8784                         break;
8785                 n = n->nbinary.ch2;
8786  evaln:
8787                 evalfn = evaltree;
8788  calleval:
8789                 status = evalfn(n, flags);
8790                 goto setstatus;
8791         }
8792         case NIF:
8793                 status = evaltree(n->nif.test, EV_TESTED);
8794                 if (evalskip)
8795                         break;
8796                 if (!status) {
8797                         n = n->nif.ifpart;
8798                         goto evaln;
8799                 }
8800                 if (n->nif.elsepart) {
8801                         n = n->nif.elsepart;
8802                         goto evaln;
8803                 }
8804                 status = 0;
8805                 goto setstatus;
8806         case NDEFUN:
8807                 defun(n);
8808                 /* Not necessary. To test it:
8809                  * "false; f() { qwerty; }; echo $?" should print 0.
8810                  */
8811                 /* status = 0; */
8812  setstatus:
8813                 exitstatus = status;
8814                 break;
8815         }
8816  out:
8817         /* Order of checks below is important:
8818          * signal handlers trigger before exit caused by "set -e".
8819          */
8820         dotrap();
8821
8822         if (checkexit & status)
8823                 raise_exception(EXEXIT);
8824         if (flags & EV_EXIT)
8825                 raise_exception(EXEXIT);
8826
8827         TRACE(("leaving evaltree (no interrupts)\n"));
8828         return exitstatus;
8829 }
8830
8831 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
8832 static
8833 #endif
8834 int evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
8835
8836 static int
8837 skiploop(void)
8838 {
8839         int skip = evalskip;
8840
8841         switch (skip) {
8842         case 0:
8843                 break;
8844         case SKIPBREAK:
8845         case SKIPCONT:
8846                 if (--skipcount <= 0) {
8847                         evalskip = 0;
8848                         break;
8849                 }
8850                 skip = SKIPBREAK;
8851                 break;
8852         }
8853         return skip;
8854 }
8855
8856 static int
8857 evalloop(union node *n, int flags)
8858 {
8859         int skip;
8860         int status;
8861
8862         loopnest++;
8863         status = 0;
8864         flags &= EV_TESTED;
8865         do {
8866                 int i;
8867
8868                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8869                 skip = skiploop();
8870                 if (skip == SKIPFUNC)
8871                         status = i;
8872                 if (skip)
8873                         continue;
8874                 if (n->type != NWHILE)
8875                         i = !i;
8876                 if (i != 0)
8877                         break;
8878                 status = evaltree(n->nbinary.ch2, flags);
8879                 skip = skiploop();
8880         } while (!(skip & ~SKIPCONT));
8881         loopnest--;
8882
8883         return status;
8884 }
8885
8886 static int
8887 evalfor(union node *n, int flags)
8888 {
8889         struct arglist arglist;
8890         union node *argp;
8891         struct strlist *sp;
8892         struct stackmark smark;
8893         int status = 0;
8894
8895         setstackmark(&smark);
8896         arglist.list = NULL;
8897         arglist.lastp = &arglist.list;
8898         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8899                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8900         }
8901         *arglist.lastp = NULL;
8902
8903         loopnest++;
8904         flags &= EV_TESTED;
8905         for (sp = arglist.list; sp; sp = sp->next) {
8906                 setvar0(n->nfor.var, sp->text);
8907                 status = evaltree(n->nfor.body, flags);
8908                 if (skiploop() & ~SKIPCONT)
8909                         break;
8910         }
8911         loopnest--;
8912         popstackmark(&smark);
8913
8914         return status;
8915 }
8916
8917 static int
8918 evalcase(union node *n, int flags)
8919 {
8920         union node *cp;
8921         union node *patp;
8922         struct arglist arglist;
8923         struct stackmark smark;
8924         int status = 0;
8925
8926         setstackmark(&smark);
8927         arglist.list = NULL;
8928         arglist.lastp = &arglist.list;
8929         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8930         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8931                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8932                         if (casematch(patp, arglist.list->text)) {
8933                                 /* Ensure body is non-empty as otherwise
8934                                  * EV_EXIT may prevent us from setting the
8935                                  * exit status.
8936                                  */
8937                                 if (evalskip == 0 && cp->nclist.body) {
8938                                         status = evaltree(cp->nclist.body, flags);
8939                                 }
8940                                 goto out;
8941                         }
8942                 }
8943         }
8944  out:
8945         popstackmark(&smark);
8946
8947         return status;
8948 }
8949
8950 /*
8951  * Kick off a subshell to evaluate a tree.
8952  */
8953 static int
8954 evalsubshell(union node *n, int flags)
8955 {
8956         struct job *jp;
8957         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
8958         int status;
8959
8960         expredir(n->nredir.redirect);
8961         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
8962                 goto nofork;
8963         INT_OFF;
8964         if (backgnd == FORK_FG)
8965                 get_tty_state();
8966         jp = makejob(/*n,*/ 1);
8967         if (forkshell(jp, n, backgnd) == 0) {
8968                 /* child */
8969                 INT_ON;
8970                 flags |= EV_EXIT;
8971                 if (backgnd)
8972                         flags &= ~EV_TESTED;
8973  nofork:
8974                 redirect(n->nredir.redirect, 0);
8975                 evaltreenr(n->nredir.n, flags);
8976                 /* never returns */
8977         }
8978         /* parent */
8979         status = 0;
8980         if (backgnd == FORK_FG)
8981                 status = waitforjob(jp);
8982         INT_ON;
8983         return status;
8984 }
8985
8986 /*
8987  * Compute the names of the files in a redirection list.
8988  */
8989 static void fixredir(union node *, const char *, int);
8990 static void
8991 expredir(union node *n)
8992 {
8993         union node *redir;
8994
8995         for (redir = n; redir; redir = redir->nfile.next) {
8996                 struct arglist fn;
8997
8998                 fn.list = NULL;
8999                 fn.lastp = &fn.list;
9000                 switch (redir->type) {
9001                 case NFROMTO:
9002                 case NFROM:
9003                 case NTO:
9004 #if BASH_REDIR_OUTPUT
9005                 case NTO2:
9006 #endif
9007                 case NCLOBBER:
9008                 case NAPPEND:
9009                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
9010                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
9011 #if BASH_REDIR_OUTPUT
9012  store_expfname:
9013 #endif
9014 #if 0
9015 // By the design of stack allocator, the loop of this kind:
9016 //      while true; do while true; do break; done </dev/null; done
9017 // will look like a memory leak: ash plans to free expfname's
9018 // of "/dev/null" as soon as it finishes running the loop
9019 // (in this case, never).
9020 // This "fix" is wrong:
9021                         if (redir->nfile.expfname)
9022                                 stunalloc(redir->nfile.expfname);
9023 // It results in corrupted state of stacked allocations.
9024 #endif
9025                         redir->nfile.expfname = fn.list->text;
9026                         break;
9027                 case NFROMFD:
9028                 case NTOFD: /* >& */
9029                         if (redir->ndup.vname) {
9030                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9031                                 if (fn.list == NULL)
9032                                         ash_msg_and_raise_error("redir error");
9033 #if BASH_REDIR_OUTPUT
9034 //FIXME: we used expandarg with different args!
9035                                 if (!isdigit_str9(fn.list->text)) {
9036                                         /* >&file, not >&fd */
9037                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9038                                                 ash_msg_and_raise_error("redir error");
9039                                         redir->type = NTO2;
9040                                         goto store_expfname;
9041                                 }
9042 #endif
9043                                 fixredir(redir, fn.list->text, 1);
9044                         }
9045                         break;
9046                 }
9047         }
9048 }
9049
9050 /*
9051  * Evaluate a pipeline.  All the processes in the pipeline are children
9052  * of the process creating the pipeline.  (This differs from some versions
9053  * of the shell, which make the last process in a pipeline the parent
9054  * of all the rest.)
9055  */
9056 static int
9057 evalpipe(union node *n, int flags)
9058 {
9059         struct job *jp;
9060         struct nodelist *lp;
9061         int pipelen;
9062         int prevfd;
9063         int pip[2];
9064         int status = 0;
9065
9066         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9067         pipelen = 0;
9068         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9069                 pipelen++;
9070         flags |= EV_EXIT;
9071         INT_OFF;
9072         if (n->npipe.pipe_backgnd == 0)
9073                 get_tty_state();
9074         jp = makejob(/*n,*/ pipelen);
9075         prevfd = -1;
9076         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9077                 prehash(lp->n);
9078                 pip[1] = -1;
9079                 if (lp->next) {
9080                         if (pipe(pip) < 0) {
9081                                 close(prevfd);
9082                                 ash_msg_and_raise_error("pipe call failed");
9083                         }
9084                 }
9085                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9086                         /* child */
9087                         INT_ON;
9088                         if (pip[1] >= 0) {
9089                                 close(pip[0]);
9090                         }
9091                         if (prevfd > 0) {
9092                                 dup2(prevfd, 0);
9093                                 close(prevfd);
9094                         }
9095                         if (pip[1] > 1) {
9096                                 dup2(pip[1], 1);
9097                                 close(pip[1]);
9098                         }
9099                         evaltreenr(lp->n, flags);
9100                         /* never returns */
9101                 }
9102                 /* parent */
9103                 if (prevfd >= 0)
9104                         close(prevfd);
9105                 prevfd = pip[0];
9106                 /* Don't want to trigger debugging */
9107                 if (pip[1] != -1)
9108                         close(pip[1]);
9109         }
9110         if (n->npipe.pipe_backgnd == 0) {
9111                 status = waitforjob(jp);
9112                 TRACE(("evalpipe:  job done exit status %d\n", status));
9113         }
9114         INT_ON;
9115
9116         return status;
9117 }
9118
9119 /*
9120  * Controls whether the shell is interactive or not.
9121  */
9122 static void
9123 setinteractive(int on)
9124 {
9125         static smallint is_interactive;
9126
9127         if (++on == is_interactive)
9128                 return;
9129         is_interactive = on;
9130         setsignal(SIGINT);
9131         setsignal(SIGQUIT);
9132         setsignal(SIGTERM);
9133 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9134         if (is_interactive > 1) {
9135                 /* Looks like they want an interactive shell */
9136                 static smallint did_banner;
9137
9138                 if (!did_banner) {
9139                         /* note: ash and hush share this string */
9140                         out1fmt("\n\n%s %s\n"
9141                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9142                                 "\n",
9143                                 bb_banner,
9144                                 "built-in shell (ash)"
9145                         );
9146                         did_banner = 1;
9147                 }
9148         }
9149 #endif
9150 }
9151
9152 static void
9153 optschanged(void)
9154 {
9155 #if DEBUG
9156         opentrace();
9157 #endif
9158         setinteractive(iflag);
9159         setjobctl(mflag);
9160 #if ENABLE_FEATURE_EDITING_VI
9161         if (viflag)
9162                 line_input_state->flags |= VI_MODE;
9163         else
9164                 line_input_state->flags &= ~VI_MODE;
9165 #else
9166         viflag = 0; /* forcibly keep the option off */
9167 #endif
9168 }
9169
9170 struct localvar_list {
9171         struct localvar_list *next;
9172         struct localvar *lv;
9173 };
9174
9175 static struct localvar_list *localvar_stack;
9176
9177 /*
9178  * Called after a function returns.
9179  * Interrupts must be off.
9180  */
9181 static void
9182 poplocalvars(void)
9183 {
9184         struct localvar_list *ll;
9185         struct localvar *lvp, *next;
9186         struct var *vp;
9187
9188         INT_OFF;
9189         ll = localvar_stack;
9190         localvar_stack = ll->next;
9191
9192         next = ll->lv;
9193         free(ll);
9194
9195         while ((lvp = next) != NULL) {
9196                 next = lvp->next;
9197                 vp = lvp->vp;
9198                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9199                 if (vp == NULL) {       /* $- saved */
9200                         memcpy(optlist, lvp->text, sizeof(optlist));
9201                         free((char*)lvp->text);
9202                         optschanged();
9203                 } else if (lvp->flags == VUNSET) {
9204                         vp->flags &= ~(VSTRFIXED|VREADONLY);
9205                         unsetvar(vp->var_text);
9206                 } else {
9207                         if (vp->var_func)
9208                                 vp->var_func(var_end(lvp->text));
9209                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
9210                                 free((char*)vp->var_text);
9211                         vp->flags = lvp->flags;
9212                         vp->var_text = lvp->text;
9213                 }
9214                 free(lvp);
9215         }
9216         INT_ON;
9217 }
9218
9219 /*
9220  * Create a new localvar environment.
9221  */
9222 static void
9223 pushlocalvars(void)
9224 {
9225         struct localvar_list *ll;
9226
9227         INT_OFF;
9228         ll = ckzalloc(sizeof(*ll));
9229         /*ll->lv = NULL; - zalloc did it */
9230         ll->next = localvar_stack;
9231         localvar_stack = ll;
9232         INT_ON;
9233 }
9234
9235 static int
9236 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9237 {
9238         volatile struct shparam saveparam;
9239         struct jmploc *volatile savehandler;
9240         struct jmploc jmploc;
9241         int e;
9242
9243         saveparam = shellparam;
9244         savehandler = exception_handler;
9245         e = setjmp(jmploc.loc);
9246         if (e) {
9247                 goto funcdone;
9248         }
9249         INT_OFF;
9250         exception_handler = &jmploc;
9251         shellparam.malloced = 0;
9252         func->count++;
9253         funcnest++;
9254         INT_ON;
9255         shellparam.nparam = argc - 1;
9256         shellparam.p = argv + 1;
9257 #if ENABLE_ASH_GETOPTS
9258         shellparam.optind = 1;
9259         shellparam.optoff = -1;
9260 #endif
9261         pushlocalvars();
9262         evaltree(func->n.narg.next, flags & EV_TESTED);
9263         poplocalvars();
9264  funcdone:
9265         INT_OFF;
9266         funcnest--;
9267         freefunc(func);
9268         freeparam(&shellparam);
9269         shellparam = saveparam;
9270         exception_handler = savehandler;
9271         INT_ON;
9272         evalskip &= ~SKIPFUNC;
9273         return e;
9274 }
9275
9276 /*
9277  * Make a variable a local variable.  When a variable is made local, it's
9278  * value and flags are saved in a localvar structure.  The saved values
9279  * will be restored when the shell function returns.  We handle the name
9280  * "-" as a special case: it makes changes to "set +-options" local
9281  * (options will be restored on return from the function).
9282  */
9283 static void
9284 mklocal(char *name)
9285 {
9286         struct localvar *lvp;
9287         struct var **vpp;
9288         struct var *vp;
9289         char *eq = strchr(name, '=');
9290
9291         INT_OFF;
9292         /* Cater for duplicate "local". Examples:
9293          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9294          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9295          */
9296         lvp = localvar_stack->lv;
9297         while (lvp) {
9298                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9299                         if (eq)
9300                                 setvareq(name, 0);
9301                         /* else:
9302                          * it's a duplicate "local VAR" declaration, do nothing
9303                          */
9304                         goto ret;
9305                 }
9306                 lvp = lvp->next;
9307         }
9308
9309         lvp = ckzalloc(sizeof(*lvp));
9310         if (LONE_DASH(name)) {
9311                 char *p;
9312                 p = ckmalloc(sizeof(optlist));
9313                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9314                 vp = NULL;
9315         } else {
9316                 vpp = hashvar(name);
9317                 vp = *findvar(vpp, name);
9318                 if (vp == NULL) {
9319                         /* variable did not exist yet */
9320                         if (eq)
9321                                 setvareq(name, VSTRFIXED);
9322                         else
9323                                 setvar(name, NULL, VSTRFIXED);
9324                         vp = *vpp;      /* the new variable */
9325                         lvp->flags = VUNSET;
9326                 } else {
9327                         lvp->text = vp->var_text;
9328                         lvp->flags = vp->flags;
9329                         /* make sure neither "struct var" nor string gets freed
9330                          * during (un)setting:
9331                          */
9332                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9333                         if (eq)
9334                                 setvareq(name, 0);
9335                         else
9336                                 /* "local VAR" unsets VAR: */
9337                                 setvar0(name, NULL);
9338                 }
9339         }
9340         lvp->vp = vp;
9341         lvp->next = localvar_stack->lv;
9342         localvar_stack->lv = lvp;
9343  ret:
9344         INT_ON;
9345 }
9346
9347 /*
9348  * The "local" command.
9349  */
9350 static int FAST_FUNC
9351 localcmd(int argc UNUSED_PARAM, char **argv)
9352 {
9353         char *name;
9354
9355         if (!localvar_stack)
9356                 ash_msg_and_raise_error("not in a function");
9357
9358         argv = argptr;
9359         while ((name = *argv++) != NULL) {
9360                 mklocal(name);
9361         }
9362         return 0;
9363 }
9364
9365 static int FAST_FUNC
9366 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9367 {
9368         return 1;
9369 }
9370
9371 static int FAST_FUNC
9372 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9373 {
9374         return 0;
9375 }
9376
9377 static int FAST_FUNC
9378 execcmd(int argc UNUSED_PARAM, char **argv)
9379 {
9380         optionarg = NULL;
9381         while (nextopt("a:") != '\0')
9382                 /* nextopt() sets optionarg to "-a ARGV0" */;
9383
9384         argv = argptr;
9385         if (argv[0]) {
9386                 char *prog;
9387
9388                 iflag = 0;              /* exit on error */
9389                 mflag = 0;
9390                 optschanged();
9391                 /* We should set up signals for "exec CMD"
9392                  * the same way as for "CMD" without "exec".
9393                  * But optschanged->setinteractive->setsignal
9394                  * still thought we are a root shell. Therefore, for example,
9395                  * SIGQUIT is still set to IGN. Fix it:
9396                  */
9397                 shlvl++;
9398                 setsignal(SIGQUIT);
9399                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9400                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9401                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9402
9403                 prog = argv[0];
9404                 if (optionarg)
9405                         argv[0] = optionarg;
9406                 shellexec(prog, argv, pathval(), 0);
9407                 /* NOTREACHED */
9408         }
9409         return 0;
9410 }
9411
9412 /*
9413  * The return command.
9414  */
9415 static int FAST_FUNC
9416 returncmd(int argc UNUSED_PARAM, char **argv)
9417 {
9418         /*
9419          * If called outside a function, do what ksh does;
9420          * skip the rest of the file.
9421          */
9422         evalskip = SKIPFUNC;
9423         return argv[1] ? number(argv[1]) : exitstatus;
9424 }
9425
9426 /* Forward declarations for builtintab[] */
9427 static int breakcmd(int, char **) FAST_FUNC;
9428 static int dotcmd(int, char **) FAST_FUNC;
9429 static int evalcmd(int, char **, int) FAST_FUNC;
9430 static int exitcmd(int, char **) FAST_FUNC;
9431 static int exportcmd(int, char **) FAST_FUNC;
9432 #if ENABLE_ASH_GETOPTS
9433 static int getoptscmd(int, char **) FAST_FUNC;
9434 #endif
9435 #if ENABLE_ASH_HELP
9436 static int helpcmd(int, char **) FAST_FUNC;
9437 #endif
9438 #if MAX_HISTORY
9439 static int historycmd(int, char **) FAST_FUNC;
9440 #endif
9441 #if ENABLE_FEATURE_SH_MATH
9442 static int letcmd(int, char **) FAST_FUNC;
9443 #endif
9444 static int readcmd(int, char **) FAST_FUNC;
9445 static int setcmd(int, char **) FAST_FUNC;
9446 static int shiftcmd(int, char **) FAST_FUNC;
9447 static int timescmd(int, char **) FAST_FUNC;
9448 static int trapcmd(int, char **) FAST_FUNC;
9449 static int umaskcmd(int, char **) FAST_FUNC;
9450 static int unsetcmd(int, char **) FAST_FUNC;
9451 static int ulimitcmd(int, char **) FAST_FUNC;
9452
9453 #define BUILTIN_NOSPEC          "0"
9454 #define BUILTIN_SPECIAL         "1"
9455 #define BUILTIN_REGULAR         "2"
9456 #define BUILTIN_SPEC_REG        "3"
9457 #define BUILTIN_ASSIGN          "4"
9458 #define BUILTIN_SPEC_ASSG       "5"
9459 #define BUILTIN_REG_ASSG        "6"
9460 #define BUILTIN_SPEC_REG_ASSG   "7"
9461
9462 /* Stubs for calling non-FAST_FUNC's */
9463 #if ENABLE_ASH_ECHO
9464 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9465 #endif
9466 #if ENABLE_ASH_PRINTF
9467 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9468 #endif
9469 #if ENABLE_ASH_TEST || BASH_TEST2
9470 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9471 #endif
9472
9473 /* Keep these in proper order since it is searched via bsearch() */
9474 static const struct builtincmd builtintab[] = {
9475         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9476         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9477 #if ENABLE_ASH_TEST
9478         { BUILTIN_REGULAR       "["       , testcmd    },
9479 #endif
9480 #if BASH_TEST2
9481         { BUILTIN_REGULAR       "[["      , testcmd    },
9482 #endif
9483 #if ENABLE_ASH_ALIAS
9484         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9485 #endif
9486 #if JOBS
9487         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9488 #endif
9489         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9490         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9491         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9492 #if ENABLE_ASH_CMDCMD
9493         { BUILTIN_REGULAR       "command" , commandcmd },
9494 #endif
9495         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9496 #if ENABLE_ASH_ECHO
9497         { BUILTIN_REGULAR       "echo"    , echocmd    },
9498 #endif
9499         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9500         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9501         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9502         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9503         { BUILTIN_REGULAR       "false"   , falsecmd   },
9504 #if JOBS
9505         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9506 #endif
9507 #if ENABLE_ASH_GETOPTS
9508         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9509 #endif
9510         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9511 #if ENABLE_ASH_HELP
9512         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9513 #endif
9514 #if MAX_HISTORY
9515         { BUILTIN_NOSPEC        "history" , historycmd },
9516 #endif
9517 #if JOBS
9518         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9519         { BUILTIN_REGULAR       "kill"    , killcmd    },
9520 #endif
9521 #if ENABLE_FEATURE_SH_MATH
9522         { BUILTIN_NOSPEC        "let"     , letcmd     },
9523 #endif
9524         { BUILTIN_ASSIGN        "local"   , localcmd   },
9525 #if ENABLE_ASH_PRINTF
9526         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9527 #endif
9528         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9529         { BUILTIN_REGULAR       "read"    , readcmd    },
9530         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9531         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9532         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9533         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9534 #if BASH_SOURCE
9535         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9536 #endif
9537 #if ENABLE_ASH_TEST
9538         { BUILTIN_REGULAR       "test"    , testcmd    },
9539 #endif
9540         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9541         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9542         { BUILTIN_REGULAR       "true"    , truecmd    },
9543         { BUILTIN_NOSPEC        "type"    , typecmd    },
9544         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9545         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9546 #if ENABLE_ASH_ALIAS
9547         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9548 #endif
9549         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9550         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9551 };
9552
9553 /* Should match the above table! */
9554 #define COMMANDCMD (builtintab + \
9555         /* . : */       2 + \
9556         /* [ */         1 * ENABLE_ASH_TEST + \
9557         /* [[ */        1 * BASH_TEST2 + \
9558         /* alias */     1 * ENABLE_ASH_ALIAS + \
9559         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9560         /* break cd cddir  */   3)
9561 #define EVALCMD (COMMANDCMD + \
9562         /* command */   1 * ENABLE_ASH_CMDCMD + \
9563         /* continue */  1 + \
9564         /* echo */      1 * ENABLE_ASH_ECHO + \
9565         0)
9566 #define EXECCMD (EVALCMD + \
9567         /* eval */      1)
9568
9569 /*
9570  * Search the table of builtin commands.
9571  */
9572 static int
9573 pstrcmp1(const void *a, const void *b)
9574 {
9575         return strcmp((char*)a, *(char**)b + 1);
9576 }
9577 static struct builtincmd *
9578 find_builtin(const char *name)
9579 {
9580         struct builtincmd *bp;
9581
9582         bp = bsearch(
9583                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9584                 pstrcmp1
9585         );
9586         return bp;
9587 }
9588
9589 /*
9590  * Execute a simple command.
9591  */
9592 static int
9593 isassignment(const char *p)
9594 {
9595         const char *q = endofname(p);
9596         if (p == q)
9597                 return 0;
9598         return *q == '=';
9599 }
9600 static int FAST_FUNC
9601 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9602 {
9603         /* Preserve exitstatus of a previous possible redirection
9604          * as POSIX mandates */
9605         return back_exitstatus;
9606 }
9607 static int
9608 evalcommand(union node *cmd, int flags)
9609 {
9610         static const struct builtincmd null_bltin = {
9611                 "\0\0", bltincmd /* why three NULs? */
9612         };
9613         struct stackmark smark;
9614         union node *argp;
9615         struct arglist arglist;
9616         struct arglist varlist;
9617         char **argv;
9618         int argc;
9619         const struct strlist *sp;
9620         struct cmdentry cmdentry;
9621         struct job *jp;
9622         char *lastarg;
9623         const char *path;
9624         int spclbltin;
9625         int status;
9626         char **nargv;
9627         struct builtincmd *bcmd;
9628         smallint cmd_is_exec;
9629         smallint pseudovarflag = 0;
9630
9631         /* First expand the arguments. */
9632         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9633         setstackmark(&smark);
9634         back_exitstatus = 0;
9635
9636         cmdentry.cmdtype = CMDBUILTIN;
9637         cmdentry.u.cmd = &null_bltin;
9638         varlist.lastp = &varlist.list;
9639         *varlist.lastp = NULL;
9640         arglist.lastp = &arglist.list;
9641         *arglist.lastp = NULL;
9642
9643         argc = 0;
9644         if (cmd->ncmd.args) {
9645                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9646                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9647         }
9648
9649         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9650                 struct strlist **spp;
9651
9652                 spp = arglist.lastp;
9653                 if (pseudovarflag && isassignment(argp->narg.text))
9654                         expandarg(argp, &arglist, EXP_VARTILDE);
9655                 else
9656                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9657
9658                 for (sp = *spp; sp; sp = sp->next)
9659                         argc++;
9660         }
9661
9662         /* Reserve one extra spot at the front for shellexec. */
9663         nargv = stalloc(sizeof(char *) * (argc + 2));
9664         argv = ++nargv;
9665         for (sp = arglist.list; sp; sp = sp->next) {
9666                 TRACE(("evalcommand arg: %s\n", sp->text));
9667                 *nargv++ = sp->text;
9668         }
9669         *nargv = NULL;
9670
9671         lastarg = NULL;
9672         if (iflag && funcnest == 0 && argc > 0)
9673                 lastarg = nargv[-1];
9674
9675         preverrout_fd = 2;
9676         expredir(cmd->ncmd.redirect);
9677         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9678
9679         path = vpath.var_text;
9680         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9681                 struct strlist **spp;
9682                 char *p;
9683
9684                 spp = varlist.lastp;
9685                 expandarg(argp, &varlist, EXP_VARTILDE);
9686
9687                 /*
9688                  * Modify the command lookup path, if a PATH= assignment
9689                  * is present
9690                  */
9691                 p = (*spp)->text;
9692                 if (varcmp(p, path) == 0)
9693                         path = p;
9694         }
9695
9696         /* Print the command if xflag is set. */
9697         if (xflag) {
9698                 const char *pfx = "";
9699
9700                 fdprintf(preverrout_fd, "%s", expandstr(ps4val()));
9701
9702                 sp = varlist.list;
9703                 while (sp) {
9704                         char *varval = sp->text;
9705                         char *eq = strchrnul(varval, '=');
9706                         if (*eq)
9707                                 eq++;
9708                         fdprintf(preverrout_fd, "%s%.*s%s",
9709                                 pfx,
9710                                 (int)(eq - varval), varval,
9711                                 maybe_single_quote(eq)
9712                         );
9713                         sp = sp->next;
9714                         pfx = " ";
9715                 }
9716
9717                 sp = arglist.list;
9718                 while (sp) {
9719                         fdprintf(preverrout_fd, "%s%s",
9720                                 pfx,
9721                                 /* always quote if matches reserved word: */
9722                                 findkwd(sp->text)
9723                                 ? single_quote(sp->text)
9724                                 : maybe_single_quote(sp->text)
9725                         );
9726                         sp = sp->next;
9727                         pfx = " ";
9728                 }
9729                 safe_write(preverrout_fd, "\n", 1);
9730         }
9731
9732         cmd_is_exec = 0;
9733         spclbltin = -1;
9734
9735         /* Now locate the command. */
9736         if (argc) {
9737                 int cmd_flag = DO_ERR;
9738 #if ENABLE_ASH_CMDCMD
9739                 const char *oldpath = path + 5;
9740 #endif
9741                 path += 5;
9742                 for (;;) {
9743                         find_command(argv[0], &cmdentry, cmd_flag, path);
9744                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9745                                 flush_stdout_stderr();
9746                                 status = 127;
9747                                 goto bail;
9748                         }
9749
9750                         /* implement bltin and command here */
9751                         if (cmdentry.cmdtype != CMDBUILTIN)
9752                                 break;
9753                         if (spclbltin < 0)
9754                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9755                         if (cmdentry.u.cmd == EXECCMD)
9756                                 cmd_is_exec = 1;
9757 #if ENABLE_ASH_CMDCMD
9758                         if (cmdentry.u.cmd == COMMANDCMD) {
9759                                 path = oldpath;
9760                                 nargv = parse_command_args(argv, &path);
9761                                 if (!nargv)
9762                                         break;
9763                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9764                                  * nargv => "PROG". path is updated if -p.
9765                                  */
9766                                 argc -= nargv - argv;
9767                                 argv = nargv;
9768                                 cmd_flag |= DO_NOFUNC;
9769                         } else
9770 #endif
9771                                 break;
9772                 }
9773         }
9774
9775         if (status) {
9776  bail:
9777                 exitstatus = status;
9778
9779                 /* We have a redirection error. */
9780                 if (spclbltin > 0)
9781                         raise_exception(EXERROR);
9782
9783                 goto out;
9784         }
9785
9786         /* Execute the command. */
9787         switch (cmdentry.cmdtype) {
9788         default: {
9789
9790 #if ENABLE_FEATURE_SH_NOFORK
9791 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9792  *     around run_nofork_applet() call.
9793  * (2) Should this check also be done in forkshell()?
9794  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9795  */
9796                 /* find_command() encodes applet_no as (-2 - applet_no) */
9797                 int applet_no = (- cmdentry.u.index - 2);
9798                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9799                         listsetvar(varlist.list, VEXPORT|VSTACK);
9800                         /* run <applet>_main() */
9801                         status = run_nofork_applet(applet_no, argv);
9802                         break;
9803                 }
9804 #endif
9805                 /* Can we avoid forking off? For example, very last command
9806                  * in a script or a subshell does not need forking,
9807                  * we can just exec it.
9808                  */
9809                 if (!(flags & EV_EXIT) || may_have_traps) {
9810                         /* No, forking off a child is necessary */
9811                         INT_OFF;
9812                         get_tty_state();
9813                         jp = makejob(/*cmd,*/ 1);
9814                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9815                                 /* parent */
9816                                 status = waitforjob(jp);
9817                                 INT_ON;
9818                                 TRACE(("forked child exited with %d\n", status));
9819                                 break;
9820                         }
9821                         /* child */
9822                         FORCE_INT_ON;
9823                         /* fall through to exec'ing external program */
9824                 }
9825                 listsetvar(varlist.list, VEXPORT|VSTACK);
9826                 shellexec(argv[0], argv, path, cmdentry.u.index);
9827                 /* NOTREACHED */
9828         } /* default */
9829         case CMDBUILTIN:
9830                 cmdenviron = varlist.list;
9831                 if (cmdenviron) {
9832                         struct strlist *list = cmdenviron;
9833                         int i = VNOSET;
9834                         if (spclbltin > 0 || argc == 0) {
9835                                 i = 0;
9836                                 if (cmd_is_exec && argc > 1)
9837                                         i = VEXPORT;
9838                         }
9839                         listsetvar(list, i);
9840                 }
9841                 /* Tight loop with builtins only:
9842                  * "while kill -0 $child; do true; done"
9843                  * will never exit even if $child died, unless we do this
9844                  * to reap the zombie and make kill detect that it's gone: */
9845                 dowait(DOWAIT_NONBLOCK, NULL);
9846
9847                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9848                         if (exception_type == EXERROR && spclbltin <= 0) {
9849                                 FORCE_INT_ON;
9850                                 goto readstatus;
9851                         }
9852  raise:
9853                         longjmp(exception_handler->loc, 1);
9854                 }
9855                 goto readstatus;
9856
9857         case CMDFUNCTION:
9858                 listsetvar(varlist.list, 0);
9859                 /* See above for the rationale */
9860                 dowait(DOWAIT_NONBLOCK, NULL);
9861                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9862                         goto raise;
9863  readstatus:
9864                 status = exitstatus;
9865                 break;
9866         } /* switch */
9867
9868  out:
9869         if (cmd->ncmd.redirect)
9870                 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9871         if (lastarg) {
9872                 /* dsl: I think this is intended to be used to support
9873                  * '_' in 'vi' command mode during line editing...
9874                  * However I implemented that within libedit itself.
9875                  */
9876                 setvar0("_", lastarg);
9877         }
9878         popstackmark(&smark);
9879
9880         return status;
9881 }
9882
9883 static int
9884 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9885 {
9886         char *volatile savecmdname;
9887         struct jmploc *volatile savehandler;
9888         struct jmploc jmploc;
9889         int status;
9890         int i;
9891
9892         savecmdname = commandname;
9893         savehandler = exception_handler;
9894         i = setjmp(jmploc.loc);
9895         if (i)
9896                 goto cmddone;
9897         exception_handler = &jmploc;
9898         commandname = argv[0];
9899         argptr = argv + 1;
9900         optptr = NULL;                  /* initialize nextopt */
9901         if (cmd == EVALCMD)
9902                 status = evalcmd(argc, argv, flags);
9903         else
9904                 status = (*cmd->builtin)(argc, argv);
9905         flush_stdout_stderr();
9906         status |= ferror(stdout);
9907         exitstatus = status;
9908  cmddone:
9909         clearerr(stdout);
9910         commandname = savecmdname;
9911         exception_handler = savehandler;
9912
9913         return i;
9914 }
9915
9916 static int
9917 goodname(const char *p)
9918 {
9919         return endofname(p)[0] == '\0';
9920 }
9921
9922
9923 /*
9924  * Search for a command.  This is called before we fork so that the
9925  * location of the command will be available in the parent as well as
9926  * the child.  The check for "goodname" is an overly conservative
9927  * check that the name will not be subject to expansion.
9928  */
9929 static void
9930 prehash(union node *n)
9931 {
9932         struct cmdentry entry;
9933
9934         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9935                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9936 }
9937
9938
9939 /* ============ Builtin commands
9940  *
9941  * Builtin commands whose functions are closely tied to evaluation
9942  * are implemented here.
9943  */
9944
9945 /*
9946  * Handle break and continue commands.  Break, continue, and return are
9947  * all handled by setting the evalskip flag.  The evaluation routines
9948  * above all check this flag, and if it is set they start skipping
9949  * commands rather than executing them.  The variable skipcount is
9950  * the number of loops to break/continue, or the number of function
9951  * levels to return.  (The latter is always 1.)  It should probably
9952  * be an error to break out of more loops than exist, but it isn't
9953  * in the standard shell so we don't make it one here.
9954  */
9955 static int FAST_FUNC
9956 breakcmd(int argc UNUSED_PARAM, char **argv)
9957 {
9958         int n = argv[1] ? number(argv[1]) : 1;
9959
9960         if (n <= 0)
9961                 ash_msg_and_raise_error(msg_illnum, argv[1]);
9962         if (n > loopnest)
9963                 n = loopnest;
9964         if (n > 0) {
9965                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9966                 skipcount = n;
9967         }
9968         return 0;
9969 }
9970
9971
9972 /*
9973  * This implements the input routines used by the parser.
9974  */
9975
9976 enum {
9977         INPUT_PUSH_FILE = 1,
9978         INPUT_NOFILE_OK = 2,
9979 };
9980
9981 static smallint checkkwd;
9982 /* values of checkkwd variable */
9983 #define CHKALIAS        0x1
9984 #define CHKKWD          0x2
9985 #define CHKNL           0x4
9986
9987 /*
9988  * Push a string back onto the input at this current parsefile level.
9989  * We handle aliases this way.
9990  */
9991 #if !ENABLE_ASH_ALIAS
9992 #define pushstring(s, ap) pushstring(s)
9993 #endif
9994 static void
9995 pushstring(char *s, struct alias *ap)
9996 {
9997         struct strpush *sp;
9998         int len;
9999
10000         len = strlen(s);
10001         INT_OFF;
10002         if (g_parsefile->strpush) {
10003                 sp = ckzalloc(sizeof(*sp));
10004                 sp->prev = g_parsefile->strpush;
10005         } else {
10006                 sp = &(g_parsefile->basestrpush);
10007         }
10008         g_parsefile->strpush = sp;
10009         sp->prev_string = g_parsefile->next_to_pgetc;
10010         sp->prev_left_in_line = g_parsefile->left_in_line;
10011         sp->unget = g_parsefile->unget;
10012         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10013 #if ENABLE_ASH_ALIAS
10014         sp->ap = ap;
10015         if (ap) {
10016                 ap->flag |= ALIASINUSE;
10017                 sp->string = s;
10018         }
10019 #endif
10020         g_parsefile->next_to_pgetc = s;
10021         g_parsefile->left_in_line = len;
10022         g_parsefile->unget = 0;
10023         INT_ON;
10024 }
10025
10026 static void
10027 popstring(void)
10028 {
10029         struct strpush *sp = g_parsefile->strpush;
10030
10031         INT_OFF;
10032 #if ENABLE_ASH_ALIAS
10033         if (sp->ap) {
10034                 if (g_parsefile->next_to_pgetc[-1] == ' '
10035                  || g_parsefile->next_to_pgetc[-1] == '\t'
10036                 ) {
10037                         checkkwd |= CHKALIAS;
10038                 }
10039                 if (sp->string != sp->ap->val) {
10040                         free(sp->string);
10041                 }
10042                 sp->ap->flag &= ~ALIASINUSE;
10043                 if (sp->ap->flag & ALIASDEAD) {
10044                         unalias(sp->ap->name);
10045                 }
10046         }
10047 #endif
10048         g_parsefile->next_to_pgetc = sp->prev_string;
10049         g_parsefile->left_in_line = sp->prev_left_in_line;
10050         g_parsefile->unget = sp->unget;
10051         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10052         g_parsefile->strpush = sp->prev;
10053         if (sp != &(g_parsefile->basestrpush))
10054                 free(sp);
10055         INT_ON;
10056 }
10057
10058 static int
10059 preadfd(void)
10060 {
10061         int nr;
10062         char *buf = g_parsefile->buf;
10063
10064         g_parsefile->next_to_pgetc = buf;
10065 #if ENABLE_FEATURE_EDITING
10066  retry:
10067         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10068                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10069         else {
10070                 int timeout = -1;
10071 # if ENABLE_ASH_IDLE_TIMEOUT
10072                 if (iflag) {
10073                         const char *tmout_var = lookupvar("TMOUT");
10074                         if (tmout_var) {
10075                                 timeout = atoi(tmout_var) * 1000;
10076                                 if (timeout <= 0)
10077                                         timeout = -1;
10078                         }
10079                 }
10080 # endif
10081 # if ENABLE_FEATURE_TAB_COMPLETION
10082                 line_input_state->path_lookup = pathval();
10083 # endif
10084                 reinit_unicode_for_ash();
10085                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
10086                 if (nr == 0) {
10087                         /* ^C pressed, "convert" to SIGINT */
10088                         write(STDOUT_FILENO, "^C", 2);
10089                         if (trap[SIGINT]) {
10090                                 buf[0] = '\n';
10091                                 buf[1] = '\0';
10092                                 raise(SIGINT);
10093                                 return 1;
10094                         }
10095                         exitstatus = 128 + SIGINT;
10096                         bb_putchar('\n');
10097                         goto retry;
10098                 }
10099                 if (nr < 0) {
10100                         if (errno == 0) {
10101                                 /* Ctrl+D pressed */
10102                                 nr = 0;
10103                         }
10104 # if ENABLE_ASH_IDLE_TIMEOUT
10105                         else if (errno == EAGAIN && timeout > 0) {
10106                                 puts("\007timed out waiting for input: auto-logout");
10107                                 exitshell();
10108                         }
10109 # endif
10110                 }
10111         }
10112 #else
10113         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10114 #endif
10115
10116 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10117         if (nr < 0) {
10118                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10119                         int flags = fcntl(0, F_GETFL);
10120                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10121                                 flags &= ~O_NONBLOCK;
10122                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10123                                         out2str("sh: turning off NDELAY mode\n");
10124                                         goto retry;
10125                                 }
10126                         }
10127                 }
10128         }
10129 #endif
10130         return nr;
10131 }
10132
10133 /*
10134  * Refill the input buffer and return the next input character:
10135  *
10136  * 1) If a string was pushed back on the input, pop it;
10137  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10138  *    or we are reading from a string so we can't refill the buffer,
10139  *    return EOF.
10140  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10141  * 4) Process input up to the next newline, deleting nul characters.
10142  */
10143 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10144 #define pgetc_debug(...) ((void)0)
10145 static int pgetc(void);
10146 static int
10147 preadbuffer(void)
10148 {
10149         char *q;
10150         int more;
10151
10152         if (g_parsefile->strpush) {
10153 #if ENABLE_ASH_ALIAS
10154                 if (g_parsefile->left_in_line == -1
10155                  && g_parsefile->strpush->ap
10156                  && g_parsefile->next_to_pgetc[-1] != ' '
10157                  && g_parsefile->next_to_pgetc[-1] != '\t'
10158                 ) {
10159                         pgetc_debug("preadbuffer PEOA");
10160                         return PEOA;
10161                 }
10162 #endif
10163                 popstring();
10164                 return pgetc();
10165         }
10166         /* on both branches above g_parsefile->left_in_line < 0.
10167          * "pgetc" needs refilling.
10168          */
10169
10170         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10171          * pungetc() may increment it a few times.
10172          * Assuming it won't increment it to less than -90.
10173          */
10174         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10175                 pgetc_debug("preadbuffer PEOF1");
10176                 /* even in failure keep left_in_line and next_to_pgetc
10177                  * in lock step, for correct multi-layer pungetc.
10178                  * left_in_line was decremented before preadbuffer(),
10179                  * must inc next_to_pgetc: */
10180                 g_parsefile->next_to_pgetc++;
10181                 return PEOF;
10182         }
10183
10184         more = g_parsefile->left_in_buffer;
10185         if (more <= 0) {
10186                 flush_stdout_stderr();
10187  again:
10188                 more = preadfd();
10189                 if (more <= 0) {
10190                         /* don't try reading again */
10191                         g_parsefile->left_in_line = -99;
10192                         pgetc_debug("preadbuffer PEOF2");
10193                         g_parsefile->next_to_pgetc++;
10194                         return PEOF;
10195                 }
10196         }
10197
10198         /* Find out where's the end of line.
10199          * Set g_parsefile->left_in_line
10200          * and g_parsefile->left_in_buffer acordingly.
10201          * NUL chars are deleted.
10202          */
10203         q = g_parsefile->next_to_pgetc;
10204         for (;;) {
10205                 char c;
10206
10207                 more--;
10208
10209                 c = *q;
10210                 if (c == '\0') {
10211                         memmove(q, q + 1, more);
10212                 } else {
10213                         q++;
10214                         if (c == '\n') {
10215                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10216                                 break;
10217                         }
10218                 }
10219
10220                 if (more <= 0) {
10221                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10222                         if (g_parsefile->left_in_line < 0)
10223                                 goto again;
10224                         break;
10225                 }
10226         }
10227         g_parsefile->left_in_buffer = more;
10228
10229         if (vflag) {
10230                 char save = *q;
10231                 *q = '\0';
10232                 out2str(g_parsefile->next_to_pgetc);
10233                 *q = save;
10234         }
10235
10236         pgetc_debug("preadbuffer at %d:%p'%s'",
10237                         g_parsefile->left_in_line,
10238                         g_parsefile->next_to_pgetc,
10239                         g_parsefile->next_to_pgetc);
10240         return (unsigned char)*g_parsefile->next_to_pgetc++;
10241 }
10242
10243 static void
10244 nlprompt(void)
10245 {
10246         g_parsefile->linno++;
10247         setprompt_if(doprompt, 2);
10248 }
10249 static void
10250 nlnoprompt(void)
10251 {
10252         g_parsefile->linno++;
10253         needprompt = doprompt;
10254 }
10255
10256 static int
10257 pgetc(void)
10258 {
10259         int c;
10260
10261         pgetc_debug("pgetc at %d:%p'%s'",
10262                         g_parsefile->left_in_line,
10263                         g_parsefile->next_to_pgetc,
10264                         g_parsefile->next_to_pgetc);
10265         if (g_parsefile->unget)
10266                 return g_parsefile->lastc[--g_parsefile->unget];
10267
10268         if (--g_parsefile->left_in_line >= 0)
10269                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10270         else
10271                 c = preadbuffer();
10272
10273         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10274         g_parsefile->lastc[0] = c;
10275
10276         return c;
10277 }
10278
10279 #if ENABLE_ASH_ALIAS
10280 static int
10281 pgetc_without_PEOA(void)
10282 {
10283         int c;
10284         do {
10285                 pgetc_debug("pgetc at %d:%p'%s'",
10286                                 g_parsefile->left_in_line,
10287                                 g_parsefile->next_to_pgetc,
10288                                 g_parsefile->next_to_pgetc);
10289                 c = pgetc();
10290         } while (c == PEOA);
10291         return c;
10292 }
10293 #else
10294 # define pgetc_without_PEOA() pgetc()
10295 #endif
10296
10297 /*
10298  * Read a line from the script.
10299  */
10300 static char *
10301 pfgets(char *line, int len)
10302 {
10303         char *p = line;
10304         int nleft = len;
10305         int c;
10306
10307         while (--nleft > 0) {
10308                 c = pgetc_without_PEOA();
10309                 if (c == PEOF) {
10310                         if (p == line)
10311                                 return NULL;
10312                         break;
10313                 }
10314                 *p++ = c;
10315                 if (c == '\n')
10316                         break;
10317         }
10318         *p = '\0';
10319         return line;
10320 }
10321
10322 /*
10323  * Undo a call to pgetc.  Only two characters may be pushed back.
10324  * PEOF may be pushed back.
10325  */
10326 static void
10327 pungetc(void)
10328 {
10329         g_parsefile->unget++;
10330 }
10331
10332 /* This one eats backslash+newline */
10333 static int
10334 pgetc_eatbnl(void)
10335 {
10336         int c;
10337
10338         while ((c = pgetc()) == '\\') {
10339                 if (pgetc() != '\n') {
10340                         pungetc();
10341                         break;
10342                 }
10343
10344                 nlprompt();
10345         }
10346
10347         return c;
10348 }
10349
10350 /*
10351  * To handle the "." command, a stack of input files is used.  Pushfile
10352  * adds a new entry to the stack and popfile restores the previous level.
10353  */
10354 static void
10355 pushfile(void)
10356 {
10357         struct parsefile *pf;
10358
10359         pf = ckzalloc(sizeof(*pf));
10360         pf->prev = g_parsefile;
10361         pf->pf_fd = -1;
10362         /*pf->strpush = NULL; - ckzalloc did it */
10363         /*pf->basestrpush.prev = NULL;*/
10364         /*pf->unget = 0;*/
10365         g_parsefile = pf;
10366 }
10367
10368 static void
10369 popfile(void)
10370 {
10371         struct parsefile *pf = g_parsefile;
10372
10373         if (pf == &basepf)
10374                 return;
10375
10376         INT_OFF;
10377         if (pf->pf_fd >= 0)
10378                 close(pf->pf_fd);
10379         free(pf->buf);
10380         while (pf->strpush)
10381                 popstring();
10382         g_parsefile = pf->prev;
10383         free(pf);
10384         INT_ON;
10385 }
10386
10387 /*
10388  * Return to top level.
10389  */
10390 static void
10391 popallfiles(void)
10392 {
10393         while (g_parsefile != &basepf)
10394                 popfile();
10395 }
10396
10397 /*
10398  * Close the file(s) that the shell is reading commands from.  Called
10399  * after a fork is done.
10400  */
10401 static void
10402 closescript(void)
10403 {
10404         popallfiles();
10405         if (g_parsefile->pf_fd > 0) {
10406                 close(g_parsefile->pf_fd);
10407                 g_parsefile->pf_fd = 0;
10408         }
10409 }
10410
10411 /*
10412  * Like setinputfile, but takes an open file descriptor.  Call this with
10413  * interrupts off.
10414  */
10415 static void
10416 setinputfd(int fd, int push)
10417 {
10418         if (push) {
10419                 pushfile();
10420                 g_parsefile->buf = NULL;
10421         }
10422         g_parsefile->pf_fd = fd;
10423         if (g_parsefile->buf == NULL)
10424                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10425         g_parsefile->left_in_buffer = 0;
10426         g_parsefile->left_in_line = 0;
10427         g_parsefile->linno = 1;
10428 }
10429
10430 /*
10431  * Set the input to take input from a file.  If push is set, push the
10432  * old input onto the stack first.
10433  */
10434 static int
10435 setinputfile(const char *fname, int flags)
10436 {
10437         int fd;
10438
10439         INT_OFF;
10440         fd = open(fname, O_RDONLY);
10441         if (fd < 0) {
10442                 if (flags & INPUT_NOFILE_OK)
10443                         goto out;
10444                 exitstatus = 127;
10445                 ash_msg_and_raise_error("can't open '%s'", fname);
10446         }
10447         if (fd < 10)
10448                 fd = savefd(fd);
10449         else
10450                 close_on_exec_on(fd);
10451         setinputfd(fd, flags & INPUT_PUSH_FILE);
10452  out:
10453         INT_ON;
10454         return fd;
10455 }
10456
10457 /*
10458  * Like setinputfile, but takes input from a string.
10459  */
10460 static void
10461 setinputstring(char *string)
10462 {
10463         INT_OFF;
10464         pushfile();
10465         g_parsefile->next_to_pgetc = string;
10466         g_parsefile->left_in_line = strlen(string);
10467         g_parsefile->buf = NULL;
10468         g_parsefile->linno = 1;
10469         INT_ON;
10470 }
10471
10472
10473 /*
10474  * Routines to check for mail.
10475  */
10476
10477 #if ENABLE_ASH_MAIL
10478
10479 /* Hash of mtimes of mailboxes */
10480 static unsigned mailtime_hash;
10481 /* Set if MAIL or MAILPATH is changed. */
10482 static smallint mail_var_path_changed;
10483
10484 /*
10485  * Print appropriate message(s) if mail has arrived.
10486  * If mail_var_path_changed is set,
10487  * then the value of MAIL has mail_var_path_changed,
10488  * so we just update the values.
10489  */
10490 static void
10491 chkmail(void)
10492 {
10493         const char *mpath;
10494         char *p;
10495         char *q;
10496         unsigned new_hash;
10497         struct stackmark smark;
10498         struct stat statb;
10499
10500         setstackmark(&smark);
10501         mpath = mpathset() ? mpathval() : mailval();
10502         new_hash = 0;
10503         for (;;) {
10504                 p = path_advance(&mpath, nullstr);
10505                 if (p == NULL)
10506                         break;
10507                 if (*p == '\0')
10508                         continue;
10509                 for (q = p; *q; q++)
10510                         continue;
10511 #if DEBUG
10512                 if (q[-1] != '/')
10513                         abort();
10514 #endif
10515                 q[-1] = '\0';                   /* delete trailing '/' */
10516                 if (stat(p, &statb) < 0) {
10517                         continue;
10518                 }
10519                 /* Very simplistic "hash": just a sum of all mtimes */
10520                 new_hash += (unsigned)statb.st_mtime;
10521         }
10522         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10523                 if (mailtime_hash != 0)
10524                         out2str("you have mail\n");
10525                 mailtime_hash = new_hash;
10526         }
10527         mail_var_path_changed = 0;
10528         popstackmark(&smark);
10529 }
10530
10531 static void FAST_FUNC
10532 changemail(const char *val UNUSED_PARAM)
10533 {
10534         mail_var_path_changed = 1;
10535 }
10536
10537 #endif /* ASH_MAIL */
10538
10539
10540 /* ============ ??? */
10541
10542 /*
10543  * Set the shell parameters.
10544  */
10545 static void
10546 setparam(char **argv)
10547 {
10548         char **newparam;
10549         char **ap;
10550         int nparam;
10551
10552         for (nparam = 0; argv[nparam]; nparam++)
10553                 continue;
10554         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10555         while (*argv) {
10556                 *ap++ = ckstrdup(*argv++);
10557         }
10558         *ap = NULL;
10559         freeparam(&shellparam);
10560         shellparam.malloced = 1;
10561         shellparam.nparam = nparam;
10562         shellparam.p = newparam;
10563 #if ENABLE_ASH_GETOPTS
10564         shellparam.optind = 1;
10565         shellparam.optoff = -1;
10566 #endif
10567 }
10568
10569 /*
10570  * Process shell options.  The global variable argptr contains a pointer
10571  * to the argument list; we advance it past the options.
10572  *
10573  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10574  * For a non-interactive shell, an error condition encountered
10575  * by a special built-in ... shall cause the shell to write a diagnostic message
10576  * to standard error and exit as shown in the following table:
10577  * Error                                           Special Built-In
10578  * ...
10579  * Utility syntax error (option or operand error)  Shall exit
10580  * ...
10581  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10582  * we see that bash does not do that (set "finishes" with error code 1 instead,
10583  * and shell continues), and people rely on this behavior!
10584  * Testcase:
10585  * set -o barfoo 2>/dev/null
10586  * echo $?
10587  *
10588  * Oh well. Let's mimic that.
10589  */
10590 static int
10591 plus_minus_o(char *name, int val)
10592 {
10593         int i;
10594
10595         if (name) {
10596                 for (i = 0; i < NOPTS; i++) {
10597                         if (strcmp(name, optnames(i)) == 0) {
10598                                 optlist[i] = val;
10599                                 return 0;
10600                         }
10601                 }
10602                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10603                 return 1;
10604         }
10605         for (i = 0; i < NOPTS; i++) {
10606                 if (val) {
10607                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10608                 } else {
10609                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10610                 }
10611         }
10612         return 0;
10613 }
10614 static void
10615 setoption(int flag, int val)
10616 {
10617         int i;
10618
10619         for (i = 0; i < NOPTS; i++) {
10620                 if (optletters(i) == flag) {
10621                         optlist[i] = val;
10622                         return;
10623                 }
10624         }
10625         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10626         /* NOTREACHED */
10627 }
10628 static int
10629 options(int cmdline)
10630 {
10631         char *p;
10632         int val;
10633         int c;
10634
10635         if (cmdline)
10636                 minusc = NULL;
10637         while ((p = *argptr) != NULL) {
10638                 c = *p++;
10639                 if (c != '-' && c != '+')
10640                         break;
10641                 argptr++;
10642                 val = 0; /* val = 0 if c == '+' */
10643                 if (c == '-') {
10644                         val = 1;
10645                         if (p[0] == '\0' || LONE_DASH(p)) {
10646                                 if (!cmdline) {
10647                                         /* "-" means turn off -x and -v */
10648                                         if (p[0] == '\0')
10649                                                 xflag = vflag = 0;
10650                                         /* "--" means reset params */
10651                                         else if (*argptr == NULL)
10652                                                 setparam(argptr);
10653                                 }
10654                                 break;    /* "-" or "--" terminates options */
10655                         }
10656                 }
10657                 /* first char was + or - */
10658                 while ((c = *p++) != '\0') {
10659                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10660                         if (c == 'c' && cmdline) {
10661                                 minusc = p;     /* command is after shell args */
10662                         } else if (c == 'o') {
10663                                 if (plus_minus_o(*argptr, val)) {
10664                                         /* it already printed err message */
10665                                         return 1; /* error */
10666                                 }
10667                                 if (*argptr)
10668                                         argptr++;
10669                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10670                                 isloginsh = 1;
10671                         /* bash does not accept +-login, we also won't */
10672                         } else if (cmdline && val && (c == '-')) { /* long options */
10673                                 if (strcmp(p, "login") == 0)
10674                                         isloginsh = 1;
10675                                 break;
10676                         } else {
10677                                 setoption(c, val);
10678                         }
10679                 }
10680         }
10681         return 0;
10682 }
10683
10684 /*
10685  * The shift builtin command.
10686  */
10687 static int FAST_FUNC
10688 shiftcmd(int argc UNUSED_PARAM, char **argv)
10689 {
10690         int n;
10691         char **ap1, **ap2;
10692
10693         n = 1;
10694         if (argv[1])
10695                 n = number(argv[1]);
10696         if (n > shellparam.nparam)
10697                 n = 0; /* bash compat, was = shellparam.nparam; */
10698         INT_OFF;
10699         shellparam.nparam -= n;
10700         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10701                 if (shellparam.malloced)
10702                         free(*ap1);
10703         }
10704         ap2 = shellparam.p;
10705         while ((*ap2++ = *ap1++) != NULL)
10706                 continue;
10707 #if ENABLE_ASH_GETOPTS
10708         shellparam.optind = 1;
10709         shellparam.optoff = -1;
10710 #endif
10711         INT_ON;
10712         return 0;
10713 }
10714
10715 /*
10716  * POSIX requires that 'set' (but not export or readonly) output the
10717  * variables in lexicographic order - by the locale's collating order (sigh).
10718  * Maybe we could keep them in an ordered balanced binary tree
10719  * instead of hashed lists.
10720  * For now just roll 'em through qsort for printing...
10721  */
10722 static int
10723 showvars(const char *sep_prefix, int on, int off)
10724 {
10725         const char *sep;
10726         char **ep, **epend;
10727
10728         ep = listvars(on, off, &epend);
10729         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10730
10731         sep = *sep_prefix ? " " : sep_prefix;
10732
10733         for (; ep < epend; ep++) {
10734                 const char *p;
10735                 const char *q;
10736
10737                 p = strchrnul(*ep, '=');
10738                 q = nullstr;
10739                 if (*p)
10740                         q = single_quote(++p);
10741                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10742         }
10743         return 0;
10744 }
10745
10746 /*
10747  * The set command builtin.
10748  */
10749 static int FAST_FUNC
10750 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10751 {
10752         int retval;
10753
10754         if (!argv[1])
10755                 return showvars(nullstr, 0, VUNSET);
10756
10757         INT_OFF;
10758         retval = options(/*cmdline:*/ 0);
10759         if (retval == 0) { /* if no parse error... */
10760                 optschanged();
10761                 if (*argptr != NULL) {
10762                         setparam(argptr);
10763                 }
10764         }
10765         INT_ON;
10766         return retval;
10767 }
10768
10769 #if ENABLE_ASH_RANDOM_SUPPORT
10770 static void FAST_FUNC
10771 change_random(const char *value)
10772 {
10773         uint32_t t;
10774
10775         if (value == NULL) {
10776                 /* "get", generate */
10777                 t = next_random(&random_gen);
10778                 /* set without recursion */
10779                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10780                 vrandom.flags &= ~VNOFUNC;
10781         } else {
10782                 /* set/reset */
10783                 t = strtoul(value, NULL, 10);
10784                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10785         }
10786 }
10787 #endif
10788
10789 #if ENABLE_ASH_GETOPTS
10790 static int
10791 getopts(char *optstr, char *optvar, char **optfirst)
10792 {
10793         char *p, *q;
10794         char c = '?';
10795         int done = 0;
10796         char sbuf[2];
10797         char **optnext;
10798         int ind = shellparam.optind;
10799         int off = shellparam.optoff;
10800
10801         sbuf[1] = '\0';
10802
10803         shellparam.optind = -1;
10804         optnext = optfirst + ind - 1;
10805
10806         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10807                 p = NULL;
10808         else
10809                 p = optnext[-1] + off;
10810         if (p == NULL || *p == '\0') {
10811                 /* Current word is done, advance */
10812                 p = *optnext;
10813                 if (p == NULL || *p != '-' || *++p == '\0') {
10814  atend:
10815                         p = NULL;
10816                         done = 1;
10817                         goto out;
10818                 }
10819                 optnext++;
10820                 if (LONE_DASH(p))        /* check for "--" */
10821                         goto atend;
10822         }
10823
10824         c = *p++;
10825         for (q = optstr; *q != c;) {
10826                 if (*q == '\0') {
10827                         if (optstr[0] == ':') {
10828                                 sbuf[0] = c;
10829                                 /*sbuf[1] = '\0'; - already is */
10830                                 setvar0("OPTARG", sbuf);
10831                         } else {
10832                                 fprintf(stderr, "Illegal option -%c\n", c);
10833                                 unsetvar("OPTARG");
10834                         }
10835                         c = '?';
10836                         goto out;
10837                 }
10838                 if (*++q == ':')
10839                         q++;
10840         }
10841
10842         if (*++q == ':') {
10843                 if (*p == '\0' && (p = *optnext) == NULL) {
10844                         if (optstr[0] == ':') {
10845                                 sbuf[0] = c;
10846                                 /*sbuf[1] = '\0'; - already is */
10847                                 setvar0("OPTARG", sbuf);
10848                                 c = ':';
10849                         } else {
10850                                 fprintf(stderr, "No arg for -%c option\n", c);
10851                                 unsetvar("OPTARG");
10852                                 c = '?';
10853                         }
10854                         goto out;
10855                 }
10856
10857                 if (p == *optnext)
10858                         optnext++;
10859                 setvar0("OPTARG", p);
10860                 p = NULL;
10861         } else
10862                 setvar0("OPTARG", nullstr);
10863  out:
10864         ind = optnext - optfirst + 1;
10865         setvar("OPTIND", itoa(ind), VNOFUNC);
10866         sbuf[0] = c;
10867         /*sbuf[1] = '\0'; - already is */
10868         setvar0(optvar, sbuf);
10869
10870         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10871         shellparam.optind = ind;
10872
10873         return done;
10874 }
10875
10876 /*
10877  * The getopts builtin.  Shellparam.optnext points to the next argument
10878  * to be processed.  Shellparam.optptr points to the next character to
10879  * be processed in the current argument.  If shellparam.optnext is NULL,
10880  * then it's the first time getopts has been called.
10881  */
10882 static int FAST_FUNC
10883 getoptscmd(int argc, char **argv)
10884 {
10885         char **optbase;
10886
10887         if (argc < 3)
10888                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10889         if (argc == 3) {
10890                 optbase = shellparam.p;
10891                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10892                         shellparam.optind = 1;
10893                         shellparam.optoff = -1;
10894                 }
10895         } else {
10896                 optbase = &argv[3];
10897                 if ((unsigned)shellparam.optind > argc - 2) {
10898                         shellparam.optind = 1;
10899                         shellparam.optoff = -1;
10900                 }
10901         }
10902
10903         return getopts(argv[1], argv[2], optbase);
10904 }
10905 #endif /* ASH_GETOPTS */
10906
10907
10908 /* ============ Shell parser */
10909
10910 struct heredoc {
10911         struct heredoc *next;   /* next here document in list */
10912         union node *here;       /* redirection node */
10913         char *eofmark;          /* string indicating end of input */
10914         smallint striptabs;     /* if set, strip leading tabs */
10915 };
10916
10917 static smallint tokpushback;           /* last token pushed back */
10918 static smallint quoteflag;             /* set if (part of) last token was quoted */
10919 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10920 static struct heredoc *heredoclist;    /* list of here documents to read */
10921 static char *wordtext;                 /* text of last word returned by readtoken */
10922 static struct nodelist *backquotelist;
10923 static union node *redirnode;
10924 static struct heredoc *heredoc;
10925
10926 static const char *
10927 tokname(char *buf, int tok)
10928 {
10929         if (tok < TSEMI)
10930                 return tokname_array[tok];
10931         sprintf(buf, "\"%s\"", tokname_array[tok]);
10932         return buf;
10933 }
10934
10935 /* raise_error_unexpected_syntax:
10936  * Called when an unexpected token is read during the parse.  The argument
10937  * is the token that is expected, or -1 if more than one type of token can
10938  * occur at this point.
10939  */
10940 static void raise_error_unexpected_syntax(int) NORETURN;
10941 static void
10942 raise_error_unexpected_syntax(int token)
10943 {
10944         char msg[64];
10945         char buf[16];
10946         int l;
10947
10948         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10949         if (token >= 0)
10950                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10951         raise_error_syntax(msg);
10952         /* NOTREACHED */
10953 }
10954
10955 #define EOFMARKLEN 79
10956
10957 /* parsing is heavily cross-recursive, need these forward decls */
10958 static union node *andor(void);
10959 static union node *pipeline(void);
10960 static union node *parse_command(void);
10961 static void parseheredoc(void);
10962 static int peektoken(void);
10963 static int readtoken(void);
10964
10965 static union node *
10966 list(int nlflag)
10967 {
10968         union node *n1, *n2, *n3;
10969         int tok;
10970
10971         n1 = NULL;
10972         for (;;) {
10973                 switch (peektoken()) {
10974                 case TNL:
10975                         if (!(nlflag & 1))
10976                                 break;
10977                         parseheredoc();
10978                         return n1;
10979
10980                 case TEOF:
10981                         if (!n1 && (nlflag & 1))
10982                                 n1 = NODE_EOF;
10983                         parseheredoc();
10984                         return n1;
10985                 }
10986
10987                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10988                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
10989                         return n1;
10990                 nlflag |= 2;
10991
10992                 n2 = andor();
10993                 tok = readtoken();
10994                 if (tok == TBACKGND) {
10995                         if (n2->type == NPIPE) {
10996                                 n2->npipe.pipe_backgnd = 1;
10997                         } else {
10998                                 if (n2->type != NREDIR) {
10999                                         n3 = stzalloc(sizeof(struct nredir));
11000                                         n3->nredir.n = n2;
11001                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11002                                         n2 = n3;
11003                                 }
11004                                 n2->type = NBACKGND;
11005                         }
11006                 }
11007                 if (n1 == NULL) {
11008                         n1 = n2;
11009                 } else {
11010                         n3 = stzalloc(sizeof(struct nbinary));
11011                         n3->type = NSEMI;
11012                         n3->nbinary.ch1 = n1;
11013                         n3->nbinary.ch2 = n2;
11014                         n1 = n3;
11015                 }
11016                 switch (tok) {
11017                 case TNL:
11018                 case TEOF:
11019                         tokpushback = 1;
11020                         /* fall through */
11021                 case TBACKGND:
11022                 case TSEMI:
11023                         break;
11024                 default:
11025                         if ((nlflag & 1))
11026                                 raise_error_unexpected_syntax(-1);
11027                         tokpushback = 1;
11028                         return n1;
11029                 }
11030         }
11031 }
11032
11033 static union node *
11034 andor(void)
11035 {
11036         union node *n1, *n2, *n3;
11037         int t;
11038
11039         n1 = pipeline();
11040         for (;;) {
11041                 t = readtoken();
11042                 if (t == TAND) {
11043                         t = NAND;
11044                 } else if (t == TOR) {
11045                         t = NOR;
11046                 } else {
11047                         tokpushback = 1;
11048                         return n1;
11049                 }
11050                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11051                 n2 = pipeline();
11052                 n3 = stzalloc(sizeof(struct nbinary));
11053                 n3->type = t;
11054                 n3->nbinary.ch1 = n1;
11055                 n3->nbinary.ch2 = n2;
11056                 n1 = n3;
11057         }
11058 }
11059
11060 static union node *
11061 pipeline(void)
11062 {
11063         union node *n1, *n2, *pipenode;
11064         struct nodelist *lp, *prev;
11065         int negate;
11066
11067         negate = 0;
11068         TRACE(("pipeline: entered\n"));
11069         if (readtoken() == TNOT) {
11070                 negate = !negate;
11071                 checkkwd = CHKKWD | CHKALIAS;
11072         } else
11073                 tokpushback = 1;
11074         n1 = parse_command();
11075         if (readtoken() == TPIPE) {
11076                 pipenode = stzalloc(sizeof(struct npipe));
11077                 pipenode->type = NPIPE;
11078                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11079                 lp = stzalloc(sizeof(struct nodelist));
11080                 pipenode->npipe.cmdlist = lp;
11081                 lp->n = n1;
11082                 do {
11083                         prev = lp;
11084                         lp = stzalloc(sizeof(struct nodelist));
11085                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11086                         lp->n = parse_command();
11087                         prev->next = lp;
11088                 } while (readtoken() == TPIPE);
11089                 lp->next = NULL;
11090                 n1 = pipenode;
11091         }
11092         tokpushback = 1;
11093         if (negate) {
11094                 n2 = stzalloc(sizeof(struct nnot));
11095                 n2->type = NNOT;
11096                 n2->nnot.com = n1;
11097                 return n2;
11098         }
11099         return n1;
11100 }
11101
11102 static union node *
11103 makename(void)
11104 {
11105         union node *n;
11106
11107         n = stzalloc(sizeof(struct narg));
11108         n->type = NARG;
11109         /*n->narg.next = NULL; - stzalloc did it */
11110         n->narg.text = wordtext;
11111         n->narg.backquote = backquotelist;
11112         return n;
11113 }
11114
11115 static void
11116 fixredir(union node *n, const char *text, int err)
11117 {
11118         int fd;
11119
11120         TRACE(("Fix redir %s %d\n", text, err));
11121         if (!err)
11122                 n->ndup.vname = NULL;
11123
11124         fd = bb_strtou(text, NULL, 10);
11125         if (!errno && fd >= 0)
11126                 n->ndup.dupfd = fd;
11127         else if (LONE_DASH(text))
11128                 n->ndup.dupfd = -1;
11129         else {
11130                 if (err)
11131                         raise_error_syntax("bad fd number");
11132                 n->ndup.vname = makename();
11133         }
11134 }
11135
11136 /*
11137  * Returns true if the text contains nothing to expand (no dollar signs
11138  * or backquotes).
11139  */
11140 static int
11141 noexpand(const char *text)
11142 {
11143         unsigned char c;
11144
11145         while ((c = *text++) != '\0') {
11146                 if (c == CTLQUOTEMARK)
11147                         continue;
11148                 if (c == CTLESC)
11149                         text++;
11150                 else if (SIT(c, BASESYNTAX) == CCTL)
11151                         return 0;
11152         }
11153         return 1;
11154 }
11155
11156 static void
11157 parsefname(void)
11158 {
11159         union node *n = redirnode;
11160
11161         if (readtoken() != TWORD)
11162                 raise_error_unexpected_syntax(-1);
11163         if (n->type == NHERE) {
11164                 struct heredoc *here = heredoc;
11165                 struct heredoc *p;
11166                 int i;
11167
11168                 if (quoteflag == 0)
11169                         n->type = NXHERE;
11170                 TRACE(("Here document %d\n", n->type));
11171                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
11172                         raise_error_syntax("illegal eof marker for << redirection");
11173                 rmescapes(wordtext, 0);
11174                 here->eofmark = wordtext;
11175                 here->next = NULL;
11176                 if (heredoclist == NULL)
11177                         heredoclist = here;
11178                 else {
11179                         for (p = heredoclist; p->next; p = p->next)
11180                                 continue;
11181                         p->next = here;
11182                 }
11183         } else if (n->type == NTOFD || n->type == NFROMFD) {
11184                 fixredir(n, wordtext, 0);
11185         } else {
11186                 n->nfile.fname = makename();
11187         }
11188 }
11189
11190 static union node *
11191 simplecmd(void)
11192 {
11193         union node *args, **app;
11194         union node *n = NULL;
11195         union node *vars, **vpp;
11196         union node **rpp, *redir;
11197         int savecheckkwd;
11198 #if BASH_TEST2
11199         smallint double_brackets_flag = 0;
11200 #endif
11201         IF_BASH_FUNCTION(smallint function_flag = 0;)
11202
11203         args = NULL;
11204         app = &args;
11205         vars = NULL;
11206         vpp = &vars;
11207         redir = NULL;
11208         rpp = &redir;
11209
11210         savecheckkwd = CHKALIAS;
11211         for (;;) {
11212                 int t;
11213                 checkkwd = savecheckkwd;
11214                 t = readtoken();
11215                 switch (t) {
11216 #if BASH_FUNCTION
11217                 case TFUNCTION:
11218                         if (peektoken() != TWORD)
11219                                 raise_error_unexpected_syntax(TWORD);
11220                         function_flag = 1;
11221                         break;
11222 #endif
11223 #if BASH_TEST2
11224                 case TAND: /* "&&" */
11225                 case TOR: /* "||" */
11226                         if (!double_brackets_flag) {
11227                                 tokpushback = 1;
11228                                 goto out;
11229                         }
11230                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11231 #endif
11232                 case TWORD:
11233                         n = stzalloc(sizeof(struct narg));
11234                         n->type = NARG;
11235                         /*n->narg.next = NULL; - stzalloc did it */
11236                         n->narg.text = wordtext;
11237 #if BASH_TEST2
11238                         if (strcmp("[[", wordtext) == 0)
11239                                 double_brackets_flag = 1;
11240                         else if (strcmp("]]", wordtext) == 0)
11241                                 double_brackets_flag = 0;
11242 #endif
11243                         n->narg.backquote = backquotelist;
11244                         if (savecheckkwd && isassignment(wordtext)) {
11245                                 *vpp = n;
11246                                 vpp = &n->narg.next;
11247                         } else {
11248                                 *app = n;
11249                                 app = &n->narg.next;
11250                                 savecheckkwd = 0;
11251                         }
11252 #if BASH_FUNCTION
11253                         if (function_flag) {
11254                                 checkkwd = CHKNL | CHKKWD;
11255                                 switch (peektoken()) {
11256                                 case TBEGIN:
11257                                 case TIF:
11258                                 case TCASE:
11259                                 case TUNTIL:
11260                                 case TWHILE:
11261                                 case TFOR:
11262                                         goto do_func;
11263                                 case TLP:
11264                                         function_flag = 0;
11265                                         break;
11266                                 case TWORD:
11267                                         if (strcmp("[[", wordtext) == 0)
11268                                                 goto do_func;
11269                                         /* fall through */
11270                                 default:
11271                                         raise_error_unexpected_syntax(-1);
11272                                 }
11273                         }
11274 #endif
11275                         break;
11276                 case TREDIR:
11277                         *rpp = n = redirnode;
11278                         rpp = &n->nfile.next;
11279                         parsefname();   /* read name of redirection file */
11280                         break;
11281                 case TLP:
11282  IF_BASH_FUNCTION(do_func:)
11283                         if (args && app == &args->narg.next
11284                          && !vars && !redir
11285                         ) {
11286                                 struct builtincmd *bcmd;
11287                                 const char *name;
11288
11289                                 /* We have a function */
11290                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11291                                         raise_error_unexpected_syntax(TRP);
11292                                 name = n->narg.text;
11293                                 if (!goodname(name)
11294                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11295                                 ) {
11296                                         raise_error_syntax("bad function name");
11297                                 }
11298                                 n->type = NDEFUN;
11299                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11300                                 n->narg.next = parse_command();
11301                                 return n;
11302                         }
11303                         IF_BASH_FUNCTION(function_flag = 0;)
11304                         /* fall through */
11305                 default:
11306                         tokpushback = 1;
11307                         goto out;
11308                 }
11309         }
11310  out:
11311         *app = NULL;
11312         *vpp = NULL;
11313         *rpp = NULL;
11314         n = stzalloc(sizeof(struct ncmd));
11315         n->type = NCMD;
11316         n->ncmd.args = args;
11317         n->ncmd.assign = vars;
11318         n->ncmd.redirect = redir;
11319         return n;
11320 }
11321
11322 static union node *
11323 parse_command(void)
11324 {
11325         union node *n1, *n2;
11326         union node *ap, **app;
11327         union node *cp, **cpp;
11328         union node *redir, **rpp;
11329         union node **rpp2;
11330         int t;
11331
11332         redir = NULL;
11333         rpp2 = &redir;
11334
11335         switch (readtoken()) {
11336         default:
11337                 raise_error_unexpected_syntax(-1);
11338                 /* NOTREACHED */
11339         case TIF:
11340                 n1 = stzalloc(sizeof(struct nif));
11341                 n1->type = NIF;
11342                 n1->nif.test = list(0);
11343                 if (readtoken() != TTHEN)
11344                         raise_error_unexpected_syntax(TTHEN);
11345                 n1->nif.ifpart = list(0);
11346                 n2 = n1;
11347                 while (readtoken() == TELIF) {
11348                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11349                         n2 = n2->nif.elsepart;
11350                         n2->type = NIF;
11351                         n2->nif.test = list(0);
11352                         if (readtoken() != TTHEN)
11353                                 raise_error_unexpected_syntax(TTHEN);
11354                         n2->nif.ifpart = list(0);
11355                 }
11356                 if (lasttoken == TELSE)
11357                         n2->nif.elsepart = list(0);
11358                 else {
11359                         n2->nif.elsepart = NULL;
11360                         tokpushback = 1;
11361                 }
11362                 t = TFI;
11363                 break;
11364         case TWHILE:
11365         case TUNTIL: {
11366                 int got;
11367                 n1 = stzalloc(sizeof(struct nbinary));
11368                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11369                 n1->nbinary.ch1 = list(0);
11370                 got = readtoken();
11371                 if (got != TDO) {
11372                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11373                                         got == TWORD ? wordtext : ""));
11374                         raise_error_unexpected_syntax(TDO);
11375                 }
11376                 n1->nbinary.ch2 = list(0);
11377                 t = TDONE;
11378                 break;
11379         }
11380         case TFOR:
11381                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11382                         raise_error_syntax("bad for loop variable");
11383                 n1 = stzalloc(sizeof(struct nfor));
11384                 n1->type = NFOR;
11385                 n1->nfor.var = wordtext;
11386                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11387                 if (readtoken() == TIN) {
11388                         app = &ap;
11389                         while (readtoken() == TWORD) {
11390                                 n2 = stzalloc(sizeof(struct narg));
11391                                 n2->type = NARG;
11392                                 /*n2->narg.next = NULL; - stzalloc did it */
11393                                 n2->narg.text = wordtext;
11394                                 n2->narg.backquote = backquotelist;
11395                                 *app = n2;
11396                                 app = &n2->narg.next;
11397                         }
11398                         *app = NULL;
11399                         n1->nfor.args = ap;
11400                         if (lasttoken != TNL && lasttoken != TSEMI)
11401                                 raise_error_unexpected_syntax(-1);
11402                 } else {
11403                         n2 = stzalloc(sizeof(struct narg));
11404                         n2->type = NARG;
11405                         /*n2->narg.next = NULL; - stzalloc did it */
11406                         n2->narg.text = (char *)dolatstr;
11407                         /*n2->narg.backquote = NULL;*/
11408                         n1->nfor.args = n2;
11409                         /*
11410                          * Newline or semicolon here is optional (but note
11411                          * that the original Bourne shell only allowed NL).
11412                          */
11413                         if (lasttoken != TSEMI)
11414                                 tokpushback = 1;
11415                 }
11416                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11417                 if (readtoken() != TDO)
11418                         raise_error_unexpected_syntax(TDO);
11419                 n1->nfor.body = list(0);
11420                 t = TDONE;
11421                 break;
11422         case TCASE:
11423                 n1 = stzalloc(sizeof(struct ncase));
11424                 n1->type = NCASE;
11425                 if (readtoken() != TWORD)
11426                         raise_error_unexpected_syntax(TWORD);
11427                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11428                 n2->type = NARG;
11429                 /*n2->narg.next = NULL; - stzalloc did it */
11430                 n2->narg.text = wordtext;
11431                 n2->narg.backquote = backquotelist;
11432                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11433                 if (readtoken() != TIN)
11434                         raise_error_unexpected_syntax(TIN);
11435                 cpp = &n1->ncase.cases;
11436  next_case:
11437                 checkkwd = CHKNL | CHKKWD;
11438                 t = readtoken();
11439                 while (t != TESAC) {
11440                         if (lasttoken == TLP)
11441                                 readtoken();
11442                         *cpp = cp = stzalloc(sizeof(struct nclist));
11443                         cp->type = NCLIST;
11444                         app = &cp->nclist.pattern;
11445                         for (;;) {
11446                                 *app = ap = stzalloc(sizeof(struct narg));
11447                                 ap->type = NARG;
11448                                 /*ap->narg.next = NULL; - stzalloc did it */
11449                                 ap->narg.text = wordtext;
11450                                 ap->narg.backquote = backquotelist;
11451                                 if (readtoken() != TPIPE)
11452                                         break;
11453                                 app = &ap->narg.next;
11454                                 readtoken();
11455                         }
11456                         //ap->narg.next = NULL;
11457                         if (lasttoken != TRP)
11458                                 raise_error_unexpected_syntax(TRP);
11459                         cp->nclist.body = list(2);
11460
11461                         cpp = &cp->nclist.next;
11462
11463                         checkkwd = CHKNL | CHKKWD;
11464                         t = readtoken();
11465                         if (t != TESAC) {
11466                                 if (t != TENDCASE)
11467                                         raise_error_unexpected_syntax(TENDCASE);
11468                                 goto next_case;
11469                         }
11470                 }
11471                 *cpp = NULL;
11472                 goto redir;
11473         case TLP:
11474                 n1 = stzalloc(sizeof(struct nredir));
11475                 n1->type = NSUBSHELL;
11476                 n1->nredir.n = list(0);
11477                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11478                 t = TRP;
11479                 break;
11480         case TBEGIN:
11481                 n1 = list(0);
11482                 t = TEND;
11483                 break;
11484         IF_BASH_FUNCTION(case TFUNCTION:)
11485         case TWORD:
11486         case TREDIR:
11487                 tokpushback = 1;
11488                 return simplecmd();
11489         }
11490
11491         if (readtoken() != t)
11492                 raise_error_unexpected_syntax(t);
11493
11494  redir:
11495         /* Now check for redirection which may follow command */
11496         checkkwd = CHKKWD | CHKALIAS;
11497         rpp = rpp2;
11498         while (readtoken() == TREDIR) {
11499                 *rpp = n2 = redirnode;
11500                 rpp = &n2->nfile.next;
11501                 parsefname();
11502         }
11503         tokpushback = 1;
11504         *rpp = NULL;
11505         if (redir) {
11506                 if (n1->type != NSUBSHELL) {
11507                         n2 = stzalloc(sizeof(struct nredir));
11508                         n2->type = NREDIR;
11509                         n2->nredir.n = n1;
11510                         n1 = n2;
11511                 }
11512                 n1->nredir.redirect = redir;
11513         }
11514         return n1;
11515 }
11516
11517 #if BASH_DOLLAR_SQUOTE
11518 static int
11519 decode_dollar_squote(void)
11520 {
11521         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11522         int c, cnt;
11523         char *p;
11524         char buf[4];
11525
11526         c = pgetc();
11527         p = strchr(C_escapes, c);
11528         if (p) {
11529                 buf[0] = c;
11530                 p = buf;
11531                 cnt = 3;
11532                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11533                         do {
11534                                 c = pgetc();
11535                                 *++p = c;
11536                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11537                         pungetc();
11538                 } else if (c == 'x') { /* \xHH */
11539                         do {
11540                                 c = pgetc();
11541                                 *++p = c;
11542                         } while (isxdigit(c) && --cnt);
11543                         pungetc();
11544                         if (cnt == 3) { /* \x but next char is "bad" */
11545                                 c = 'x';
11546                                 goto unrecognized;
11547                         }
11548                 } else { /* simple seq like \\ or \t */
11549                         p++;
11550                 }
11551                 *p = '\0';
11552                 p = buf;
11553                 c = bb_process_escape_sequence((void*)&p);
11554         } else { /* unrecognized "\z": print both chars unless ' or " */
11555                 if (c != '\'' && c != '"') {
11556  unrecognized:
11557                         c |= 0x100; /* "please encode \, then me" */
11558                 }
11559         }
11560         return c;
11561 }
11562 #endif
11563
11564 /*
11565  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11566  * is not NULL, read a here document.  In the latter case, eofmark is the
11567  * word which marks the end of the document and striptabs is true if
11568  * leading tabs should be stripped from the document.  The argument c
11569  * is the first character of the input token or document.
11570  *
11571  * Because C does not have internal subroutines, I have simulated them
11572  * using goto's to implement the subroutine linkage.  The following macros
11573  * will run code that appears at the end of readtoken1.
11574  */
11575 #define CHECKEND()      {goto checkend; checkend_return:;}
11576 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11577 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11578 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11579 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11580 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11581 static int
11582 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11583 {
11584         /* NB: syntax parameter fits into smallint */
11585         /* c parameter is an unsigned char or PEOF or PEOA */
11586         char *out;
11587         size_t len;
11588         char line[EOFMARKLEN + 1];
11589         struct nodelist *bqlist;
11590         smallint quotef;
11591         smallint dblquote;
11592         smallint oldstyle;
11593         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11594         smallint pssyntax;   /* we are expanding a prompt string */
11595         int varnest;         /* levels of variables expansion */
11596         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11597         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11598         int dqvarnest;       /* levels of variables expansion within double quotes */
11599
11600         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11601
11602         startlinno = g_parsefile->linno;
11603         bqlist = NULL;
11604         quotef = 0;
11605         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11606         pssyntax = (syntax == PSSYNTAX);
11607         if (pssyntax)
11608                 syntax = DQSYNTAX;
11609         dblquote = (syntax == DQSYNTAX);
11610         varnest = 0;
11611         IF_FEATURE_SH_MATH(arinest = 0;)
11612         IF_FEATURE_SH_MATH(parenlevel = 0;)
11613         dqvarnest = 0;
11614
11615         STARTSTACKSTR(out);
11616  loop:
11617         /* For each line, until end of word */
11618         CHECKEND();     /* set c to PEOF if at end of here document */
11619         for (;;) {      /* until end of line or end of word */
11620                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11621                 switch (SIT(c, syntax)) {
11622                 case CNL:       /* '\n' */
11623                         if (syntax == BASESYNTAX)
11624                                 goto endword;   /* exit outer loop */
11625                         USTPUTC(c, out);
11626                         nlprompt();
11627                         c = pgetc();
11628                         goto loop;              /* continue outer loop */
11629                 case CWORD:
11630                         USTPUTC(c, out);
11631                         break;
11632                 case CCTL:
11633 #if BASH_DOLLAR_SQUOTE
11634                         if (c == '\\' && bash_dollar_squote) {
11635                                 c = decode_dollar_squote();
11636                                 if (c == '\0') {
11637                                         /* skip $'\000', $'\x00' (like bash) */
11638                                         break;
11639                                 }
11640                                 if (c & 0x100) {
11641                                         /* Unknown escape. Encode as '\z' */
11642                                         c = (unsigned char)c;
11643                                         if (eofmark == NULL || dblquote)
11644                                                 USTPUTC(CTLESC, out);
11645                                         USTPUTC('\\', out);
11646                                 }
11647                         }
11648 #endif
11649                         if (eofmark == NULL || dblquote)
11650                                 USTPUTC(CTLESC, out);
11651                         USTPUTC(c, out);
11652                         break;
11653                 case CBACK:     /* backslash */
11654                         c = pgetc_without_PEOA();
11655                         if (c == PEOF) {
11656                                 USTPUTC(CTLESC, out);
11657                                 USTPUTC('\\', out);
11658                                 pungetc();
11659                         } else if (c == '\n') {
11660                                 nlprompt();
11661                         } else {
11662                                 if (c == '$' && pssyntax) {
11663                                         USTPUTC(CTLESC, out);
11664                                         USTPUTC('\\', out);
11665                                 }
11666                                 /* Backslash is retained if we are in "str" and next char isn't special */
11667                                 if (dblquote
11668                                  && c != '\\'
11669                                  && c != '`'
11670                                  && c != '$'
11671                                  && (c != '"' || eofmark != NULL)
11672                                 ) {
11673                                         USTPUTC('\\', out);
11674                                 }
11675                                 USTPUTC(CTLESC, out);
11676                                 USTPUTC(c, out);
11677                                 quotef = 1;
11678                         }
11679                         break;
11680                 case CSQUOTE:
11681                         syntax = SQSYNTAX;
11682  quotemark:
11683                         if (eofmark == NULL) {
11684                                 USTPUTC(CTLQUOTEMARK, out);
11685                         }
11686                         break;
11687                 case CDQUOTE:
11688                         syntax = DQSYNTAX;
11689                         dblquote = 1;
11690                         goto quotemark;
11691                 case CENDQUOTE:
11692                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11693                         if (eofmark != NULL && varnest == 0) {
11694                                 USTPUTC(c, out);
11695                         } else {
11696                                 if (dqvarnest == 0) {
11697                                         syntax = BASESYNTAX;
11698                                         dblquote = 0;
11699                                 }
11700                                 quotef = 1;
11701                                 goto quotemark;
11702                         }
11703                         break;
11704                 case CVAR:      /* '$' */
11705                         PARSESUB();             /* parse substitution */
11706                         break;
11707                 case CENDVAR:   /* '}' */
11708                         if (varnest > 0) {
11709                                 varnest--;
11710                                 if (dqvarnest > 0) {
11711                                         dqvarnest--;
11712                                 }
11713                                 c = CTLENDVAR;
11714                         }
11715                         USTPUTC(c, out);
11716                         break;
11717 #if ENABLE_FEATURE_SH_MATH
11718                 case CLP:       /* '(' in arithmetic */
11719                         parenlevel++;
11720                         USTPUTC(c, out);
11721                         break;
11722                 case CRP:       /* ')' in arithmetic */
11723                         if (parenlevel > 0) {
11724                                 parenlevel--;
11725                         } else {
11726                                 if (pgetc_eatbnl() == ')') {
11727                                         c = CTLENDARI;
11728                                         if (--arinest == 0) {
11729                                                 syntax = prevsyntax;
11730                                         }
11731                                 } else {
11732                                         /*
11733                                          * unbalanced parens
11734                                          * (don't 2nd guess - no error)
11735                                          */
11736                                         pungetc();
11737                                 }
11738                         }
11739                         USTPUTC(c, out);
11740                         break;
11741 #endif
11742                 case CBQUOTE:   /* '`' */
11743                         PARSEBACKQOLD();
11744                         break;
11745                 case CENDFILE:
11746                         goto endword;           /* exit outer loop */
11747                 case CIGN:
11748                         break;
11749                 default:
11750                         if (varnest == 0) {
11751 #if BASH_REDIR_OUTPUT
11752                                 if (c == '&') {
11753 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11754                                         if (pgetc() == '>')
11755                                                 c = 0x100 + '>'; /* flag &> */
11756                                         pungetc();
11757                                 }
11758 #endif
11759                                 goto endword;   /* exit outer loop */
11760                         }
11761                         IF_ASH_ALIAS(if (c != PEOA))
11762                                 USTPUTC(c, out);
11763                 }
11764                 c = pgetc();
11765         } /* for (;;) */
11766  endword:
11767
11768 #if ENABLE_FEATURE_SH_MATH
11769         if (syntax == ARISYNTAX)
11770                 raise_error_syntax("missing '))'");
11771 #endif
11772         if (syntax != BASESYNTAX && eofmark == NULL)
11773                 raise_error_syntax("unterminated quoted string");
11774         if (varnest != 0) {
11775                 startlinno = g_parsefile->linno;
11776                 /* { */
11777                 raise_error_syntax("missing '}'");
11778         }
11779         USTPUTC('\0', out);
11780         len = out - (char *)stackblock();
11781         out = stackblock();
11782         if (eofmark == NULL) {
11783                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11784                  && quotef == 0
11785                 ) {
11786                         if (isdigit_str9(out)) {
11787                                 PARSEREDIR(); /* passed as params: out, c */
11788                                 lasttoken = TREDIR;
11789                                 return lasttoken;
11790                         }
11791                         /* else: non-number X seen, interpret it
11792                          * as "NNNX>file" = "NNNX >file" */
11793                 }
11794                 pungetc();
11795         }
11796         quoteflag = quotef;
11797         backquotelist = bqlist;
11798         grabstackblock(len);
11799         wordtext = out;
11800         lasttoken = TWORD;
11801         return lasttoken;
11802 /* end of readtoken routine */
11803
11804 /*
11805  * Check to see whether we are at the end of the here document.  When this
11806  * is called, c is set to the first character of the next input line.  If
11807  * we are at the end of the here document, this routine sets the c to PEOF.
11808  */
11809 checkend: {
11810         if (eofmark) {
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                 if (c == *eofmark) {
11821                         if (pfgets(line, sizeof(line)) != NULL) {
11822                                 char *p, *q;
11823                                 int cc;
11824
11825                                 p = line;
11826                                 for (q = eofmark + 1;; p++, q++) {
11827                                         cc = *p;
11828                                         if (cc == '\n')
11829                                                 cc = 0;
11830                                         if (!*q || cc != *q)
11831                                                 break;
11832                                 }
11833                                 if (cc == *q) {
11834                                         c = PEOF;
11835                                         nlnoprompt();
11836                                 } else {
11837                                         pushstring(line, NULL);
11838                                 }
11839                         }
11840                 }
11841         }
11842         goto checkend_return;
11843 }
11844
11845 /*
11846  * Parse a redirection operator.  The variable "out" points to a string
11847  * specifying the fd to be redirected.  The variable "c" contains the
11848  * first character of the redirection operator.
11849  */
11850 parseredir: {
11851         /* out is already checked to be a valid number or "" */
11852         int fd = (*out == '\0' ? -1 : atoi(out));
11853         union node *np;
11854
11855         np = stzalloc(sizeof(struct nfile));
11856         if (c == '>') {
11857                 np->nfile.fd = 1;
11858                 c = pgetc();
11859                 if (c == '>')
11860                         np->type = NAPPEND;
11861                 else if (c == '|')
11862                         np->type = NCLOBBER;
11863                 else if (c == '&')
11864                         np->type = NTOFD;
11865                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11866                 else {
11867                         np->type = NTO;
11868                         pungetc();
11869                 }
11870         }
11871 #if BASH_REDIR_OUTPUT
11872         else if (c == 0x100 + '>') { /* this flags &> redirection */
11873                 np->nfile.fd = 1;
11874                 pgetc(); /* this is '>', no need to check */
11875                 np->type = NTO2;
11876         }
11877 #endif
11878         else { /* c == '<' */
11879                 /*np->nfile.fd = 0; - stzalloc did it */
11880                 c = pgetc();
11881                 switch (c) {
11882                 case '<':
11883                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11884                                 np = stzalloc(sizeof(struct nhere));
11885                                 /*np->nfile.fd = 0; - stzalloc did it */
11886                         }
11887                         np->type = NHERE;
11888                         heredoc = stzalloc(sizeof(struct heredoc));
11889                         heredoc->here = np;
11890                         c = pgetc();
11891                         if (c == '-') {
11892                                 heredoc->striptabs = 1;
11893                         } else {
11894                                 /*heredoc->striptabs = 0; - stzalloc did it */
11895                                 pungetc();
11896                         }
11897                         break;
11898
11899                 case '&':
11900                         np->type = NFROMFD;
11901                         break;
11902
11903                 case '>':
11904                         np->type = NFROMTO;
11905                         break;
11906
11907                 default:
11908                         np->type = NFROM;
11909                         pungetc();
11910                         break;
11911                 }
11912         }
11913         if (fd >= 0)
11914                 np->nfile.fd = fd;
11915         redirnode = np;
11916         goto parseredir_return;
11917 }
11918
11919 /*
11920  * Parse a substitution.  At this point, we have read the dollar sign
11921  * and nothing else.
11922  */
11923
11924 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11925  * (assuming ascii char codes, as the original implementation did) */
11926 #define is_special(c) \
11927         (((unsigned)(c) - 33 < 32) \
11928                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11929 parsesub: {
11930         unsigned char subtype;
11931         int typeloc;
11932
11933         c = pgetc_eatbnl();
11934         if (c > 255 /* PEOA or PEOF */
11935          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11936         ) {
11937 #if BASH_DOLLAR_SQUOTE
11938                 if (syntax != DQSYNTAX && c == '\'')
11939                         bash_dollar_squote = 1;
11940                 else
11941 #endif
11942                         USTPUTC('$', out);
11943                 pungetc();
11944         } else if (c == '(') {
11945                 /* $(command) or $((arith)) */
11946                 if (pgetc_eatbnl() == '(') {
11947 #if ENABLE_FEATURE_SH_MATH
11948                         PARSEARITH();
11949 #else
11950                         raise_error_syntax("support for $((arith)) is disabled");
11951 #endif
11952                 } else {
11953                         pungetc();
11954                         PARSEBACKQNEW();
11955                 }
11956         } else {
11957                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11958                 USTPUTC(CTLVAR, out);
11959                 typeloc = out - (char *)stackblock();
11960                 STADJUST(1, out);
11961                 subtype = VSNORMAL;
11962                 if (c == '{') {
11963                         c = pgetc_eatbnl();
11964                         subtype = 0;
11965                 }
11966  varname:
11967                 if (is_name(c)) {
11968                         /* $[{[#]]NAME[}] */
11969                         do {
11970                                 STPUTC(c, out);
11971                                 c = pgetc_eatbnl();
11972                         } while (is_in_name(c));
11973                 } else if (isdigit(c)) {
11974                         /* $[{[#]]NUM[}] */
11975                         do {
11976                                 STPUTC(c, out);
11977                                 c = pgetc_eatbnl();
11978                         } while (isdigit(c));
11979                 } else if (is_special(c)) {
11980                         /* $[{[#]]<specialchar>[}] */
11981                         int cc = c;
11982
11983                         c = pgetc_eatbnl();
11984                         if (!subtype && cc == '#') {
11985                                 subtype = VSLENGTH;
11986                                 if (c == '_' || isalnum(c))
11987                                         goto varname;
11988                                 cc = c;
11989                                 c = pgetc_eatbnl();
11990                                 if (cc == '}' || c != '}') {
11991                                         pungetc();
11992                                         subtype = 0;
11993                                         c = cc;
11994                                         cc = '#';
11995                                 }
11996                         }
11997                         USTPUTC(cc, out);
11998                 } else {
11999                         goto badsub;
12000                 }
12001                 if (c != '}' && subtype == VSLENGTH) {
12002                         /* ${#VAR didn't end with } */
12003                         goto badsub;
12004                 }
12005
12006                 if (subtype == 0) {
12007                         static const char types[] ALIGN1 = "}-+?=";
12008                         /* ${VAR...} but not $VAR or ${#VAR} */
12009                         /* c == first char after VAR */
12010                         switch (c) {
12011                         case ':':
12012                                 c = pgetc_eatbnl();
12013 #if BASH_SUBSTR
12014                                 /* This check is only needed to not misinterpret
12015                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12016                                  * constructs.
12017                                  */
12018                                 if (!strchr(types, c)) {
12019                                         subtype = VSSUBSTR;
12020                                         pungetc();
12021                                         break; /* "goto badsub" is bigger (!) */
12022                                 }
12023 #endif
12024                                 subtype = VSNUL;
12025                                 /*FALLTHROUGH*/
12026                         default: {
12027                                 const char *p = strchr(types, c);
12028                                 if (p == NULL)
12029                                         break;
12030                                 subtype |= p - types + VSNORMAL;
12031                                 break;
12032                         }
12033                         case '%':
12034                         case '#': {
12035                                 int cc = c;
12036                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12037                                 c = pgetc_eatbnl();
12038                                 if (c != cc)
12039                                         goto badsub;
12040                                 subtype++;
12041                                 break;
12042                         }
12043 #if BASH_PATTERN_SUBST
12044                         case '/':
12045                                 /* ${v/[/]pattern/repl} */
12046 //TODO: encode pattern and repl separately.
12047 // Currently ${v/$var_with_slash/repl} is horribly broken
12048                                 subtype = VSREPLACE;
12049                                 c = pgetc_eatbnl();
12050                                 if (c != '/')
12051                                         goto badsub;
12052                                 subtype++; /* VSREPLACEALL */
12053                                 break;
12054 #endif
12055                         }
12056                 } else {
12057  badsub:
12058                         pungetc();
12059                 }
12060                 ((unsigned char *)stackblock())[typeloc] = subtype;
12061                 if (subtype != VSNORMAL) {
12062                         varnest++;
12063                         if (dblquote)
12064                                 dqvarnest++;
12065                 }
12066                 STPUTC('=', out);
12067         }
12068         goto parsesub_return;
12069 }
12070
12071 /*
12072  * Called to parse command substitutions.  Newstyle is set if the command
12073  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12074  * list of commands (passed by reference), and savelen is the number of
12075  * characters on the top of the stack which must be preserved.
12076  */
12077 parsebackq: {
12078         struct nodelist **nlpp;
12079         union node *n;
12080         char *str;
12081         size_t savelen;
12082         smallint saveprompt = 0;
12083
12084         str = NULL;
12085         savelen = out - (char *)stackblock();
12086         if (savelen > 0) {
12087                 /*
12088                  * FIXME: this can allocate very large block on stack and SEGV.
12089                  * Example:
12090                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12091                  * allocates 100kb for every command subst. With about
12092                  * a hundred command substitutions stack overflows.
12093                  * With larger prepended string, SEGV happens sooner.
12094                  */
12095                 str = alloca(savelen);
12096                 memcpy(str, stackblock(), savelen);
12097         }
12098
12099         if (oldstyle) {
12100                 /* We must read until the closing backquote, giving special
12101                  * treatment to some slashes, and then push the string and
12102                  * reread it as input, interpreting it normally.
12103                  */
12104                 char *pout;
12105                 size_t psavelen;
12106                 char *pstr;
12107
12108                 STARTSTACKSTR(pout);
12109                 for (;;) {
12110                         int pc;
12111
12112                         setprompt_if(needprompt, 2);
12113                         pc = pgetc();
12114                         switch (pc) {
12115                         case '`':
12116                                 goto done;
12117
12118                         case '\\':
12119                                 pc = pgetc();
12120                                 if (pc == '\n') {
12121                                         nlprompt();
12122                                         /*
12123                                          * If eating a newline, avoid putting
12124                                          * the newline into the new character
12125                                          * stream (via the STPUTC after the
12126                                          * switch).
12127                                          */
12128                                         continue;
12129                                 }
12130                                 if (pc != '\\' && pc != '`' && pc != '$'
12131                                  && (!dblquote || pc != '"')
12132                                 ) {
12133                                         STPUTC('\\', pout);
12134                                 }
12135                                 if (pc <= 255 /* not PEOA or PEOF */) {
12136                                         break;
12137                                 }
12138                                 /* fall through */
12139
12140                         case PEOF:
12141                         IF_ASH_ALIAS(case PEOA:)
12142                                 startlinno = g_parsefile->linno;
12143                                 raise_error_syntax("EOF in backquote substitution");
12144
12145                         case '\n':
12146                                 nlnoprompt();
12147                                 break;
12148
12149                         default:
12150                                 break;
12151                         }
12152                         STPUTC(pc, pout);
12153                 }
12154  done:
12155                 STPUTC('\0', pout);
12156                 psavelen = pout - (char *)stackblock();
12157                 if (psavelen > 0) {
12158                         pstr = grabstackstr(pout);
12159                         setinputstring(pstr);
12160                 }
12161         }
12162         nlpp = &bqlist;
12163         while (*nlpp)
12164                 nlpp = &(*nlpp)->next;
12165         *nlpp = stzalloc(sizeof(**nlpp));
12166         /* (*nlpp)->next = NULL; - stzalloc did it */
12167
12168         if (oldstyle) {
12169                 saveprompt = doprompt;
12170                 doprompt = 0;
12171         }
12172
12173         n = list(2);
12174
12175         if (oldstyle)
12176                 doprompt = saveprompt;
12177         else if (readtoken() != TRP)
12178                 raise_error_unexpected_syntax(TRP);
12179
12180         (*nlpp)->n = n;
12181         if (oldstyle) {
12182                 /*
12183                  * Start reading from old file again, ignoring any pushed back
12184                  * tokens left from the backquote parsing
12185                  */
12186                 popfile();
12187                 tokpushback = 0;
12188         }
12189         while (stackblocksize() <= savelen)
12190                 growstackblock();
12191         STARTSTACKSTR(out);
12192         if (str) {
12193                 memcpy(out, str, savelen);
12194                 STADJUST(savelen, out);
12195         }
12196         USTPUTC(CTLBACKQ, out);
12197         if (oldstyle)
12198                 goto parsebackq_oldreturn;
12199         goto parsebackq_newreturn;
12200 }
12201
12202 #if ENABLE_FEATURE_SH_MATH
12203 /*
12204  * Parse an arithmetic expansion (indicate start of one and set state)
12205  */
12206 parsearith: {
12207         if (++arinest == 1) {
12208                 prevsyntax = syntax;
12209                 syntax = ARISYNTAX;
12210         }
12211         USTPUTC(CTLARI, out);
12212         goto parsearith_return;
12213 }
12214 #endif
12215 } /* end of readtoken */
12216
12217 /*
12218  * Read the next input token.
12219  * If the token is a word, we set backquotelist to the list of cmds in
12220  *      backquotes.  We set quoteflag to true if any part of the word was
12221  *      quoted.
12222  * If the token is TREDIR, then we set redirnode to a structure containing
12223  *      the redirection.
12224  * In all cases, the variable startlinno is set to the number of the line
12225  *      on which the token starts.
12226  *
12227  * [Change comment:  here documents and internal procedures]
12228  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12229  *  word parsing code into a separate routine.  In this case, readtoken
12230  *  doesn't need to have any internal procedures, but parseword does.
12231  *  We could also make parseoperator in essence the main routine, and
12232  *  have parseword (readtoken1?) handle both words and redirection.]
12233  */
12234 #define NEW_xxreadtoken
12235 #ifdef NEW_xxreadtoken
12236 /* singles must be first! */
12237 static const char xxreadtoken_chars[7] ALIGN1 = {
12238         '\n', '(', ')', /* singles */
12239         '&', '|', ';',  /* doubles */
12240         0
12241 };
12242
12243 #define xxreadtoken_singles 3
12244 #define xxreadtoken_doubles 3
12245
12246 static const char xxreadtoken_tokens[] ALIGN1 = {
12247         TNL, TLP, TRP,          /* only single occurrence allowed */
12248         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12249         TEOF,                   /* corresponds to trailing nul */
12250         TAND, TOR, TENDCASE     /* if double occurrence */
12251 };
12252
12253 static int
12254 xxreadtoken(void)
12255 {
12256         int c;
12257
12258         if (tokpushback) {
12259                 tokpushback = 0;
12260                 return lasttoken;
12261         }
12262         setprompt_if(needprompt, 2);
12263         startlinno = g_parsefile->linno;
12264         for (;;) {                      /* until token or start of word found */
12265                 c = pgetc();
12266                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12267                         continue;
12268
12269                 if (c == '#') {
12270                         while ((c = pgetc()) != '\n' && c != PEOF)
12271                                 continue;
12272                         pungetc();
12273                 } else if (c == '\\') {
12274                         if (pgetc() != '\n') {
12275                                 pungetc();
12276                                 break; /* return readtoken1(...) */
12277                         }
12278                         nlprompt();
12279                 } else {
12280                         const char *p;
12281
12282                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12283                         if (c != PEOF) {
12284                                 if (c == '\n') {
12285                                         nlnoprompt();
12286                                 }
12287
12288                                 p = strchr(xxreadtoken_chars, c);
12289                                 if (p == NULL)
12290                                         break; /* return readtoken1(...) */
12291
12292                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12293                                         int cc = pgetc();
12294                                         if (cc == c) {    /* double occurrence? */
12295                                                 p += xxreadtoken_doubles + 1;
12296                                         } else {
12297                                                 pungetc();
12298 #if BASH_REDIR_OUTPUT
12299                                                 if (c == '&' && cc == '>') /* &> */
12300                                                         break; /* return readtoken1(...) */
12301 #endif
12302                                         }
12303                                 }
12304                         }
12305                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12306                         return lasttoken;
12307                 }
12308         } /* for (;;) */
12309
12310         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12311 }
12312 #else /* old xxreadtoken */
12313 #define RETURN(token)   return lasttoken = token
12314 static int
12315 xxreadtoken(void)
12316 {
12317         int c;
12318
12319         if (tokpushback) {
12320                 tokpushback = 0;
12321                 return lasttoken;
12322         }
12323         setprompt_if(needprompt, 2);
12324         startlinno = g_parsefile->linno;
12325         for (;;) {      /* until token or start of word found */
12326                 c = pgetc();
12327                 switch (c) {
12328                 case ' ': case '\t':
12329                 IF_ASH_ALIAS(case PEOA:)
12330                         continue;
12331                 case '#':
12332                         while ((c = pgetc()) != '\n' && c != PEOF)
12333                                 continue;
12334                         pungetc();
12335                         continue;
12336                 case '\\':
12337                         if (pgetc() == '\n') {
12338                                 nlprompt();
12339                                 continue;
12340                         }
12341                         pungetc();
12342                         goto breakloop;
12343                 case '\n':
12344                         nlnoprompt();
12345                         RETURN(TNL);
12346                 case PEOF:
12347                         RETURN(TEOF);
12348                 case '&':
12349                         if (pgetc() == '&')
12350                                 RETURN(TAND);
12351                         pungetc();
12352                         RETURN(TBACKGND);
12353                 case '|':
12354                         if (pgetc() == '|')
12355                                 RETURN(TOR);
12356                         pungetc();
12357                         RETURN(TPIPE);
12358                 case ';':
12359                         if (pgetc() == ';')
12360                                 RETURN(TENDCASE);
12361                         pungetc();
12362                         RETURN(TSEMI);
12363                 case '(':
12364                         RETURN(TLP);
12365                 case ')':
12366                         RETURN(TRP);
12367                 default:
12368                         goto breakloop;
12369                 }
12370         }
12371  breakloop:
12372         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12373 #undef RETURN
12374 }
12375 #endif /* old xxreadtoken */
12376
12377 static int
12378 readtoken(void)
12379 {
12380         int t;
12381         int kwd = checkkwd;
12382 #if DEBUG
12383         smallint alreadyseen = tokpushback;
12384 #endif
12385
12386 #if ENABLE_ASH_ALIAS
12387  top:
12388 #endif
12389
12390         t = xxreadtoken();
12391
12392         /*
12393          * eat newlines
12394          */
12395         if (kwd & CHKNL) {
12396                 while (t == TNL) {
12397                         parseheredoc();
12398                         t = xxreadtoken();
12399                 }
12400         }
12401
12402         if (t != TWORD || quoteflag) {
12403                 goto out;
12404         }
12405
12406         /*
12407          * check for keywords
12408          */
12409         if (kwd & CHKKWD) {
12410                 const char *const *pp;
12411
12412                 pp = findkwd(wordtext);
12413                 if (pp) {
12414                         lasttoken = t = pp - tokname_array;
12415                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12416                         goto out;
12417                 }
12418         }
12419
12420         if (checkkwd & CHKALIAS) {
12421 #if ENABLE_ASH_ALIAS
12422                 struct alias *ap;
12423                 ap = lookupalias(wordtext, 1);
12424                 if (ap != NULL) {
12425                         if (*ap->val) {
12426                                 pushstring(ap->val, ap);
12427                         }
12428                         goto top;
12429                 }
12430 #endif
12431         }
12432  out:
12433         checkkwd = 0;
12434 #if DEBUG
12435         if (!alreadyseen)
12436                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12437         else
12438                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12439 #endif
12440         return t;
12441 }
12442
12443 static int
12444 peektoken(void)
12445 {
12446         int t;
12447
12448         t = readtoken();
12449         tokpushback = 1;
12450         return t;
12451 }
12452
12453 /*
12454  * Read and parse a command.  Returns NODE_EOF on end of file.
12455  * (NULL is a valid parse tree indicating a blank line.)
12456  */
12457 static union node *
12458 parsecmd(int interact)
12459 {
12460         tokpushback = 0;
12461         checkkwd = 0;
12462         heredoclist = 0;
12463         doprompt = interact;
12464         setprompt_if(doprompt, doprompt);
12465         needprompt = 0;
12466         return list(1);
12467 }
12468
12469 /*
12470  * Input any here documents.
12471  */
12472 static void
12473 parseheredoc(void)
12474 {
12475         struct heredoc *here;
12476         union node *n;
12477
12478         here = heredoclist;
12479         heredoclist = NULL;
12480
12481         while (here) {
12482                 setprompt_if(needprompt, 2);
12483                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12484                                 here->eofmark, here->striptabs);
12485                 n = stzalloc(sizeof(struct narg));
12486                 n->narg.type = NARG;
12487                 /*n->narg.next = NULL; - stzalloc did it */
12488                 n->narg.text = wordtext;
12489                 n->narg.backquote = backquotelist;
12490                 here->here->nhere.doc = n;
12491                 here = here->next;
12492         }
12493 }
12494
12495
12496 /*
12497  * called by editline -- any expansions to the prompt should be added here.
12498  */
12499 static const char *
12500 expandstr(const char *ps)
12501 {
12502         union node n;
12503         int saveprompt;
12504
12505         /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
12506          * and token processing _can_ alter it (delete NULs etc). */
12507         setinputstring((char *)ps);
12508
12509         saveprompt = doprompt;
12510         doprompt = 0;
12511         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
12512         doprompt = saveprompt;
12513
12514         popfile();
12515
12516         n.narg.type = NARG;
12517         n.narg.next = NULL;
12518         n.narg.text = wordtext;
12519         n.narg.backquote = backquotelist;
12520
12521         expandarg(&n, NULL, EXP_QUOTED);
12522         return stackblock();
12523 }
12524
12525 static inline int
12526 parser_eof(void)
12527 {
12528         return tokpushback && lasttoken == TEOF;
12529 }
12530
12531 /*
12532  * Execute a command or commands contained in a string.
12533  */
12534 static int
12535 evalstring(char *s, int flags)
12536 {
12537         struct jmploc *volatile savehandler;
12538         struct jmploc jmploc;
12539         int ex;
12540
12541         union node *n;
12542         struct stackmark smark;
12543         int status;
12544
12545         s = sstrdup(s);
12546         setinputstring(s);
12547         setstackmark(&smark);
12548
12549         status = 0;
12550         /* On exception inside execution loop, we must popfile().
12551          * Try interactively:
12552          *      readonly a=a
12553          *      command eval "a=b"  # throws "is read only" error
12554          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12555          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12556          */
12557         savehandler = exception_handler;
12558         ex = setjmp(jmploc.loc);
12559         if (ex)
12560                 goto out;
12561         exception_handler = &jmploc;
12562
12563         while ((n = parsecmd(0)) != NODE_EOF) {
12564                 int i;
12565
12566                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12567                 if (n)
12568                         status = i;
12569                 popstackmark(&smark);
12570                 if (evalskip)
12571                         break;
12572         }
12573  out:
12574         popstackmark(&smark);
12575         popfile();
12576         stunalloc(s);
12577
12578         exception_handler = savehandler;
12579         if (ex)
12580                 longjmp(exception_handler->loc, ex);
12581
12582         return status;
12583 }
12584
12585 /*
12586  * The eval command.
12587  */
12588 static int FAST_FUNC
12589 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12590 {
12591         char *p;
12592         char *concat;
12593
12594         if (argv[1]) {
12595                 p = argv[1];
12596                 argv += 2;
12597                 if (argv[0]) {
12598                         STARTSTACKSTR(concat);
12599                         for (;;) {
12600                                 concat = stack_putstr(p, concat);
12601                                 p = *argv++;
12602                                 if (p == NULL)
12603                                         break;
12604                                 STPUTC(' ', concat);
12605                         }
12606                         STPUTC('\0', concat);
12607                         p = grabstackstr(concat);
12608                 }
12609                 return evalstring(p, flags & EV_TESTED);
12610         }
12611         return 0;
12612 }
12613
12614 /*
12615  * Read and execute commands.
12616  * "Top" is nonzero for the top level command loop;
12617  * it turns on prompting if the shell is interactive.
12618  */
12619 static int
12620 cmdloop(int top)
12621 {
12622         union node *n;
12623         struct stackmark smark;
12624         int inter;
12625         int status = 0;
12626         int numeof = 0;
12627
12628         TRACE(("cmdloop(%d) called\n", top));
12629         for (;;) {
12630                 int skip;
12631
12632                 setstackmark(&smark);
12633 #if JOBS
12634                 if (doing_jobctl)
12635                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12636 #endif
12637                 inter = 0;
12638                 if (iflag && top) {
12639                         inter++;
12640                         chkmail();
12641                 }
12642                 n = parsecmd(inter);
12643 #if DEBUG
12644                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12645                         showtree(n);
12646 #endif
12647                 if (n == NODE_EOF) {
12648                         if (!top || numeof >= 50)
12649                                 break;
12650                         if (!stoppedjobs()) {
12651                                 if (!Iflag)
12652                                         break;
12653                                 out2str("\nUse \"exit\" to leave shell.\n");
12654                         }
12655                         numeof++;
12656                 } else if (nflag == 0) {
12657                         int i;
12658
12659                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12660                         job_warning >>= 1;
12661                         numeof = 0;
12662                         i = evaltree(n, 0);
12663                         if (n)
12664                                 status = i;
12665                 }
12666                 popstackmark(&smark);
12667                 skip = evalskip;
12668
12669                 if (skip) {
12670                         evalskip &= ~SKIPFUNC;
12671                         break;
12672                 }
12673         }
12674         return status;
12675 }
12676
12677 /*
12678  * Take commands from a file.  To be compatible we should do a path
12679  * search for the file, which is necessary to find sub-commands.
12680  */
12681 static char *
12682 find_dot_file(char *name)
12683 {
12684         char *fullname;
12685         const char *path = pathval();
12686         struct stat statb;
12687
12688         /* don't try this for absolute or relative paths */
12689         if (strchr(name, '/'))
12690                 return name;
12691
12692         while ((fullname = path_advance(&path, name)) != NULL) {
12693                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12694                         /*
12695                          * Don't bother freeing here, since it will
12696                          * be freed by the caller.
12697                          */
12698                         return fullname;
12699                 }
12700                 if (fullname != name)
12701                         stunalloc(fullname);
12702         }
12703
12704         /* not found in the PATH */
12705         ash_msg_and_raise_error("%s: not found", name);
12706         /* NOTREACHED */
12707 }
12708
12709 static int FAST_FUNC
12710 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12711 {
12712         /* "false; . empty_file; echo $?" should print 0, not 1: */
12713         int status = 0;
12714         char *fullname;
12715         char **argv;
12716         char *args_need_save;
12717         struct strlist *sp;
12718         volatile struct shparam saveparam;
12719
12720         for (sp = cmdenviron; sp; sp = sp->next)
12721                 setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12722
12723         nextopt(nullstr); /* handle possible "--" */
12724         argv = argptr;
12725
12726         if (!argv[0]) {
12727                 /* bash says: "bash: .: filename argument required" */
12728                 return 2; /* bash compat */
12729         }
12730
12731         /* This aborts if file isn't found, which is POSIXly correct.
12732          * bash returns exitcode 1 instead.
12733          */
12734         fullname = find_dot_file(argv[0]);
12735         argv++;
12736         args_need_save = argv[0];
12737         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12738                 int argc;
12739                 saveparam = shellparam;
12740                 shellparam.malloced = 0;
12741                 argc = 1;
12742                 while (argv[argc])
12743                         argc++;
12744                 shellparam.nparam = argc;
12745                 shellparam.p = argv;
12746         };
12747
12748         /* This aborts if file can't be opened, which is POSIXly correct.
12749          * bash returns exitcode 1 instead.
12750          */
12751         setinputfile(fullname, INPUT_PUSH_FILE);
12752         commandname = fullname;
12753         status = cmdloop(0);
12754         popfile();
12755
12756         if (args_need_save) {
12757                 freeparam(&shellparam);
12758                 shellparam = saveparam;
12759         };
12760
12761         return status;
12762 }
12763
12764 static int FAST_FUNC
12765 exitcmd(int argc UNUSED_PARAM, char **argv)
12766 {
12767         if (stoppedjobs())
12768                 return 0;
12769         if (argv[1])
12770                 exitstatus = number(argv[1]);
12771         raise_exception(EXEXIT);
12772         /* NOTREACHED */
12773 }
12774
12775 /*
12776  * Read a file containing shell functions.
12777  */
12778 static void
12779 readcmdfile(char *name)
12780 {
12781         setinputfile(name, INPUT_PUSH_FILE);
12782         cmdloop(0);
12783         popfile();
12784 }
12785
12786
12787 /* ============ find_command inplementation */
12788
12789 /*
12790  * Resolve a command name.  If you change this routine, you may have to
12791  * change the shellexec routine as well.
12792  */
12793 static void
12794 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12795 {
12796         struct tblentry *cmdp;
12797         int idx;
12798         int prev;
12799         char *fullname;
12800         struct stat statb;
12801         int e;
12802         int updatetbl;
12803         struct builtincmd *bcmd;
12804
12805         /* If name contains a slash, don't use PATH or hash table */
12806         if (strchr(name, '/') != NULL) {
12807                 entry->u.index = -1;
12808                 if (act & DO_ABS) {
12809                         while (stat(name, &statb) < 0) {
12810 #ifdef SYSV
12811                                 if (errno == EINTR)
12812                                         continue;
12813 #endif
12814                                 entry->cmdtype = CMDUNKNOWN;
12815                                 return;
12816                         }
12817                 }
12818                 entry->cmdtype = CMDNORMAL;
12819                 return;
12820         }
12821
12822 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12823
12824         updatetbl = (path == pathval());
12825         if (!updatetbl) {
12826                 act |= DO_ALTPATH;
12827                 if (strstr(path, "%builtin") != NULL)
12828                         act |= DO_ALTBLTIN;
12829         }
12830
12831         /* If name is in the table, check answer will be ok */
12832         cmdp = cmdlookup(name, 0);
12833         if (cmdp != NULL) {
12834                 int bit;
12835
12836                 switch (cmdp->cmdtype) {
12837                 default:
12838 #if DEBUG
12839                         abort();
12840 #endif
12841                 case CMDNORMAL:
12842                         bit = DO_ALTPATH;
12843                         break;
12844                 case CMDFUNCTION:
12845                         bit = DO_NOFUNC;
12846                         break;
12847                 case CMDBUILTIN:
12848                         bit = DO_ALTBLTIN;
12849                         break;
12850                 }
12851                 if (act & bit) {
12852                         updatetbl = 0;
12853                         cmdp = NULL;
12854                 } else if (cmdp->rehash == 0)
12855                         /* if not invalidated by cd, we're done */
12856                         goto success;
12857         }
12858
12859         /* If %builtin not in path, check for builtin next */
12860         bcmd = find_builtin(name);
12861         if (bcmd) {
12862                 if (IS_BUILTIN_REGULAR(bcmd))
12863                         goto builtin_success;
12864                 if (act & DO_ALTPATH) {
12865                         if (!(act & DO_ALTBLTIN))
12866                                 goto builtin_success;
12867                 } else if (builtinloc <= 0) {
12868                         goto builtin_success;
12869                 }
12870         }
12871
12872 #if ENABLE_FEATURE_SH_STANDALONE
12873         {
12874                 int applet_no = find_applet_by_name(name);
12875                 if (applet_no >= 0) {
12876                         entry->cmdtype = CMDNORMAL;
12877                         entry->u.index = -2 - applet_no;
12878                         return;
12879                 }
12880         }
12881 #endif
12882
12883         /* We have to search path. */
12884         prev = -1;              /* where to start */
12885         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12886                 if (cmdp->cmdtype == CMDBUILTIN)
12887                         prev = builtinloc;
12888                 else
12889                         prev = cmdp->param.index;
12890         }
12891
12892         e = ENOENT;
12893         idx = -1;
12894  loop:
12895         while ((fullname = path_advance(&path, name)) != NULL) {
12896                 stunalloc(fullname);
12897                 /* NB: code below will still use fullname
12898                  * despite it being "unallocated" */
12899                 idx++;
12900                 if (pathopt) {
12901                         if (prefix(pathopt, "builtin")) {
12902                                 if (bcmd)
12903                                         goto builtin_success;
12904                                 continue;
12905                         }
12906                         if ((act & DO_NOFUNC)
12907                          || !prefix(pathopt, "func")
12908                         ) {     /* ignore unimplemented options */
12909                                 continue;
12910                         }
12911                 }
12912                 /* if rehash, don't redo absolute path names */
12913                 if (fullname[0] == '/' && idx <= prev) {
12914                         if (idx < prev)
12915                                 continue;
12916                         TRACE(("searchexec \"%s\": no change\n", name));
12917                         goto success;
12918                 }
12919                 while (stat(fullname, &statb) < 0) {
12920 #ifdef SYSV
12921                         if (errno == EINTR)
12922                                 continue;
12923 #endif
12924                         if (errno != ENOENT && errno != ENOTDIR)
12925                                 e = errno;
12926                         goto loop;
12927                 }
12928                 e = EACCES;     /* if we fail, this will be the error */
12929                 if (!S_ISREG(statb.st_mode))
12930                         continue;
12931                 if (pathopt) {          /* this is a %func directory */
12932                         stalloc(strlen(fullname) + 1);
12933                         /* NB: stalloc will return space pointed by fullname
12934                          * (because we don't have any intervening allocations
12935                          * between stunalloc above and this stalloc) */
12936                         readcmdfile(fullname);
12937                         cmdp = cmdlookup(name, 0);
12938                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12939                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12940                         stunalloc(fullname);
12941                         goto success;
12942                 }
12943                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12944                 if (!updatetbl) {
12945                         entry->cmdtype = CMDNORMAL;
12946                         entry->u.index = idx;
12947                         return;
12948                 }
12949                 INT_OFF;
12950                 cmdp = cmdlookup(name, 1);
12951                 cmdp->cmdtype = CMDNORMAL;
12952                 cmdp->param.index = idx;
12953                 INT_ON;
12954                 goto success;
12955         }
12956
12957         /* We failed.  If there was an entry for this command, delete it */
12958         if (cmdp && updatetbl)
12959                 delete_cmd_entry();
12960         if (act & DO_ERR)
12961                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12962         entry->cmdtype = CMDUNKNOWN;
12963         return;
12964
12965  builtin_success:
12966         if (!updatetbl) {
12967                 entry->cmdtype = CMDBUILTIN;
12968                 entry->u.cmd = bcmd;
12969                 return;
12970         }
12971         INT_OFF;
12972         cmdp = cmdlookup(name, 1);
12973         cmdp->cmdtype = CMDBUILTIN;
12974         cmdp->param.cmd = bcmd;
12975         INT_ON;
12976  success:
12977         cmdp->rehash = 0;
12978         entry->cmdtype = cmdp->cmdtype;
12979         entry->u = cmdp->param;
12980 }
12981
12982
12983 /*
12984  * The trap builtin.
12985  */
12986 static int FAST_FUNC
12987 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12988 {
12989         char *action;
12990         char **ap;
12991         int signo, exitcode;
12992
12993         nextopt(nullstr);
12994         ap = argptr;
12995         if (!*ap) {
12996                 for (signo = 0; signo < NSIG; signo++) {
12997                         char *tr = trap_ptr[signo];
12998                         if (tr) {
12999                                 /* note: bash adds "SIG", but only if invoked
13000                                  * as "bash". If called as "sh", or if set -o posix,
13001                                  * then it prints short signal names.
13002                                  * We are printing short names: */
13003                                 out1fmt("trap -- %s %s\n",
13004                                                 single_quote(tr),
13005                                                 get_signame(signo));
13006                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13007                  * In this case, we will exit very soon, no need to free(). */
13008                                 /* if (trap_ptr != trap && tp[0]) */
13009                                 /*      free(tr); */
13010                         }
13011                 }
13012                 /*
13013                 if (trap_ptr != trap) {
13014                         free(trap_ptr);
13015                         trap_ptr = trap;
13016                 }
13017                 */
13018                 return 0;
13019         }
13020
13021         /* Why the second check?
13022          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13023          * In this case, NUM is signal no, not an action.
13024          */
13025         action = NULL;
13026         if (ap[1] && !is_number(ap[0]))
13027                 action = *ap++;
13028
13029         exitcode = 0;
13030         while (*ap) {
13031                 signo = get_signum(*ap);
13032                 if (signo < 0) {
13033                         /* Mimic bash message exactly */
13034                         ash_msg("%s: invalid signal specification", *ap);
13035                         exitcode = 1;
13036                         goto next;
13037                 }
13038                 INT_OFF;
13039                 if (action) {
13040                         if (LONE_DASH(action))
13041                                 action = NULL;
13042                         else {
13043                                 if (action[0]) /* not NULL and not "" and not "-" */
13044                                         may_have_traps = 1;
13045                                 action = ckstrdup(action);
13046                         }
13047                 }
13048                 free(trap[signo]);
13049                 trap[signo] = action;
13050                 if (signo != 0)
13051                         setsignal(signo);
13052                 INT_ON;
13053  next:
13054                 ap++;
13055         }
13056         return exitcode;
13057 }
13058
13059
13060 /* ============ Builtins */
13061
13062 #if ENABLE_ASH_HELP
13063 static int FAST_FUNC
13064 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13065 {
13066         unsigned col;
13067         unsigned i;
13068
13069         out1fmt(
13070                 "Built-in commands:\n"
13071                 "------------------\n");
13072         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13073                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13074                                         builtintab[i].name + 1);
13075                 if (col > 60) {
13076                         out1fmt("\n");
13077                         col = 0;
13078                 }
13079         }
13080 # if ENABLE_FEATURE_SH_STANDALONE
13081         {
13082                 const char *a = applet_names;
13083                 while (*a) {
13084                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13085                         if (col > 60) {
13086                                 out1fmt("\n");
13087                                 col = 0;
13088                         }
13089                         while (*a++ != '\0')
13090                                 continue;
13091                 }
13092         }
13093 # endif
13094         newline_and_flush(stdout);
13095         return EXIT_SUCCESS;
13096 }
13097 #endif
13098
13099 #if MAX_HISTORY
13100 static int FAST_FUNC
13101 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13102 {
13103         show_history(line_input_state);
13104         return EXIT_SUCCESS;
13105 }
13106 #endif
13107
13108 /*
13109  * The export and readonly commands.
13110  */
13111 static int FAST_FUNC
13112 exportcmd(int argc UNUSED_PARAM, char **argv)
13113 {
13114         struct var *vp;
13115         char *name;
13116         const char *p;
13117         char **aptr;
13118         char opt;
13119         int flag;
13120         int flag_off;
13121
13122         /* "readonly" in bash accepts, but ignores -n.
13123          * We do the same: it saves a conditional in nextopt's param.
13124          */
13125         flag_off = 0;
13126         while ((opt = nextopt("np")) != '\0') {
13127                 if (opt == 'n')
13128                         flag_off = VEXPORT;
13129         }
13130         flag = VEXPORT;
13131         if (argv[0][0] == 'r') {
13132                 flag = VREADONLY;
13133                 flag_off = 0; /* readonly ignores -n */
13134         }
13135         flag_off = ~flag_off;
13136
13137         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13138         {
13139                 aptr = argptr;
13140                 name = *aptr;
13141                 if (name) {
13142                         do {
13143                                 p = strchr(name, '=');
13144                                 if (p != NULL) {
13145                                         p++;
13146                                 } else {
13147                                         vp = *findvar(hashvar(name), name);
13148                                         if (vp) {
13149                                                 vp->flags = ((vp->flags | flag) & flag_off);
13150                                                 continue;
13151                                         }
13152                                 }
13153                                 setvar(name, p, (flag & flag_off));
13154                         } while ((name = *++aptr) != NULL);
13155                         return 0;
13156                 }
13157         }
13158
13159         /* No arguments. Show the list of exported or readonly vars.
13160          * -n is ignored.
13161          */
13162         showvars(argv[0], flag, 0);
13163         return 0;
13164 }
13165
13166 /*
13167  * Delete a function if it exists.
13168  */
13169 static void
13170 unsetfunc(const char *name)
13171 {
13172         struct tblentry *cmdp;
13173
13174         cmdp = cmdlookup(name, 0);
13175         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13176                 delete_cmd_entry();
13177 }
13178
13179 /*
13180  * The unset builtin command.  We unset the function before we unset the
13181  * variable to allow a function to be unset when there is a readonly variable
13182  * with the same name.
13183  */
13184 static int FAST_FUNC
13185 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13186 {
13187         char **ap;
13188         int i;
13189         int flag = 0;
13190
13191         while ((i = nextopt("vf")) != 0) {
13192                 flag = i;
13193         }
13194
13195         for (ap = argptr; *ap; ap++) {
13196                 if (flag != 'f') {
13197                         unsetvar(*ap);
13198                         continue;
13199                 }
13200                 if (flag != 'v')
13201                         unsetfunc(*ap);
13202         }
13203         return 0;
13204 }
13205
13206 static const unsigned char timescmd_str[] ALIGN1 = {
13207         ' ',  offsetof(struct tms, tms_utime),
13208         '\n', offsetof(struct tms, tms_stime),
13209         ' ',  offsetof(struct tms, tms_cutime),
13210         '\n', offsetof(struct tms, tms_cstime),
13211         0
13212 };
13213 static int FAST_FUNC
13214 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13215 {
13216         unsigned long clk_tck, s, t;
13217         const unsigned char *p;
13218         struct tms buf;
13219
13220         clk_tck = bb_clk_tck();
13221         times(&buf);
13222
13223         p = timescmd_str;
13224         do {
13225                 t = *(clock_t *)(((char *) &buf) + p[1]);
13226                 s = t / clk_tck;
13227                 t = t % clk_tck;
13228                 out1fmt("%lum%lu.%03lus%c",
13229                         s / 60, s % 60,
13230                         (t * 1000) / clk_tck,
13231                         p[0]);
13232                 p += 2;
13233         } while (*p);
13234
13235         return 0;
13236 }
13237
13238 #if ENABLE_FEATURE_SH_MATH
13239 /*
13240  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13241  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13242  *
13243  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13244  */
13245 static int FAST_FUNC
13246 letcmd(int argc UNUSED_PARAM, char **argv)
13247 {
13248         arith_t i;
13249
13250         argv++;
13251         if (!*argv)
13252                 ash_msg_and_raise_error("expression expected");
13253         do {
13254                 i = ash_arith(*argv);
13255         } while (*++argv);
13256
13257         return !i;
13258 }
13259 #endif
13260
13261 /*
13262  * The read builtin. Options:
13263  *      -r              Do not interpret '\' specially
13264  *      -s              Turn off echo (tty only)
13265  *      -n NCHARS       Read NCHARS max
13266  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13267  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13268  *      -u FD           Read from given FD instead of fd 0
13269  * This uses unbuffered input, which may be avoidable in some cases.
13270  * TODO: bash also has:
13271  *      -a ARRAY        Read into array[0],[1],etc
13272  *      -d DELIM        End on DELIM char, not newline
13273  *      -e              Use line editing (tty only)
13274  */
13275 static int FAST_FUNC
13276 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13277 {
13278         char *opt_n = NULL;
13279         char *opt_p = NULL;
13280         char *opt_t = NULL;
13281         char *opt_u = NULL;
13282         int read_flags = 0;
13283         const char *r;
13284         int i;
13285
13286         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13287                 switch (i) {
13288                 case 'p':
13289                         opt_p = optionarg;
13290                         break;
13291                 case 'n':
13292                         opt_n = optionarg;
13293                         break;
13294                 case 's':
13295                         read_flags |= BUILTIN_READ_SILENT;
13296                         break;
13297                 case 't':
13298                         opt_t = optionarg;
13299                         break;
13300                 case 'r':
13301                         read_flags |= BUILTIN_READ_RAW;
13302                         break;
13303                 case 'u':
13304                         opt_u = optionarg;
13305                         break;
13306                 default:
13307                         break;
13308                 }
13309         }
13310
13311         /* "read -s" needs to save/restore termios, can't allow ^C
13312          * to jump out of it.
13313          */
13314  again:
13315         INT_OFF;
13316         r = shell_builtin_read(setvar0,
13317                 argptr,
13318                 bltinlookup("IFS"), /* can be NULL */
13319                 read_flags,
13320                 opt_n,
13321                 opt_p,
13322                 opt_t,
13323                 opt_u
13324         );
13325         INT_ON;
13326
13327         if ((uintptr_t)r == 1 && errno == EINTR) {
13328                 /* to get SIGCHLD: sleep 1 & read x; echo $x */
13329                 if (pending_sig == 0)
13330                         goto again;
13331         }
13332
13333         if ((uintptr_t)r > 1)
13334                 ash_msg_and_raise_error(r);
13335
13336         return (uintptr_t)r;
13337 }
13338
13339 static int FAST_FUNC
13340 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13341 {
13342         static const char permuser[3] ALIGN1 = "ogu";
13343
13344         mode_t mask;
13345         int symbolic_mode = 0;
13346
13347         while (nextopt("S") != '\0') {
13348                 symbolic_mode = 1;
13349         }
13350
13351         INT_OFF;
13352         mask = umask(0);
13353         umask(mask);
13354         INT_ON;
13355
13356         if (*argptr == NULL) {
13357                 if (symbolic_mode) {
13358                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13359                         char *p = buf;
13360                         int i;
13361
13362                         i = 2;
13363                         for (;;) {
13364                                 *p++ = ',';
13365                                 *p++ = permuser[i];
13366                                 *p++ = '=';
13367                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13368                                 if (!(mask & 0400)) *p++ = 'r';
13369                                 if (!(mask & 0200)) *p++ = 'w';
13370                                 if (!(mask & 0100)) *p++ = 'x';
13371                                 mask <<= 3;
13372                                 if (--i < 0)
13373                                         break;
13374                         }
13375                         *p = '\0';
13376                         puts(buf + 1);
13377                 } else {
13378                         out1fmt("%04o\n", mask);
13379                 }
13380         } else {
13381                 char *modestr = *argptr;
13382                 /* numeric umasks are taken as-is */
13383                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13384                 if (!isdigit(modestr[0]))
13385                         mask ^= 0777;
13386                 mask = bb_parse_mode(modestr, mask);
13387                 if ((unsigned)mask > 0777) {
13388                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13389                 }
13390                 if (!isdigit(modestr[0]))
13391                         mask ^= 0777;
13392                 umask(mask);
13393         }
13394         return 0;
13395 }
13396
13397 static int FAST_FUNC
13398 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13399 {
13400         return shell_builtin_ulimit(argv);
13401 }
13402
13403 /* ============ main() and helpers */
13404
13405 /*
13406  * Called to exit the shell.
13407  */
13408 static void
13409 exitshell(void)
13410 {
13411         struct jmploc loc;
13412         char *p;
13413         int status;
13414
13415 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13416         save_history(line_input_state);
13417 #endif
13418         status = exitstatus;
13419         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13420         if (setjmp(loc.loc)) {
13421                 if (exception_type == EXEXIT)
13422                         status = exitstatus;
13423                 goto out;
13424         }
13425         exception_handler = &loc;
13426         p = trap[0];
13427         if (p) {
13428                 trap[0] = NULL;
13429                 evalskip = 0;
13430                 evalstring(p, 0);
13431                 /*free(p); - we'll exit soon */
13432         }
13433  out:
13434         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13435          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13436          */
13437         setjobctl(0);
13438         flush_stdout_stderr();
13439         _exit(status);
13440         /* NOTREACHED */
13441 }
13442
13443 static void
13444 init(void)
13445 {
13446         /* we will never free this */
13447         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13448
13449         sigmode[SIGCHLD - 1] = S_DFL;
13450         setsignal(SIGCHLD);
13451
13452         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13453          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13454          */
13455         signal(SIGHUP, SIG_DFL);
13456
13457         {
13458                 char **envp;
13459                 const char *p;
13460                 struct stat st1, st2;
13461
13462                 initvar();
13463                 for (envp = environ; envp && *envp; envp++) {
13464                         p = endofname(*envp);
13465                         if (p != *envp && *p == '=') {
13466                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13467                         }
13468                 }
13469
13470                 setvareq((char*)defoptindvar, VTEXTFIXED);
13471
13472                 setvar0("PPID", utoa(getppid()));
13473 #if BASH_SHLVL_VAR
13474                 p = lookupvar("SHLVL");
13475                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13476 #endif
13477 #if BASH_HOSTNAME_VAR
13478                 if (!lookupvar("HOSTNAME")) {
13479                         struct utsname uts;
13480                         uname(&uts);
13481                         setvar0("HOSTNAME", uts.nodename);
13482                 }
13483 #endif
13484                 p = lookupvar("PWD");
13485                 if (p) {
13486                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13487                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13488                         ) {
13489                                 p = NULL;
13490                         }
13491                 }
13492                 setpwd(p, 0);
13493         }
13494 }
13495
13496
13497 //usage:#define ash_trivial_usage
13498 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13499 //usage:#define ash_full_usage "\n\n"
13500 //usage:        "Unix shell interpreter"
13501
13502 /*
13503  * Process the shell command line arguments.
13504  */
13505 static void
13506 procargs(char **argv)
13507 {
13508         int i;
13509         const char *xminusc;
13510         char **xargv;
13511
13512         xargv = argv;
13513         arg0 = xargv[0];
13514         /* if (xargv[0]) - mmm, this is always true! */
13515                 xargv++;
13516         for (i = 0; i < NOPTS; i++)
13517                 optlist[i] = 2;
13518         argptr = xargv;
13519         if (options(/*cmdline:*/ 1)) {
13520                 /* it already printed err message */
13521                 raise_exception(EXERROR);
13522         }
13523         xargv = argptr;
13524         xminusc = minusc;
13525         if (*xargv == NULL) {
13526                 if (xminusc)
13527                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13528                 sflag = 1;
13529         }
13530         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13531                 iflag = 1;
13532         if (mflag == 2)
13533                 mflag = iflag;
13534         for (i = 0; i < NOPTS; i++)
13535                 if (optlist[i] == 2)
13536                         optlist[i] = 0;
13537 #if DEBUG == 2
13538         debug = 1;
13539 #endif
13540         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13541         if (xminusc) {
13542                 minusc = *xargv++;
13543                 if (*xargv)
13544                         goto setarg0;
13545         } else if (!sflag) {
13546                 setinputfile(*xargv, 0);
13547  setarg0:
13548                 arg0 = *xargv++;
13549                 commandname = arg0;
13550         }
13551
13552         shellparam.p = xargv;
13553 #if ENABLE_ASH_GETOPTS
13554         shellparam.optind = 1;
13555         shellparam.optoff = -1;
13556 #endif
13557         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13558         while (*xargv) {
13559                 shellparam.nparam++;
13560                 xargv++;
13561         }
13562         optschanged();
13563 }
13564
13565 /*
13566  * Read /etc/profile, ~/.profile, $ENV.
13567  */
13568 static void
13569 read_profile(const char *name)
13570 {
13571         name = expandstr(name);
13572         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13573                 return;
13574         cmdloop(0);
13575         popfile();
13576 }
13577
13578 /*
13579  * This routine is called when an error or an interrupt occurs in an
13580  * interactive shell and control is returned to the main command loop.
13581  * (In dash, this function is auto-generated by build machinery).
13582  */
13583 static void
13584 reset(void)
13585 {
13586         /* from eval.c: */
13587         evalskip = 0;
13588         loopnest = 0;
13589
13590         /* from expand.c: */
13591         ifsfree();
13592
13593         /* from input.c: */
13594         g_parsefile->left_in_buffer = 0;
13595         g_parsefile->left_in_line = 0;      /* clear input buffer */
13596         popallfiles();
13597
13598         /* from redir.c: */
13599         while (redirlist)
13600                 popredir(/*drop:*/ 0, /*restore:*/ 0);
13601
13602         /* from var.c: */
13603         while (localvar_stack)
13604                 poplocalvars();
13605 }
13606
13607 #if PROFILE
13608 static short profile_buf[16384];
13609 extern int etext();
13610 #endif
13611
13612 /*
13613  * Main routine.  We initialize things, parse the arguments, execute
13614  * profiles if we're a login shell, and then call cmdloop to execute
13615  * commands.  The setjmp call sets up the location to jump to when an
13616  * exception occurs.  When an exception occurs the variable "state"
13617  * is used to figure out how far we had gotten.
13618  */
13619 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13620 int ash_main(int argc UNUSED_PARAM, char **argv)
13621 {
13622         volatile smallint state;
13623         struct jmploc jmploc;
13624         struct stackmark smark;
13625
13626         /* Initialize global data */
13627         INIT_G_misc();
13628         INIT_G_memstack();
13629         INIT_G_var();
13630 #if ENABLE_ASH_ALIAS
13631         INIT_G_alias();
13632 #endif
13633         INIT_G_cmdtable();
13634
13635 #if PROFILE
13636         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13637 #endif
13638
13639 #if ENABLE_FEATURE_EDITING
13640         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13641 #endif
13642         state = 0;
13643         if (setjmp(jmploc.loc)) {
13644                 smallint e;
13645                 smallint s;
13646
13647                 reset();
13648
13649                 e = exception_type;
13650                 s = state;
13651                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13652                         exitshell();
13653                 }
13654                 if (e == EXINT) {
13655                         newline_and_flush(stderr);
13656                 }
13657
13658                 popstackmark(&smark);
13659                 FORCE_INT_ON; /* enable interrupts */
13660                 if (s == 1)
13661                         goto state1;
13662                 if (s == 2)
13663                         goto state2;
13664                 if (s == 3)
13665                         goto state3;
13666                 goto state4;
13667         }
13668         exception_handler = &jmploc;
13669         rootpid = getpid();
13670
13671         init();
13672         setstackmark(&smark);
13673         procargs(argv);
13674 #if DEBUG
13675         TRACE(("Shell args: "));
13676         trace_puts_args(argv);
13677 #endif
13678
13679         if (argv[0] && argv[0][0] == '-')
13680                 isloginsh = 1;
13681         if (isloginsh) {
13682                 const char *hp;
13683
13684                 state = 1;
13685                 read_profile("/etc/profile");
13686  state1:
13687                 state = 2;
13688                 hp = lookupvar("HOME");
13689                 if (hp)
13690                         read_profile("$HOME/.profile");
13691         }
13692  state2:
13693         state = 3;
13694         if (
13695 #ifndef linux
13696          getuid() == geteuid() && getgid() == getegid() &&
13697 #endif
13698          iflag
13699         ) {
13700                 const char *shinit = lookupvar("ENV");
13701                 if (shinit != NULL && *shinit != '\0')
13702                         read_profile(shinit);
13703         }
13704         popstackmark(&smark);
13705  state3:
13706         state = 4;
13707         if (minusc) {
13708                 /* evalstring pushes parsefile stack.
13709                  * Ensure we don't falsely claim that 0 (stdin)
13710                  * is one of stacked source fds.
13711                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13712                 // if (!sflag) g_parsefile->pf_fd = -1;
13713                 // ^^ not necessary since now we special-case fd 0
13714                 // in is_hidden_fd() to not be considered "hidden fd"
13715                 evalstring(minusc, sflag ? 0 : EV_EXIT);
13716         }
13717
13718         if (sflag || minusc == NULL) {
13719 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13720                 if (iflag) {
13721                         const char *hp = lookupvar("HISTFILE");
13722                         if (!hp) {
13723                                 hp = lookupvar("HOME");
13724                                 if (hp) {
13725                                         INT_OFF;
13726                                         hp = concat_path_file(hp, ".ash_history");
13727                                         setvar0("HISTFILE", hp);
13728                                         free((char*)hp);
13729                                         INT_ON;
13730                                         hp = lookupvar("HISTFILE");
13731                                 }
13732                         }
13733                         if (hp)
13734                                 line_input_state->hist_file = hp;
13735 # if ENABLE_FEATURE_SH_HISTFILESIZE
13736                         hp = lookupvar("HISTFILESIZE");
13737                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13738 # endif
13739                 }
13740 #endif
13741  state4: /* XXX ??? - why isn't this before the "if" statement */
13742                 cmdloop(1);
13743         }
13744 #if PROFILE
13745         monitor(0);
13746 #endif
13747 #ifdef GPROF
13748         {
13749                 extern void _mcleanup(void);
13750                 _mcleanup();
13751         }
13752 #endif
13753         TRACE(("End of main reached\n"));
13754         exitshell();
13755         /* NOTREACHED */
13756 }
13757
13758
13759 /*-
13760  * Copyright (c) 1989, 1991, 1993, 1994
13761  *      The Regents of the University of California.  All rights reserved.
13762  *
13763  * This code is derived from software contributed to Berkeley by
13764  * Kenneth Almquist.
13765  *
13766  * Redistribution and use in source and binary forms, with or without
13767  * modification, are permitted provided that the following conditions
13768  * are met:
13769  * 1. Redistributions of source code must retain the above copyright
13770  *    notice, this list of conditions and the following disclaimer.
13771  * 2. Redistributions in binary form must reproduce the above copyright
13772  *    notice, this list of conditions and the following disclaimer in the
13773  *    documentation and/or other materials provided with the distribution.
13774  * 3. Neither the name of the University nor the names of its contributors
13775  *    may be used to endorse or promote products derived from this software
13776  *    without specific prior written permission.
13777  *
13778  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13779  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13780  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13781  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13782  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13783  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13784  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13785  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13786  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13787  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13788  * SUCH DAMAGE.
13789  */