ash: "Undo all redirections" comment is wrong, delete it
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * Original BSD copyright notice is retained at the end of this file.
9  *
10  * Copyright (c) 1989, 1991, 1993, 1994
11  *      The Regents of the University of California.  All rights reserved.
12  *
13  * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
14  * was re-ported from NetBSD and debianized.
15  *
16  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
17  */
18 //config:config ASH
19 //config:       bool "ash (77 kb)"
20 //config:       default y
21 //config:       depends on !NOMMU
22 //config:       help
23 //config:       The most complete and most pedantically correct shell included with
24 //config:       busybox. This shell is actually a derivative of the Debian 'dash'
25 //config:       shell (by Herbert Xu), which was created by porting the 'ash' shell
26 //config:       (written by Kenneth Almquist) from NetBSD.
27 //config:
28 //config:# ash options
29 //config:# note: Don't remove !NOMMU part in the next line; it would break
30 //config:# menuconfig's indenting.
31 //config:if !NOMMU && (ASH || SH_IS_ASH || BASH_IS_ASH)
32 //config:
33 //config:config ASH_OPTIMIZE_FOR_SIZE
34 //config:       bool "Optimize for size instead of speed"
35 //config:       default y
36 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
37 //config:
38 //config:config ASH_INTERNAL_GLOB
39 //config:       bool "Use internal glob() implementation"
40 //config:       default y       # Y is bigger, but because of uclibc glob() bug, let Y be default for now
41 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
42 //config:       help
43 //config:       Do not use glob() function from libc, use internal implementation.
44 //config:       Use this if you are getting "glob.h: No such file or directory"
45 //config:       or similar build errors.
46 //config:       Note that as of now (2017-01), uclibc and musl glob() both have bugs
47 //config:       which would break ash if you select N here.
48 //config:
49 //config:config ASH_BASH_COMPAT
50 //config:       bool "bash-compatible extensions"
51 //config:       default y
52 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
53 //config:
54 //config:config ASH_JOB_CONTROL
55 //config:       bool "Job control"
56 //config:       default y
57 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
58 //config:
59 //config:config ASH_ALIAS
60 //config:       bool "Alias support"
61 //config:       default y
62 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
63 //config:
64 //config:config ASH_RANDOM_SUPPORT
65 //config:       bool "Pseudorandom generator and $RANDOM variable"
66 //config:       default y
67 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
68 //config:       help
69 //config:       Enable pseudorandom generator and dynamic variable "$RANDOM".
70 //config:       Each read of "$RANDOM" will generate a new pseudorandom value.
71 //config:       You can reset the generator by using a specified start value.
72 //config:       After "unset RANDOM" the generator will switch off and this
73 //config:       variable will no longer have special treatment.
74 //config:
75 //config:config ASH_EXPAND_PRMT
76 //config:       bool "Expand prompt string"
77 //config:       default y
78 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
79 //config:       help
80 //config:       $PS# may contain volatile content, such as backquote commands.
81 //config:       This option recreates the prompt string from the environment
82 //config:       variable each time it is displayed.
83 //config:
84 //config:config ASH_IDLE_TIMEOUT
85 //config:       bool "Idle timeout variable $TMOUT"
86 //config:       default y
87 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
88 //config:       help
89 //config:       Enable bash-like auto-logout after $TMOUT seconds of idle time.
90 //config:
91 //config:config ASH_MAIL
92 //config:       bool "Check for new mail in interactive shell"
93 //config:       default y
94 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
95 //config:       help
96 //config:       Enable "check for new mail" function:
97 //config:       if set, $MAIL file and $MAILPATH list of files
98 //config:       are checked for mtime changes, and "you have mail"
99 //config:       message is printed if change is detected.
100 //config:
101 //config:config ASH_ECHO
102 //config:       bool "echo builtin"
103 //config:       default y
104 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
105 //config:
106 //config:config ASH_PRINTF
107 //config:       bool "printf builtin"
108 //config:       default y
109 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
110 //config:
111 //config:config ASH_TEST
112 //config:       bool "test builtin"
113 //config:       default y
114 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
115 //config:
116 //config:config ASH_HELP
117 //config:       bool "help builtin"
118 //config:       default y
119 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
120 //config:
121 //config:config ASH_GETOPTS
122 //config:       bool "getopts builtin"
123 //config:       default y
124 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
125 //config:
126 //config:config ASH_CMDCMD
127 //config:       bool "command builtin"
128 //config:       default y
129 //config:       depends on ASH || SH_IS_ASH || BASH_IS_ASH
130 //config:       help
131 //config:       Enable support for the 'command' builtin, which allows
132 //config:       you to run the specified command or builtin,
133 //config:       even when there is a function with the same name.
134 //config:
135 //config:endif # ash options
136
137 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
138 //                      APPLET_ODDNAME:name  main location    suid_type     help
139 //applet:IF_SH_IS_ASH(  APPLET_ODDNAME(sh,   ash, BB_DIR_BIN, BB_SUID_DROP, ash))
140 //applet:IF_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, ash))
141
142 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
143 //kbuild:lib-$(CONFIG_SH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
144 //kbuild:lib-$(CONFIG_BASH_IS_ASH) += ash.o ash_ptr_hack.o shell_common.o
145 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
146
147 /*
148  * DEBUG=1 to compile in debugging ('set -o debug' turns on)
149  * DEBUG=2 to compile in and turn on debugging.
150  * When debugging is on ("set -o debug" was executed, or DEBUG=2),
151  * debugging info is written to ./trace, quit signal generates core dump.
152  */
153 #define DEBUG 0
154 /* Tweak debug output verbosity here */
155 #define DEBUG_TIME 0
156 #define DEBUG_PID 1
157 #define DEBUG_SIG 1
158 #define DEBUG_INTONOFF 0
159
160 #define PROFILE 0
161
162 #define JOBS ENABLE_ASH_JOB_CONTROL
163
164 #include <setjmp.h>
165 #include <fnmatch.h>
166 #include <sys/times.h>
167 #include <sys/utsname.h> /* for setting $HOSTNAME */
168 #include "busybox.h" /* for applet_names */
169
170 /* So far, all bash compat is controlled by one config option */
171 /* Separate defines document which part of code implements what */
172 /* function keyword */
173 #define    BASH_FUNCTION        ENABLE_ASH_BASH_COMPAT
174 #define IF_BASH_FUNCTION            IF_ASH_BASH_COMPAT
175 /* &>file */
176 #define    BASH_REDIR_OUTPUT    ENABLE_ASH_BASH_COMPAT
177 #define IF_BASH_REDIR_OUTPUT        IF_ASH_BASH_COMPAT
178 /* $'...' */
179 #define    BASH_DOLLAR_SQUOTE   ENABLE_ASH_BASH_COMPAT
180 #define IF_BASH_DOLLAR_SQUOTE       IF_ASH_BASH_COMPAT
181 #define    BASH_PATTERN_SUBST   ENABLE_ASH_BASH_COMPAT
182 #define IF_BASH_PATTERN_SUBST       IF_ASH_BASH_COMPAT
183 #define    BASH_SUBSTR          ENABLE_ASH_BASH_COMPAT
184 #define IF_BASH_SUBSTR              IF_ASH_BASH_COMPAT
185 /* [[ EXPR ]] */
186 #define    BASH_TEST2           (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
187 #define    BASH_SOURCE          ENABLE_ASH_BASH_COMPAT
188 #define    BASH_PIPEFAIL        ENABLE_ASH_BASH_COMPAT
189 #define    BASH_HOSTNAME_VAR    ENABLE_ASH_BASH_COMPAT
190 #define    BASH_SHLVL_VAR       ENABLE_ASH_BASH_COMPAT
191
192 #if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
193 /* Bionic at least up to version 24 has no glob() */
194 # undef  ENABLE_ASH_INTERNAL_GLOB
195 # define ENABLE_ASH_INTERNAL_GLOB 1
196 #endif
197
198 #if !ENABLE_ASH_INTERNAL_GLOB && defined(__UCLIBC__)
199 # error uClibc glob() is buggy, use ASH_INTERNAL_GLOB.
200 # error The bug is: for "$PWD"/<pattern> ash will escape e.g. dashes in "$PWD"
201 # error with backslash, even ones which do not need to be: "/a-b" -> "/a\-b"
202 # error glob() should unbackslash them and match. uClibc does not unbackslash,
203 # error fails to match dirname, subsequently not expanding <pattern> in it.
204 // Testcase:
205 // if (glob("/etc/polkit\\-1", 0, NULL, &pglob)) - this returns 0 on uclibc, no bug
206 // if (glob("/etc/polkit\\-1/*", 0, NULL, &pglob)) printf("uclibc bug!\n");
207 #endif
208
209 #if !ENABLE_ASH_INTERNAL_GLOB
210 # include <glob.h>
211 #endif
212
213 #include "unicode.h"
214 #include "shell_common.h"
215 #if ENABLE_FEATURE_SH_MATH
216 # include "math.h"
217 #else
218 typedef long arith_t;
219 # define ARITH_FMT "%ld"
220 #endif
221 #if ENABLE_ASH_RANDOM_SUPPORT
222 # include "random.h"
223 #else
224 # define CLEAR_RANDOM_T(rnd) ((void)0)
225 #endif
226
227 #include "NUM_APPLETS.h"
228 #if NUM_APPLETS == 1
229 /* STANDALONE does not make sense, and won't compile */
230 # undef CONFIG_FEATURE_SH_STANDALONE
231 # undef ENABLE_FEATURE_SH_STANDALONE
232 # undef IF_FEATURE_SH_STANDALONE
233 # undef IF_NOT_FEATURE_SH_STANDALONE
234 # define ENABLE_FEATURE_SH_STANDALONE 0
235 # define IF_FEATURE_SH_STANDALONE(...)
236 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
237 #endif
238
239 #ifndef PIPE_BUF
240 # define PIPE_BUF 4096           /* amount of buffering in a pipe */
241 #endif
242
243 #if !BB_MMU
244 # error "Do not even bother, ash will not run on NOMMU machine"
245 #endif
246
247
248 /* ============ Hash table sizes. Configurable. */
249
250 #define VTABSIZE 39
251 #define ATABSIZE 39
252 #define CMDTABLESIZE 31         /* should be prime */
253
254
255 /* ============ Shell options */
256
257 static const char *const optletters_optnames[] = {
258         "e"   "errexit",
259         "f"   "noglob",
260         "I"   "ignoreeof",
261         "i"   "interactive",
262         "m"   "monitor",
263         "n"   "noexec",
264         "s"   "stdin",
265         "x"   "xtrace",
266         "v"   "verbose",
267         "C"   "noclobber",
268         "a"   "allexport",
269         "b"   "notify",
270         "u"   "nounset",
271         "\0"  "vi"
272 #if BASH_PIPEFAIL
273         ,"\0"  "pipefail"
274 #endif
275 #if DEBUG
276         ,"\0"  "nolog"
277         ,"\0"  "debug"
278 #endif
279 };
280
281 #define optletters(n)  optletters_optnames[n][0]
282 #define optnames(n)   (optletters_optnames[n] + 1)
283
284 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
285
286
287 /* ============ Misc data */
288
289 #define msg_illnum "Illegal number: %s"
290
291 /*
292  * We enclose jmp_buf in a structure so that we can declare pointers to
293  * jump locations.  The global variable handler contains the location to
294  * jump to when an exception occurs, and the global variable exception_type
295  * contains a code identifying the exception.  To implement nested
296  * exception handlers, the user should save the value of handler on entry
297  * to an inner scope, set handler to point to a jmploc structure for the
298  * inner scope, and restore handler on exit from the scope.
299  */
300 struct jmploc {
301         jmp_buf loc;
302 };
303
304 struct globals_misc {
305         uint8_t exitstatus;     /* exit status of last command */
306         uint8_t back_exitstatus;/* exit status of backquoted command */
307         smallint job_warning;   /* user was warned about stopped jobs (can be 2, 1 or 0). */
308         int rootpid;            /* pid of main shell */
309         /* shell level: 0 for the main shell, 1 for its children, and so on */
310         int shlvl;
311 #define rootshell (!shlvl)
312         char *minusc;  /* argument to -c option */
313
314         char *curdir; // = nullstr;     /* current working directory */
315         char *physdir; // = nullstr;    /* physical working directory */
316
317         char *arg0; /* value of $0 */
318
319         struct jmploc *exception_handler;
320
321         volatile int suppress_int; /* counter */
322         volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
323         volatile /*sig_atomic_t*/ smallint got_sigchld; /* 1 = got SIGCHLD */
324         volatile /*sig_atomic_t*/ smallint pending_sig; /* last pending signal */
325         smallint exception_type; /* kind of exception (0..5) */
326         /* exceptions */
327 #define EXINT 0         /* SIGINT received */
328 #define EXERROR 1       /* a generic error */
329 #define EXEXIT 4        /* exit the shell */
330
331         smallint isloginsh;
332         char nullstr[1];        /* zero length string */
333
334         char optlist[NOPTS];
335 #define eflag optlist[0]
336 #define fflag optlist[1]
337 #define Iflag optlist[2]
338 #define iflag optlist[3]
339 #define mflag optlist[4]
340 #define nflag optlist[5]
341 #define sflag optlist[6]
342 #define xflag optlist[7]
343 #define vflag optlist[8]
344 #define Cflag optlist[9]
345 #define aflag optlist[10]
346 #define bflag optlist[11]
347 #define uflag optlist[12]
348 #define viflag optlist[13]
349 #if BASH_PIPEFAIL
350 # define pipefail optlist[14]
351 #else
352 # define pipefail 0
353 #endif
354 #if DEBUG
355 # define nolog optlist[14 + BASH_PIPEFAIL]
356 # define debug optlist[15 + BASH_PIPEFAIL]
357 #endif
358
359         /* trap handler commands */
360         /*
361          * Sigmode records the current value of the signal handlers for the various
362          * modes.  A value of zero means that the current handler is not known.
363          * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
364          */
365         char sigmode[NSIG - 1];
366 #define S_DFL      1            /* default signal handling (SIG_DFL) */
367 #define S_CATCH    2            /* signal is caught */
368 #define S_IGN      3            /* signal is ignored (SIG_IGN) */
369 #define S_HARD_IGN 4            /* signal is ignored permanently */
370
371         /* indicates specified signal received */
372         uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
373         uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
374         char *trap[NSIG];
375         char **trap_ptr;        /* used only by "trap hack" */
376
377         /* Rarely referenced stuff */
378 #if ENABLE_ASH_RANDOM_SUPPORT
379         random_t random_gen;
380 #endif
381         pid_t backgndpid;        /* pid of last background process */
382 };
383 extern struct globals_misc *const ash_ptr_to_globals_misc;
384 #define G_misc (*ash_ptr_to_globals_misc)
385 #define exitstatus        (G_misc.exitstatus )
386 #define back_exitstatus   (G_misc.back_exitstatus )
387 #define job_warning       (G_misc.job_warning)
388 #define rootpid     (G_misc.rootpid    )
389 #define shlvl       (G_misc.shlvl      )
390 #define minusc      (G_misc.minusc     )
391 #define curdir      (G_misc.curdir     )
392 #define physdir     (G_misc.physdir    )
393 #define arg0        (G_misc.arg0       )
394 #define exception_handler (G_misc.exception_handler)
395 #define exception_type    (G_misc.exception_type   )
396 #define suppress_int      (G_misc.suppress_int     )
397 #define pending_int       (G_misc.pending_int      )
398 #define got_sigchld       (G_misc.got_sigchld      )
399 #define pending_sig       (G_misc.pending_sig      )
400 #define isloginsh   (G_misc.isloginsh  )
401 #define nullstr     (G_misc.nullstr    )
402 #define optlist     (G_misc.optlist    )
403 #define sigmode     (G_misc.sigmode    )
404 #define gotsig      (G_misc.gotsig     )
405 #define may_have_traps    (G_misc.may_have_traps   )
406 #define trap        (G_misc.trap       )
407 #define trap_ptr    (G_misc.trap_ptr   )
408 #define random_gen  (G_misc.random_gen )
409 #define backgndpid  (G_misc.backgndpid )
410 #define INIT_G_misc() do { \
411         (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
412         barrier(); \
413         curdir = nullstr; \
414         physdir = nullstr; \
415         trap_ptr = trap; \
416 } while (0)
417
418
419 /* ============ DEBUG */
420 #if DEBUG
421 static void trace_printf(const char *fmt, ...);
422 static void trace_vprintf(const char *fmt, va_list va);
423 # define TRACE(param)    trace_printf param
424 # define TRACEV(param)   trace_vprintf param
425 # define close(fd) do { \
426         int dfd = (fd); \
427         if (close(dfd) < 0) \
428                 bb_error_msg("bug on %d: closing %d(0x%x)", \
429                         __LINE__, dfd, dfd); \
430 } while (0)
431 #else
432 # define TRACE(param)
433 # define TRACEV(param)
434 #endif
435
436
437 /* ============ Utility functions */
438 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
439 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
440
441 static int
442 isdigit_str9(const char *str)
443 {
444         int maxlen = 9 + 1; /* max 9 digits: 999999999 */
445         while (--maxlen && isdigit(*str))
446                 str++;
447         return (*str == '\0');
448 }
449
450 static const char *
451 var_end(const char *var)
452 {
453         while (*var)
454                 if (*var++ == '=')
455                         break;
456         return var;
457 }
458
459
460 /* ============ Interrupts / exceptions */
461
462 static void exitshell(void) NORETURN;
463
464 /*
465  * These macros allow the user to suspend the handling of interrupt signals
466  * over a period of time.  This is similar to SIGHOLD or to sigblock, but
467  * much more efficient and portable.  (But hacking the kernel is so much
468  * more fun than worrying about efficiency and portability. :-))
469  */
470 #if DEBUG_INTONOFF
471 # define INT_OFF do { \
472         TRACE(("%s:%d INT_OFF(%d)\n", __func__, __LINE__, suppress_int)); \
473         suppress_int++; \
474         barrier(); \
475 } while (0)
476 #else
477 # define INT_OFF do { \
478         suppress_int++; \
479         barrier(); \
480 } while (0)
481 #endif
482
483 /*
484  * Called to raise an exception.  Since C doesn't include exceptions, we
485  * just do a longjmp to the exception handler.  The type of exception is
486  * stored in the global variable "exception_type".
487  */
488 static void raise_exception(int) NORETURN;
489 static void
490 raise_exception(int e)
491 {
492 #if DEBUG
493         if (exception_handler == NULL)
494                 abort();
495 #endif
496         INT_OFF;
497         exception_type = e;
498         longjmp(exception_handler->loc, 1);
499 }
500 #if DEBUG
501 #define raise_exception(e) do { \
502         TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
503         raise_exception(e); \
504 } while (0)
505 #endif
506
507 /*
508  * Called when a SIGINT is received.  (If the user specifies
509  * that SIGINT is to be trapped or ignored using the trap builtin, then
510  * this routine is not called.)  Suppressint is nonzero when interrupts
511  * are held using the INT_OFF macro.  (The test for iflag is just
512  * defensive programming.)
513  */
514 static void raise_interrupt(void) NORETURN;
515 static void
516 raise_interrupt(void)
517 {
518         pending_int = 0;
519         /* Signal is not automatically unmasked after it is raised,
520          * do it ourself - unmask all signals */
521         sigprocmask_allsigs(SIG_UNBLOCK);
522         /* pending_sig = 0; - now done in signal_handler() */
523
524         if (!(rootshell && iflag)) {
525                 /* Kill ourself with SIGINT */
526                 signal(SIGINT, SIG_DFL);
527                 raise(SIGINT);
528         }
529         /* bash: ^C even on empty command line sets $? */
530         exitstatus = SIGINT + 128;
531         raise_exception(EXINT);
532         /* NOTREACHED */
533 }
534 #if DEBUG
535 #define raise_interrupt() do { \
536         TRACE(("raising interrupt on line %d\n", __LINE__)); \
537         raise_interrupt(); \
538 } while (0)
539 #endif
540
541 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
542 int_on(void)
543 {
544         barrier();
545         if (--suppress_int == 0 && pending_int) {
546                 raise_interrupt();
547         }
548 }
549 #if DEBUG_INTONOFF
550 # define INT_ON do { \
551         TRACE(("%s:%d INT_ON(%d)\n", __func__, __LINE__, suppress_int-1)); \
552         int_on(); \
553 } while (0)
554 #else
555 # define INT_ON int_on()
556 #endif
557 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
558 force_int_on(void)
559 {
560         barrier();
561         suppress_int = 0;
562         if (pending_int)
563                 raise_interrupt();
564 }
565 #define FORCE_INT_ON force_int_on()
566
567 #define SAVE_INT(v) ((v) = suppress_int)
568
569 #define RESTORE_INT(v) do { \
570         barrier(); \
571         suppress_int = (v); \
572         if (suppress_int == 0 && pending_int) \
573                 raise_interrupt(); \
574 } while (0)
575
576
577 /* ============ Stdout/stderr output */
578
579 static void
580 outstr(const char *p, FILE *file)
581 {
582         INT_OFF;
583         fputs(p, file);
584         INT_ON;
585 }
586
587 static void
588 flush_stdout_stderr(void)
589 {
590         INT_OFF;
591         fflush_all();
592         INT_ON;
593 }
594
595 /* Was called outcslow(c,FILE*), but c was always '\n' */
596 static void
597 newline_and_flush(FILE *dest)
598 {
599         INT_OFF;
600         putc('\n', dest);
601         fflush(dest);
602         INT_ON;
603 }
604
605 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
606 static int
607 out1fmt(const char *fmt, ...)
608 {
609         va_list ap;
610         int r;
611
612         INT_OFF;
613         va_start(ap, fmt);
614         r = vprintf(fmt, ap);
615         va_end(ap);
616         INT_ON;
617         return r;
618 }
619
620 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
621 static int
622 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
623 {
624         va_list ap;
625         int ret;
626
627         INT_OFF;
628         va_start(ap, fmt);
629         ret = vsnprintf(outbuf, length, fmt, ap);
630         va_end(ap);
631         INT_ON;
632         return ret;
633 }
634
635 static void
636 out1str(const char *p)
637 {
638         outstr(p, stdout);
639 }
640
641 static void
642 out2str(const char *p)
643 {
644         outstr(p, stderr);
645         flush_stdout_stderr();
646 }
647
648
649 /* ============ Parser structures */
650
651 /* control characters in argument strings */
652 #define CTL_FIRST CTLESC
653 #define CTLESC       ((unsigned char)'\201')    /* escape next character */
654 #define CTLVAR       ((unsigned char)'\202')    /* variable defn */
655 #define CTLENDVAR    ((unsigned char)'\203')
656 #define CTLBACKQ     ((unsigned char)'\204')
657 #define CTLARI       ((unsigned char)'\206')    /* arithmetic expression */
658 #define CTLENDARI    ((unsigned char)'\207')
659 #define CTLQUOTEMARK ((unsigned char)'\210')
660 #define CTL_LAST CTLQUOTEMARK
661
662 /* variable substitution byte (follows CTLVAR) */
663 #define VSTYPE  0x0f            /* type of variable substitution */
664 #define VSNUL   0x10            /* colon--treat the empty string as unset */
665
666 /* values of VSTYPE field */
667 #define VSNORMAL        0x1     /* normal variable:  $var or ${var} */
668 #define VSMINUS         0x2     /* ${var-text} */
669 #define VSPLUS          0x3     /* ${var+text} */
670 #define VSQUESTION      0x4     /* ${var?message} */
671 #define VSASSIGN        0x5     /* ${var=text} */
672 #define VSTRIMRIGHT     0x6     /* ${var%pattern} */
673 #define VSTRIMRIGHTMAX  0x7     /* ${var%%pattern} */
674 #define VSTRIMLEFT      0x8     /* ${var#pattern} */
675 #define VSTRIMLEFTMAX   0x9     /* ${var##pattern} */
676 #define VSLENGTH        0xa     /* ${#var} */
677 #if BASH_SUBSTR
678 #define VSSUBSTR        0xc     /* ${var:position:length} */
679 #endif
680 #if BASH_PATTERN_SUBST
681 #define VSREPLACE       0xd     /* ${var/pattern/replacement} */
682 #define VSREPLACEALL    0xe     /* ${var//pattern/replacement} */
683 #endif
684
685 static const char dolatstr[] ALIGN1 = {
686         CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=', CTLQUOTEMARK, '\0'
687 };
688 #define DOLATSTRLEN 6
689
690 #define NCMD      0
691 #define NPIPE     1
692 #define NREDIR    2
693 #define NBACKGND  3
694 #define NSUBSHELL 4
695 #define NAND      5
696 #define NOR       6
697 #define NSEMI     7
698 #define NIF       8
699 #define NWHILE    9
700 #define NUNTIL   10
701 #define NFOR     11
702 #define NCASE    12
703 #define NCLIST   13
704 #define NDEFUN   14
705 #define NARG     15
706 #define NTO      16
707 #if BASH_REDIR_OUTPUT
708 #define NTO2     17
709 #endif
710 #define NCLOBBER 18
711 #define NFROM    19
712 #define NFROMTO  20
713 #define NAPPEND  21
714 #define NTOFD    22
715 #define NFROMFD  23
716 #define NHERE    24
717 #define NXHERE   25
718 #define NNOT     26
719 #define N_NUMBER 27
720
721 union node;
722
723 struct ncmd {
724         smallint type; /* Nxxxx */
725         union node *assign;
726         union node *args;
727         union node *redirect;
728 };
729
730 struct npipe {
731         smallint type;
732         smallint pipe_backgnd;
733         struct nodelist *cmdlist;
734 };
735
736 struct nredir {
737         smallint type;
738         union node *n;
739         union node *redirect;
740 };
741
742 struct nbinary {
743         smallint type;
744         union node *ch1;
745         union node *ch2;
746 };
747
748 struct nif {
749         smallint type;
750         union node *test;
751         union node *ifpart;
752         union node *elsepart;
753 };
754
755 struct nfor {
756         smallint type;
757         union node *args;
758         union node *body;
759         char *var;
760 };
761
762 struct ncase {
763         smallint type;
764         union node *expr;
765         union node *cases;
766 };
767
768 struct nclist {
769         smallint type;
770         union node *next;
771         union node *pattern;
772         union node *body;
773 };
774
775 struct narg {
776         smallint type;
777         union node *next;
778         char *text;
779         struct nodelist *backquote;
780 };
781
782 /* nfile and ndup layout must match!
783  * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
784  * that it is actually NTO2 (>&file), and change its type.
785  */
786 struct nfile {
787         smallint type;
788         union node *next;
789         int fd;
790         int _unused_dupfd;
791         union node *fname;
792         char *expfname;
793 };
794
795 struct ndup {
796         smallint type;
797         union node *next;
798         int fd;
799         int dupfd;
800         union node *vname;
801         char *_unused_expfname;
802 };
803
804 struct nhere {
805         smallint type;
806         union node *next;
807         int fd;
808         union node *doc;
809 };
810
811 struct nnot {
812         smallint type;
813         union node *com;
814 };
815
816 union node {
817         smallint type;
818         struct ncmd ncmd;
819         struct npipe npipe;
820         struct nredir nredir;
821         struct nbinary nbinary;
822         struct nif nif;
823         struct nfor nfor;
824         struct ncase ncase;
825         struct nclist nclist;
826         struct narg narg;
827         struct nfile nfile;
828         struct ndup ndup;
829         struct nhere nhere;
830         struct nnot nnot;
831 };
832
833 /*
834  * NODE_EOF is returned by parsecmd when it encounters an end of file.
835  * It must be distinct from NULL.
836  */
837 #define NODE_EOF ((union node *) -1L)
838
839 struct nodelist {
840         struct nodelist *next;
841         union node *n;
842 };
843
844 struct funcnode {
845         int count;
846         union node n;
847 };
848
849 /*
850  * Free a parse tree.
851  */
852 static void
853 freefunc(struct funcnode *f)
854 {
855         if (f && --f->count < 0)
856                 free(f);
857 }
858
859
860 /* ============ Debugging output */
861
862 #if DEBUG
863
864 static FILE *tracefile;
865
866 static void
867 trace_printf(const char *fmt, ...)
868 {
869         va_list va;
870
871         if (debug != 1)
872                 return;
873         if (DEBUG_TIME)
874                 fprintf(tracefile, "%u ", (int) time(NULL));
875         if (DEBUG_PID)
876                 fprintf(tracefile, "[%u] ", (int) getpid());
877         if (DEBUG_SIG)
878                 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
879         va_start(va, fmt);
880         vfprintf(tracefile, fmt, va);
881         va_end(va);
882 }
883
884 static void
885 trace_vprintf(const char *fmt, va_list va)
886 {
887         if (debug != 1)
888                 return;
889         vfprintf(tracefile, fmt, va);
890         fprintf(tracefile, "\n");
891 }
892
893 static void
894 trace_puts(const char *s)
895 {
896         if (debug != 1)
897                 return;
898         fputs(s, tracefile);
899 }
900
901 static void
902 trace_puts_quoted(char *s)
903 {
904         char *p;
905         char c;
906
907         if (debug != 1)
908                 return;
909         putc('"', tracefile);
910         for (p = s; *p; p++) {
911                 switch ((unsigned char)*p) {
912                 case '\n': c = 'n'; goto backslash;
913                 case '\t': c = 't'; goto backslash;
914                 case '\r': c = 'r'; goto backslash;
915                 case '\"': c = '\"'; goto backslash;
916                 case '\\': c = '\\'; goto backslash;
917                 case CTLESC: c = 'e'; goto backslash;
918                 case CTLVAR: c = 'v'; goto backslash;
919                 case CTLBACKQ: c = 'q'; goto backslash;
920  backslash:
921                         putc('\\', tracefile);
922                         putc(c, tracefile);
923                         break;
924                 default:
925                         if (*p >= ' ' && *p <= '~')
926                                 putc(*p, tracefile);
927                         else {
928                                 putc('\\', tracefile);
929                                 putc((*p >> 6) & 03, tracefile);
930                                 putc((*p >> 3) & 07, tracefile);
931                                 putc(*p & 07, tracefile);
932                         }
933                         break;
934                 }
935         }
936         putc('"', tracefile);
937 }
938
939 static void
940 trace_puts_args(char **ap)
941 {
942         if (debug != 1)
943                 return;
944         if (!*ap)
945                 return;
946         while (1) {
947                 trace_puts_quoted(*ap);
948                 if (!*++ap) {
949                         putc('\n', tracefile);
950                         break;
951                 }
952                 putc(' ', tracefile);
953         }
954 }
955
956 static void
957 opentrace(void)
958 {
959         char s[100];
960 #ifdef O_APPEND
961         int flags;
962 #endif
963
964         if (debug != 1) {
965                 if (tracefile)
966                         fflush(tracefile);
967                 /* leave open because libedit might be using it */
968                 return;
969         }
970         strcpy(s, "./trace");
971         if (tracefile) {
972                 if (!freopen(s, "a", tracefile)) {
973                         fprintf(stderr, "Can't re-open %s\n", s);
974                         debug = 0;
975                         return;
976                 }
977         } else {
978                 tracefile = fopen(s, "a");
979                 if (tracefile == NULL) {
980                         fprintf(stderr, "Can't open %s\n", s);
981                         debug = 0;
982                         return;
983                 }
984         }
985 #ifdef O_APPEND
986         flags = fcntl(fileno(tracefile), F_GETFL);
987         if (flags >= 0)
988                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
989 #endif
990         setlinebuf(tracefile);
991         fputs("\nTracing started.\n", tracefile);
992 }
993
994 static void
995 indent(int amount, char *pfx, FILE *fp)
996 {
997         int i;
998
999         for (i = 0; i < amount; i++) {
1000                 if (pfx && i == amount - 1)
1001                         fputs(pfx, fp);
1002                 putc('\t', fp);
1003         }
1004 }
1005
1006 /* little circular references here... */
1007 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
1008
1009 static void
1010 sharg(union node *arg, FILE *fp)
1011 {
1012         char *p;
1013         struct nodelist *bqlist;
1014         unsigned char subtype;
1015
1016         if (arg->type != NARG) {
1017                 out1fmt("<node type %d>\n", arg->type);
1018                 abort();
1019         }
1020         bqlist = arg->narg.backquote;
1021         for (p = arg->narg.text; *p; p++) {
1022                 switch ((unsigned char)*p) {
1023                 case CTLESC:
1024                         p++;
1025                         putc(*p, fp);
1026                         break;
1027                 case CTLVAR:
1028                         putc('$', fp);
1029                         putc('{', fp);
1030                         subtype = *++p;
1031                         if (subtype == VSLENGTH)
1032                                 putc('#', fp);
1033
1034                         while (*p != '=') {
1035                                 putc(*p, fp);
1036                                 p++;
1037                         }
1038
1039                         if (subtype & VSNUL)
1040                                 putc(':', fp);
1041
1042                         switch (subtype & VSTYPE) {
1043                         case VSNORMAL:
1044                                 putc('}', fp);
1045                                 break;
1046                         case VSMINUS:
1047                                 putc('-', fp);
1048                                 break;
1049                         case VSPLUS:
1050                                 putc('+', fp);
1051                                 break;
1052                         case VSQUESTION:
1053                                 putc('?', fp);
1054                                 break;
1055                         case VSASSIGN:
1056                                 putc('=', fp);
1057                                 break;
1058                         case VSTRIMLEFT:
1059                                 putc('#', fp);
1060                                 break;
1061                         case VSTRIMLEFTMAX:
1062                                 putc('#', fp);
1063                                 putc('#', fp);
1064                                 break;
1065                         case VSTRIMRIGHT:
1066                                 putc('%', fp);
1067                                 break;
1068                         case VSTRIMRIGHTMAX:
1069                                 putc('%', fp);
1070                                 putc('%', fp);
1071                                 break;
1072                         case VSLENGTH:
1073                                 break;
1074                         default:
1075                                 out1fmt("<subtype %d>", subtype);
1076                         }
1077                         break;
1078                 case CTLENDVAR:
1079                         putc('}', fp);
1080                         break;
1081                 case CTLBACKQ:
1082                         putc('$', fp);
1083                         putc('(', fp);
1084                         shtree(bqlist->n, -1, NULL, fp);
1085                         putc(')', fp);
1086                         break;
1087                 default:
1088                         putc(*p, fp);
1089                         break;
1090                 }
1091         }
1092 }
1093
1094 static void
1095 shcmd(union node *cmd, FILE *fp)
1096 {
1097         union node *np;
1098         int first;
1099         const char *s;
1100         int dftfd;
1101
1102         first = 1;
1103         for (np = cmd->ncmd.args; np; np = np->narg.next) {
1104                 if (!first)
1105                         putc(' ', fp);
1106                 sharg(np, fp);
1107                 first = 0;
1108         }
1109         for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1110                 if (!first)
1111                         putc(' ', fp);
1112                 dftfd = 0;
1113                 switch (np->nfile.type) {
1114                 case NTO:      s = ">>"+1; dftfd = 1; break;
1115                 case NCLOBBER: s = ">|"; dftfd = 1; break;
1116                 case NAPPEND:  s = ">>"; dftfd = 1; break;
1117 #if BASH_REDIR_OUTPUT
1118                 case NTO2:
1119 #endif
1120                 case NTOFD:    s = ">&"; dftfd = 1; break;
1121                 case NFROM:    s = "<"; break;
1122                 case NFROMFD:  s = "<&"; break;
1123                 case NFROMTO:  s = "<>"; break;
1124                 default:       s = "*error*"; break;
1125                 }
1126                 if (np->nfile.fd != dftfd)
1127                         fprintf(fp, "%d", np->nfile.fd);
1128                 fputs(s, fp);
1129                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1130                         fprintf(fp, "%d", np->ndup.dupfd);
1131                 } else {
1132                         sharg(np->nfile.fname, fp);
1133                 }
1134                 first = 0;
1135         }
1136 }
1137
1138 static void
1139 shtree(union node *n, int ind, char *pfx, FILE *fp)
1140 {
1141         struct nodelist *lp;
1142         const char *s;
1143
1144         if (n == NULL)
1145                 return;
1146
1147         indent(ind, pfx, fp);
1148
1149         if (n == NODE_EOF) {
1150                 fputs("<EOF>", fp);
1151                 return;
1152         }
1153
1154         switch (n->type) {
1155         case NSEMI:
1156                 s = "; ";
1157                 goto binop;
1158         case NAND:
1159                 s = " && ";
1160                 goto binop;
1161         case NOR:
1162                 s = " || ";
1163  binop:
1164                 shtree(n->nbinary.ch1, ind, NULL, fp);
1165                 /* if (ind < 0) */
1166                         fputs(s, fp);
1167                 shtree(n->nbinary.ch2, ind, NULL, fp);
1168                 break;
1169         case NCMD:
1170                 shcmd(n, fp);
1171                 if (ind >= 0)
1172                         putc('\n', fp);
1173                 break;
1174         case NPIPE:
1175                 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1176                         shtree(lp->n, 0, NULL, fp);
1177                         if (lp->next)
1178                                 fputs(" | ", fp);
1179                 }
1180                 if (n->npipe.pipe_backgnd)
1181                         fputs(" &", fp);
1182                 if (ind >= 0)
1183                         putc('\n', fp);
1184                 break;
1185         default:
1186                 fprintf(fp, "<node type %d>", n->type);
1187                 if (ind >= 0)
1188                         putc('\n', fp);
1189                 break;
1190         }
1191 }
1192
1193 static void
1194 showtree(union node *n)
1195 {
1196         trace_puts("showtree called\n");
1197         shtree(n, 1, NULL, stderr);
1198 }
1199
1200 #endif /* DEBUG */
1201
1202
1203 /* ============ Parser data */
1204
1205 /*
1206  * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1207  */
1208 struct strlist {
1209         struct strlist *next;
1210         char *text;
1211 };
1212
1213 struct alias;
1214
1215 struct strpush {
1216         struct strpush *prev;   /* preceding string on stack */
1217         char *prev_string;
1218         int prev_left_in_line;
1219 #if ENABLE_ASH_ALIAS
1220         struct alias *ap;       /* if push was associated with an alias */
1221 #endif
1222         char *string;           /* remember the string since it may change */
1223
1224         /* Remember last two characters for pungetc. */
1225         int lastc[2];
1226
1227         /* Number of outstanding calls to pungetc. */
1228         int unget;
1229 };
1230
1231 struct parsefile {
1232         struct parsefile *prev; /* preceding file on stack */
1233         int linno;              /* current line */
1234         int pf_fd;              /* file descriptor (or -1 if string) */
1235         int left_in_line;       /* number of chars left in this line */
1236         int left_in_buffer;     /* number of chars left in this buffer past the line */
1237         char *next_to_pgetc;    /* next char in buffer */
1238         char *buf;              /* input buffer */
1239         struct strpush *strpush; /* for pushing strings at this level */
1240         struct strpush basestrpush; /* so pushing one is fast */
1241
1242         /* Remember last two characters for pungetc. */
1243         int lastc[2];
1244
1245         /* Number of outstanding calls to pungetc. */
1246         int unget;
1247 };
1248
1249 static struct parsefile basepf;        /* top level input file */
1250 static struct parsefile *g_parsefile = &basepf;  /* current input file */
1251 static int startlinno;                 /* line # where last token started */
1252 static char *commandname;              /* currently executing command */
1253
1254
1255 /* ============ Message printing */
1256
1257 static void
1258 ash_vmsg(const char *msg, va_list ap)
1259 {
1260         fprintf(stderr, "%s: ", arg0);
1261         if (commandname) {
1262                 if (strcmp(arg0, commandname))
1263                         fprintf(stderr, "%s: ", commandname);
1264                 if (!iflag || g_parsefile->pf_fd > 0)
1265                         fprintf(stderr, "line %d: ", startlinno);
1266         }
1267         vfprintf(stderr, msg, ap);
1268         newline_and_flush(stderr);
1269 }
1270
1271 /*
1272  * Exverror is called to raise the error exception.  If the second argument
1273  * is not NULL then error prints an error message using printf style
1274  * formatting.  It then raises the error exception.
1275  */
1276 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1277 static void
1278 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1279 {
1280 #if DEBUG
1281         if (msg) {
1282                 TRACE(("ash_vmsg_and_raise(%d):", cond));
1283                 TRACEV((msg, ap));
1284         } else
1285                 TRACE(("ash_vmsg_and_raise(%d):NULL\n", cond));
1286         if (msg)
1287 #endif
1288                 ash_vmsg(msg, ap);
1289
1290         flush_stdout_stderr();
1291         raise_exception(cond);
1292         /* NOTREACHED */
1293 }
1294
1295 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1296 static void
1297 ash_msg_and_raise_error(const char *msg, ...)
1298 {
1299         va_list ap;
1300
1301         exitstatus = 2;
1302
1303         va_start(ap, msg);
1304         ash_vmsg_and_raise(EXERROR, msg, ap);
1305         /* NOTREACHED */
1306         va_end(ap);
1307 }
1308
1309 /*
1310  * Use '%m' to append error string on platforms that support it, '%s' and
1311  * strerror() on those that don't.
1312  *
1313  * 'fmt' must be a string literal.
1314  */
1315 #ifdef HAVE_PRINTF_PERCENTM
1316 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %m", ##__VA_ARGS__)
1317 #else
1318 #define ash_msg_and_raise_perror(fmt, ...) ash_msg_and_raise_error(fmt ": %s", ##__VA_ARGS__, strerror(errno))
1319 #endif
1320
1321 static void raise_error_syntax(const char *) NORETURN;
1322 static void
1323 raise_error_syntax(const char *msg)
1324 {
1325         ash_msg_and_raise_error("syntax error: %s", msg);
1326         /* NOTREACHED */
1327 }
1328
1329 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1330 static void
1331 ash_msg_and_raise(int cond, const char *msg, ...)
1332 {
1333         va_list ap;
1334
1335         va_start(ap, msg);
1336         ash_vmsg_and_raise(cond, msg, ap);
1337         /* NOTREACHED */
1338         va_end(ap);
1339 }
1340
1341 /*
1342  * error/warning routines for external builtins
1343  */
1344 static void
1345 ash_msg(const char *fmt, ...)
1346 {
1347         va_list ap;
1348
1349         va_start(ap, fmt);
1350         ash_vmsg(fmt, ap);
1351         va_end(ap);
1352 }
1353
1354 /*
1355  * Return a string describing an error.  The returned string may be a
1356  * pointer to a static buffer that will be overwritten on the next call.
1357  * Action describes the operation that got the error.
1358  */
1359 static const char *
1360 errmsg(int e, const char *em)
1361 {
1362         if (e == ENOENT || e == ENOTDIR) {
1363                 return em;
1364         }
1365         return strerror(e);
1366 }
1367
1368
1369 /* ============ Memory allocation */
1370
1371 #if 0
1372 /* I consider these wrappers nearly useless:
1373  * ok, they return you to nearest exception handler, but
1374  * how much memory do you leak in the process, making
1375  * memory starvation worse?
1376  */
1377 static void *
1378 ckrealloc(void * p, size_t nbytes)
1379 {
1380         p = realloc(p, nbytes);
1381         if (!p)
1382                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1383         return p;
1384 }
1385
1386 static void *
1387 ckmalloc(size_t nbytes)
1388 {
1389         return ckrealloc(NULL, nbytes);
1390 }
1391
1392 static void *
1393 ckzalloc(size_t nbytes)
1394 {
1395         return memset(ckmalloc(nbytes), 0, nbytes);
1396 }
1397
1398 static char *
1399 ckstrdup(const char *s)
1400 {
1401         char *p = strdup(s);
1402         if (!p)
1403                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1404         return p;
1405 }
1406 #else
1407 /* Using bbox equivalents. They exit if out of memory */
1408 # define ckrealloc xrealloc
1409 # define ckmalloc  xmalloc
1410 # define ckzalloc  xzalloc
1411 # define ckstrdup  xstrdup
1412 #endif
1413
1414 /*
1415  * It appears that grabstackstr() will barf with such alignments
1416  * because stalloc() will return a string allocated in a new stackblock.
1417  */
1418 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1419 enum {
1420         /* Most machines require the value returned from malloc to be aligned
1421          * in some way.  The following macro will get this right
1422          * on many machines.  */
1423         SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1424         /* Minimum size of a block */
1425         MINSIZE = SHELL_ALIGN(504),
1426 };
1427
1428 struct stack_block {
1429         struct stack_block *prev;
1430         char space[MINSIZE];
1431 };
1432
1433 struct stackmark {
1434         struct stack_block *stackp;
1435         char *stacknxt;
1436         size_t stacknleft;
1437 };
1438
1439
1440 struct globals_memstack {
1441         struct stack_block *g_stackp; // = &stackbase;
1442         char *g_stacknxt; // = stackbase.space;
1443         char *sstrend; // = stackbase.space + MINSIZE;
1444         size_t g_stacknleft; // = MINSIZE;
1445         struct stack_block stackbase;
1446 };
1447 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1448 #define G_memstack (*ash_ptr_to_globals_memstack)
1449 #define g_stackp     (G_memstack.g_stackp    )
1450 #define g_stacknxt   (G_memstack.g_stacknxt  )
1451 #define sstrend      (G_memstack.sstrend     )
1452 #define g_stacknleft (G_memstack.g_stacknleft)
1453 #define stackbase    (G_memstack.stackbase   )
1454 #define INIT_G_memstack() do { \
1455         (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1456         barrier(); \
1457         g_stackp = &stackbase; \
1458         g_stacknxt = stackbase.space; \
1459         g_stacknleft = MINSIZE; \
1460         sstrend = stackbase.space + MINSIZE; \
1461 } while (0)
1462
1463
1464 #define stackblock()     ((void *)g_stacknxt)
1465 #define stackblocksize() g_stacknleft
1466
1467 /*
1468  * Parse trees for commands are allocated in lifo order, so we use a stack
1469  * to make this more efficient, and also to avoid all sorts of exception
1470  * handling code to handle interrupts in the middle of a parse.
1471  *
1472  * The size 504 was chosen because the Ultrix malloc handles that size
1473  * well.
1474  */
1475 static void *
1476 stalloc(size_t nbytes)
1477 {
1478         char *p;
1479         size_t aligned;
1480
1481         aligned = SHELL_ALIGN(nbytes);
1482         if (aligned > g_stacknleft) {
1483                 size_t len;
1484                 size_t blocksize;
1485                 struct stack_block *sp;
1486
1487                 blocksize = aligned;
1488                 if (blocksize < MINSIZE)
1489                         blocksize = MINSIZE;
1490                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1491                 if (len < blocksize)
1492                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
1493                 INT_OFF;
1494                 sp = ckmalloc(len);
1495                 sp->prev = g_stackp;
1496                 g_stacknxt = sp->space;
1497                 g_stacknleft = blocksize;
1498                 sstrend = g_stacknxt + blocksize;
1499                 g_stackp = sp;
1500                 INT_ON;
1501         }
1502         p = g_stacknxt;
1503         g_stacknxt += aligned;
1504         g_stacknleft -= aligned;
1505         return p;
1506 }
1507
1508 static void *
1509 stzalloc(size_t nbytes)
1510 {
1511         return memset(stalloc(nbytes), 0, nbytes);
1512 }
1513
1514 static void
1515 stunalloc(void *p)
1516 {
1517 #if DEBUG
1518         if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1519                 write(STDERR_FILENO, "stunalloc\n", 10);
1520                 abort();
1521         }
1522 #endif
1523         g_stacknleft += g_stacknxt - (char *)p;
1524         g_stacknxt = p;
1525 }
1526
1527 /*
1528  * Like strdup but works with the ash stack.
1529  */
1530 static char *
1531 sstrdup(const char *p)
1532 {
1533         size_t len = strlen(p) + 1;
1534         return memcpy(stalloc(len), p, len);
1535 }
1536
1537 static inline void
1538 grabstackblock(size_t len)
1539 {
1540         stalloc(len);
1541 }
1542
1543 static void
1544 pushstackmark(struct stackmark *mark, size_t len)
1545 {
1546         mark->stackp = g_stackp;
1547         mark->stacknxt = g_stacknxt;
1548         mark->stacknleft = g_stacknleft;
1549         grabstackblock(len);
1550 }
1551
1552 static void
1553 setstackmark(struct stackmark *mark)
1554 {
1555         pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase);
1556 }
1557
1558 static void
1559 popstackmark(struct stackmark *mark)
1560 {
1561         struct stack_block *sp;
1562
1563         if (!mark->stackp)
1564                 return;
1565
1566         INT_OFF;
1567         while (g_stackp != mark->stackp) {
1568                 sp = g_stackp;
1569                 g_stackp = sp->prev;
1570                 free(sp);
1571         }
1572         g_stacknxt = mark->stacknxt;
1573         g_stacknleft = mark->stacknleft;
1574         sstrend = mark->stacknxt + mark->stacknleft;
1575         INT_ON;
1576 }
1577
1578 /*
1579  * When the parser reads in a string, it wants to stick the string on the
1580  * stack and only adjust the stack pointer when it knows how big the
1581  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
1582  * of space on top of the stack and stackblocklen returns the length of
1583  * this block.  Growstackblock will grow this space by at least one byte,
1584  * possibly moving it (like realloc).  Grabstackblock actually allocates the
1585  * part of the block that has been used.
1586  */
1587 static void
1588 growstackblock(void)
1589 {
1590         size_t newlen;
1591
1592         newlen = g_stacknleft * 2;
1593         if (newlen < g_stacknleft)
1594                 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1595         if (newlen < 128)
1596                 newlen += 128;
1597
1598         if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1599                 struct stack_block *sp;
1600                 struct stack_block *prevstackp;
1601                 size_t grosslen;
1602
1603                 INT_OFF;
1604                 sp = g_stackp;
1605                 prevstackp = sp->prev;
1606                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1607                 sp = ckrealloc(sp, grosslen);
1608                 sp->prev = prevstackp;
1609                 g_stackp = sp;
1610                 g_stacknxt = sp->space;
1611                 g_stacknleft = newlen;
1612                 sstrend = sp->space + newlen;
1613                 INT_ON;
1614         } else {
1615                 char *oldspace = g_stacknxt;
1616                 size_t oldlen = g_stacknleft;
1617                 char *p = stalloc(newlen);
1618
1619                 /* free the space we just allocated */
1620                 g_stacknxt = memcpy(p, oldspace, oldlen);
1621                 g_stacknleft += newlen;
1622         }
1623 }
1624
1625 /*
1626  * The following routines are somewhat easier to use than the above.
1627  * The user declares a variable of type STACKSTR, which may be declared
1628  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
1629  * the user uses the macro STPUTC to add characters to the string.  In
1630  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1631  * grown as necessary.  When the user is done, she can just leave the
1632  * string there and refer to it using stackblock().  Or she can allocate
1633  * the space for it using grabstackstr().  If it is necessary to allow
1634  * someone else to use the stack temporarily and then continue to grow
1635  * the string, the user should use grabstack to allocate the space, and
1636  * then call ungrabstr(p) to return to the previous mode of operation.
1637  *
1638  * USTPUTC is like STPUTC except that it doesn't check for overflow.
1639  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1640  * is space for at least one character.
1641  */
1642 static void *
1643 growstackstr(void)
1644 {
1645         size_t len = stackblocksize();
1646         growstackblock();
1647         return (char *)stackblock() + len;
1648 }
1649
1650 /*
1651  * Called from CHECKSTRSPACE.
1652  */
1653 static char *
1654 makestrspace(size_t newlen, char *p)
1655 {
1656         size_t len = p - g_stacknxt;
1657         size_t size;
1658
1659         for (;;) {
1660                 size_t nleft;
1661
1662                 size = stackblocksize();
1663                 nleft = size - len;
1664                 if (nleft >= newlen)
1665                         break;
1666                 growstackblock();
1667         }
1668         return (char *)stackblock() + len;
1669 }
1670
1671 static char *
1672 stack_nputstr(const char *s, size_t n, char *p)
1673 {
1674         p = makestrspace(n, p);
1675         p = (char *)mempcpy(p, s, n);
1676         return p;
1677 }
1678
1679 static char *
1680 stack_putstr(const char *s, char *p)
1681 {
1682         return stack_nputstr(s, strlen(s), p);
1683 }
1684
1685 static char *
1686 _STPUTC(int c, char *p)
1687 {
1688         if (p == sstrend)
1689                 p = growstackstr();
1690         *p++ = c;
1691         return p;
1692 }
1693
1694 #define STARTSTACKSTR(p)        ((p) = stackblock())
1695 #define STPUTC(c, p)            ((p) = _STPUTC((c), (p)))
1696 #define CHECKSTRSPACE(n, p) do { \
1697         char *q = (p); \
1698         size_t l = (n); \
1699         size_t m = sstrend - q; \
1700         if (l > m) \
1701                 (p) = makestrspace(l, q); \
1702 } while (0)
1703 #define USTPUTC(c, p)           (*(p)++ = (c))
1704 #define STACKSTRNUL(p) do { \
1705         if ((p) == sstrend) \
1706                 (p) = growstackstr(); \
1707         *(p) = '\0'; \
1708 } while (0)
1709 #define STUNPUTC(p)             (--(p))
1710 #define STTOPC(p)               ((p)[-1])
1711 #define STADJUST(amount, p)     ((p) += (amount))
1712
1713 #define grabstackstr(p)         stalloc((char *)(p) - (char *)stackblock())
1714 #define ungrabstackstr(s, p)    stunalloc(s)
1715 #define stackstrend()           ((void *)sstrend)
1716
1717
1718 /* ============ String helpers */
1719
1720 /*
1721  * prefix -- see if pfx is a prefix of string.
1722  */
1723 static char *
1724 prefix(const char *string, const char *pfx)
1725 {
1726         while (*pfx) {
1727                 if (*pfx++ != *string++)
1728                         return NULL;
1729         }
1730         return (char *) string;
1731 }
1732
1733 /*
1734  * Check for a valid number.  This should be elsewhere.
1735  */
1736 static int
1737 is_number(const char *p)
1738 {
1739         do {
1740                 if (!isdigit(*p))
1741                         return 0;
1742         } while (*++p != '\0');
1743         return 1;
1744 }
1745
1746 /*
1747  * Convert a string of digits to an integer, printing an error message on
1748  * failure.
1749  */
1750 static int
1751 number(const char *s)
1752 {
1753         if (!is_number(s))
1754                 ash_msg_and_raise_error(msg_illnum, s);
1755         return atoi(s);
1756 }
1757
1758 /*
1759  * Produce a single quoted string suitable as input to the shell.
1760  * The return string is allocated on the stack.
1761  */
1762 static char *
1763 single_quote(const char *s)
1764 {
1765         char *p;
1766
1767         STARTSTACKSTR(p);
1768
1769         do {
1770                 char *q;
1771                 size_t len;
1772
1773                 len = strchrnul(s, '\'') - s;
1774
1775                 q = p = makestrspace(len + 3, p);
1776
1777                 *q++ = '\'';
1778                 q = (char *)mempcpy(q, s, len);
1779                 *q++ = '\'';
1780                 s += len;
1781
1782                 STADJUST(q - p, p);
1783
1784                 if (*s != '\'')
1785                         break;
1786                 len = 0;
1787                 do len++; while (*++s == '\'');
1788
1789                 q = p = makestrspace(len + 3, p);
1790
1791                 *q++ = '"';
1792                 q = (char *)mempcpy(q, s - len, len);
1793                 *q++ = '"';
1794
1795                 STADJUST(q - p, p);
1796         } while (*s);
1797
1798         USTPUTC('\0', p);
1799
1800         return stackblock();
1801 }
1802
1803 /*
1804  * Produce a possibly single quoted string suitable as input to the shell.
1805  * If quoting was done, the return string is allocated on the stack,
1806  * otherwise a pointer to the original string is returned.
1807  */
1808 static const char *
1809 maybe_single_quote(const char *s)
1810 {
1811         const char *p = s;
1812
1813         while (*p) {
1814                 /* Assuming ACSII */
1815                 /* quote ctrl_chars space !"#$%&'()* */
1816                 if (*p < '+')
1817                         goto need_quoting;
1818                 /* quote ;<=>? */
1819                 if (*p >= ';' && *p <= '?')
1820                         goto need_quoting;
1821                 /* quote `[\ */
1822                 if (*p == '`')
1823                         goto need_quoting;
1824                 if (*p == '[')
1825                         goto need_quoting;
1826                 if (*p == '\\')
1827                         goto need_quoting;
1828                 /* quote {|}~ DEL and high bytes */
1829                 if (*p > 'z')
1830                         goto need_quoting;
1831                 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1832                 /* TODO: maybe avoid quoting % */
1833                 p++;
1834         }
1835         return s;
1836
1837  need_quoting:
1838         return single_quote(s);
1839 }
1840
1841
1842 /* ============ nextopt */
1843
1844 static char **argptr;                  /* argument list for builtin commands */
1845 static char *optionarg;                /* set by nextopt (like getopt) */
1846 static char *optptr;                   /* used by nextopt */
1847
1848 /*
1849  * XXX - should get rid of. Have all builtins use getopt(3).
1850  * The library getopt must have the BSD extension static variable
1851  * "optreset", otherwise it can't be used within the shell safely.
1852  *
1853  * Standard option processing (a la getopt) for builtin routines.
1854  * The only argument that is passed to nextopt is the option string;
1855  * the other arguments are unnecessary. It returns the character,
1856  * or '\0' on end of input.
1857  */
1858 static int
1859 nextopt(const char *optstring)
1860 {
1861         char *p;
1862         const char *q;
1863         char c;
1864
1865         p = optptr;
1866         if (p == NULL || *p == '\0') {
1867                 /* We ate entire "-param", take next one */
1868                 p = *argptr;
1869                 if (p == NULL)
1870                         return '\0';
1871                 if (*p != '-')
1872                         return '\0';
1873                 if (*++p == '\0') /* just "-" ? */
1874                         return '\0';
1875                 argptr++;
1876                 if (LONE_DASH(p)) /* "--" ? */
1877                         return '\0';
1878                 /* p => next "-param" */
1879         }
1880         /* p => some option char in the middle of a "-param" */
1881         c = *p++;
1882         for (q = optstring; *q != c;) {
1883                 if (*q == '\0')
1884                         ash_msg_and_raise_error("illegal option -%c", c);
1885                 if (*++q == ':')
1886                         q++;
1887         }
1888         if (*++q == ':') {
1889                 if (*p == '\0') {
1890                         p = *argptr++;
1891                         if (p == NULL)
1892                                 ash_msg_and_raise_error("no arg for -%c option", c);
1893                 }
1894                 optionarg = p;
1895                 p = NULL;
1896         }
1897         optptr = p;
1898         return c;
1899 }
1900
1901
1902 /* ============ Shell variables */
1903
1904 /*
1905  * The parsefile structure pointed to by the global variable parsefile
1906  * contains information about the current file being read.
1907  */
1908 struct shparam {
1909         int nparam;             /* # of positional parameters (without $0) */
1910 #if ENABLE_ASH_GETOPTS
1911         int optind;             /* next parameter to be processed by getopts */
1912         int optoff;             /* used by getopts */
1913 #endif
1914         unsigned char malloced; /* if parameter list dynamically allocated */
1915         char **p;               /* parameter list */
1916 };
1917
1918 /*
1919  * Free the list of positional parameters.
1920  */
1921 static void
1922 freeparam(volatile struct shparam *param)
1923 {
1924         if (param->malloced) {
1925                 char **ap, **ap1;
1926                 ap = ap1 = param->p;
1927                 while (*ap)
1928                         free(*ap++);
1929                 free(ap1);
1930         }
1931 }
1932
1933 #if ENABLE_ASH_GETOPTS
1934 static void FAST_FUNC getoptsreset(const char *value);
1935 #endif
1936
1937 struct var {
1938         struct var *next;               /* next entry in hash list */
1939         int flags;                      /* flags are defined above */
1940         const char *var_text;           /* name=value */
1941         void (*var_func)(const char *) FAST_FUNC; /* function to be called when  */
1942                                         /* the variable gets set/unset */
1943 };
1944
1945 struct localvar {
1946         struct localvar *next;          /* next local variable in list */
1947         struct var *vp;                 /* the variable that was made local */
1948         int flags;                      /* saved flags */
1949         const char *text;               /* saved text */
1950 };
1951
1952 /* flags */
1953 #define VEXPORT         0x01    /* variable is exported */
1954 #define VREADONLY       0x02    /* variable cannot be modified */
1955 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1956 #define VTEXTFIXED      0x08    /* text is statically allocated */
1957 #define VSTACK          0x10    /* text is allocated on the stack */
1958 #define VUNSET          0x20    /* the variable is not set */
1959 #define VNOFUNC         0x40    /* don't call the callback function */
1960 #define VNOSET          0x80    /* do not set variable - just readonly test */
1961 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1962 #if ENABLE_ASH_RANDOM_SUPPORT
1963 # define VDYNAMIC       0x200   /* dynamic variable */
1964 #else
1965 # define VDYNAMIC       0
1966 #endif
1967
1968
1969 /* Need to be before varinit_data[] */
1970 #if ENABLE_LOCALE_SUPPORT
1971 static void FAST_FUNC
1972 change_lc_all(const char *value)
1973 {
1974         if (value && *value != '\0')
1975                 setlocale(LC_ALL, value);
1976 }
1977 static void FAST_FUNC
1978 change_lc_ctype(const char *value)
1979 {
1980         if (value && *value != '\0')
1981                 setlocale(LC_CTYPE, value);
1982 }
1983 #endif
1984 #if ENABLE_ASH_MAIL
1985 static void chkmail(void);
1986 static void changemail(const char *var_value) FAST_FUNC;
1987 #else
1988 # define chkmail()  ((void)0)
1989 #endif
1990 static void changepath(const char *) FAST_FUNC;
1991 #if ENABLE_ASH_RANDOM_SUPPORT
1992 static void change_random(const char *) FAST_FUNC;
1993 #endif
1994
1995 static const struct {
1996         int flags;
1997         const char *var_text;
1998         void (*var_func)(const char *) FAST_FUNC;
1999 } varinit_data[] = {
2000         /*
2001          * Note: VEXPORT would not work correctly here for NOFORK applets:
2002          * some environment strings may be constant.
2003          */
2004         { VSTRFIXED|VTEXTFIXED       , defifsvar   , NULL            },
2005 #if ENABLE_ASH_MAIL
2006         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL"      , changemail      },
2007         { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH"  , changemail      },
2008 #endif
2009         { VSTRFIXED|VTEXTFIXED       , bb_PATH_root_path, changepath },
2010         { VSTRFIXED|VTEXTFIXED       , "PS1=$ "    , NULL            },
2011         { VSTRFIXED|VTEXTFIXED       , "PS2=> "    , NULL            },
2012         { VSTRFIXED|VTEXTFIXED       , "PS4=+ "    , NULL            },
2013 #if ENABLE_ASH_GETOPTS
2014         { VSTRFIXED|VTEXTFIXED       , defoptindvar, getoptsreset    },
2015 #endif
2016 #if ENABLE_ASH_RANDOM_SUPPORT
2017         { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
2018 #endif
2019 #if ENABLE_LOCALE_SUPPORT
2020         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL"    , change_lc_all   },
2021         { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE"  , change_lc_ctype },
2022 #endif
2023 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
2024         { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE"  , NULL            },
2025 #endif
2026 };
2027
2028 struct redirtab;
2029
2030 struct globals_var {
2031         struct shparam shellparam;      /* $@ current positional parameters */
2032         struct redirtab *redirlist;
2033         int preverrout_fd;   /* save fd2 before print debug if xflag is set. */
2034         struct var *vartab[VTABSIZE];
2035         struct var varinit[ARRAY_SIZE(varinit_data)];
2036 };
2037 extern struct globals_var *const ash_ptr_to_globals_var;
2038 #define G_var (*ash_ptr_to_globals_var)
2039 #define shellparam    (G_var.shellparam   )
2040 //#define redirlist     (G_var.redirlist    )
2041 #define preverrout_fd (G_var.preverrout_fd)
2042 #define vartab        (G_var.vartab       )
2043 #define varinit       (G_var.varinit      )
2044 #define INIT_G_var() do { \
2045         unsigned i; \
2046         (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
2047         barrier(); \
2048         for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2049                 varinit[i].flags    = varinit_data[i].flags; \
2050                 varinit[i].var_text = varinit_data[i].var_text; \
2051                 varinit[i].var_func = varinit_data[i].var_func; \
2052         } \
2053 } while (0)
2054
2055 #define vifs      varinit[0]
2056 #if ENABLE_ASH_MAIL
2057 # define vmail    (&vifs)[1]
2058 # define vmpath   (&vmail)[1]
2059 # define vpath    (&vmpath)[1]
2060 #else
2061 # define vpath    (&vifs)[1]
2062 #endif
2063 #define vps1      (&vpath)[1]
2064 #define vps2      (&vps1)[1]
2065 #define vps4      (&vps2)[1]
2066 #if ENABLE_ASH_GETOPTS
2067 # define voptind  (&vps4)[1]
2068 # if ENABLE_ASH_RANDOM_SUPPORT
2069 #  define vrandom (&voptind)[1]
2070 # endif
2071 #else
2072 # if ENABLE_ASH_RANDOM_SUPPORT
2073 #  define vrandom (&vps4)[1]
2074 # endif
2075 #endif
2076
2077 /*
2078  * The following macros access the values of the above variables.
2079  * They have to skip over the name.  They return the null string
2080  * for unset variables.
2081  */
2082 #define ifsval()        (vifs.var_text + 4)
2083 #define ifsset()        ((vifs.flags & VUNSET) == 0)
2084 #if ENABLE_ASH_MAIL
2085 # define mailval()      (vmail.var_text + 5)
2086 # define mpathval()     (vmpath.var_text + 9)
2087 # define mpathset()     ((vmpath.flags & VUNSET) == 0)
2088 #endif
2089 #define pathval()       (vpath.var_text + 5)
2090 #define ps1val()        (vps1.var_text + 4)
2091 #define ps2val()        (vps2.var_text + 4)
2092 #define ps4val()        (vps4.var_text + 4)
2093 #if ENABLE_ASH_GETOPTS
2094 # define optindval()    (voptind.var_text + 7)
2095 #endif
2096
2097 #if ENABLE_ASH_GETOPTS
2098 static void FAST_FUNC
2099 getoptsreset(const char *value)
2100 {
2101         shellparam.optind = number(value) ?: 1;
2102         shellparam.optoff = -1;
2103 }
2104 #endif
2105
2106 /*
2107  * Compares two strings up to the first = or '\0'.  The first
2108  * string must be terminated by '='; the second may be terminated by
2109  * either '=' or '\0'.
2110  */
2111 static int
2112 varcmp(const char *p, const char *q)
2113 {
2114         int c, d;
2115
2116         while ((c = *p) == (d = *q)) {
2117                 if (c == '\0' || c == '=')
2118                         goto out;
2119                 p++;
2120                 q++;
2121         }
2122         if (c == '=')
2123                 c = '\0';
2124         if (d == '=')
2125                 d = '\0';
2126  out:
2127         return c - d;
2128 }
2129
2130 /*
2131  * Find the appropriate entry in the hash table from the name.
2132  */
2133 static struct var **
2134 hashvar(const char *p)
2135 {
2136         unsigned hashval;
2137
2138         hashval = ((unsigned char) *p) << 4;
2139         while (*p && *p != '=')
2140                 hashval += (unsigned char) *p++;
2141         return &vartab[hashval % VTABSIZE];
2142 }
2143
2144 static int
2145 vpcmp(const void *a, const void *b)
2146 {
2147         return varcmp(*(const char **)a, *(const char **)b);
2148 }
2149
2150 /*
2151  * This routine initializes the builtin variables.
2152  */
2153 static void
2154 initvar(void)
2155 {
2156         struct var *vp;
2157         struct var *end;
2158         struct var **vpp;
2159
2160         /*
2161          * PS1 depends on uid
2162          */
2163 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2164         vps1.var_text = "PS1=\\w \\$ ";
2165 #else
2166         if (!geteuid())
2167                 vps1.var_text = "PS1=# ";
2168 #endif
2169         vp = varinit;
2170         end = vp + ARRAY_SIZE(varinit);
2171         do {
2172                 vpp = hashvar(vp->var_text);
2173                 vp->next = *vpp;
2174                 *vpp = vp;
2175         } while (++vp < end);
2176 }
2177
2178 static struct var **
2179 findvar(struct var **vpp, const char *name)
2180 {
2181         for (; *vpp; vpp = &(*vpp)->next) {
2182                 if (varcmp((*vpp)->var_text, name) == 0) {
2183                         break;
2184                 }
2185         }
2186         return vpp;
2187 }
2188
2189 /*
2190  * Find the value of a variable.  Returns NULL if not set.
2191  */
2192 static const char* FAST_FUNC
2193 lookupvar(const char *name)
2194 {
2195         struct var *v;
2196
2197         v = *findvar(hashvar(name), name);
2198         if (v) {
2199 #if ENABLE_ASH_RANDOM_SUPPORT
2200         /*
2201          * Dynamic variables are implemented roughly the same way they are
2202          * in bash. Namely, they're "special" so long as they aren't unset.
2203          * As soon as they're unset, they're no longer dynamic, and dynamic
2204          * lookup will no longer happen at that point. -- PFM.
2205          */
2206                 if (v->flags & VDYNAMIC)
2207                         v->var_func(NULL);
2208 #endif
2209                 if (!(v->flags & VUNSET))
2210                         return var_end(v->var_text);
2211         }
2212         return NULL;
2213 }
2214
2215 #if ENABLE_UNICODE_SUPPORT
2216 static void
2217 reinit_unicode_for_ash(void)
2218 {
2219         /* Unicode support should be activated even if LANG is set
2220          * _during_ shell execution, not only if it was set when
2221          * shell was started. Therefore, re-check LANG every time:
2222          */
2223         if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
2224          || ENABLE_UNICODE_USING_LOCALE
2225         ) {
2226                 const char *s = lookupvar("LC_ALL");
2227                 if (!s) s = lookupvar("LC_CTYPE");
2228                 if (!s) s = lookupvar("LANG");
2229                 reinit_unicode(s);
2230         }
2231 }
2232 #else
2233 # define reinit_unicode_for_ash() ((void)0)
2234 #endif
2235
2236 /*
2237  * Search the environment of a builtin command.
2238  */
2239 static ALWAYS_INLINE const char *
2240 bltinlookup(const char *name)
2241 {
2242         return lookupvar(name);
2243 }
2244
2245 /*
2246  * Same as setvar except that the variable and value are passed in
2247  * the first argument as name=value.  Since the first argument will
2248  * be actually stored in the table, it should not be a string that
2249  * will go away.
2250  * Called with interrupts off.
2251  */
2252 static struct var *
2253 setvareq(char *s, int flags)
2254 {
2255         struct var *vp, **vpp;
2256
2257         vpp = hashvar(s);
2258         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2259         vpp = findvar(vpp, s);
2260         vp = *vpp;
2261         if (vp) {
2262                 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2263                         const char *n;
2264
2265                         if (flags & VNOSAVE)
2266                                 free(s);
2267                         n = vp->var_text;
2268                         exitstatus = 1;
2269                         ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2270                 }
2271
2272                 if (flags & VNOSET)
2273                         goto out;
2274
2275                 if (vp->var_func && !(flags & VNOFUNC))
2276                         vp->var_func(var_end(s));
2277
2278                 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2279                         free((char*)vp->var_text);
2280
2281                 if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) | (vp->flags & VSTRFIXED)) == VUNSET) {
2282                         *vpp = vp->next;
2283                         free(vp);
2284  out_free:
2285                         if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
2286                                 free(s);
2287                         goto out;
2288                 }
2289
2290                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2291         } else {
2292                 /* variable s is not found */
2293                 if (flags & VNOSET)
2294                         goto out;
2295                 if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
2296                         goto out_free;
2297                 vp = ckzalloc(sizeof(*vp));
2298                 vp->next = *vpp;
2299                 /*vp->func = NULL; - ckzalloc did it */
2300                 *vpp = vp;
2301         }
2302         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2303                 s = ckstrdup(s);
2304         vp->var_text = s;
2305         vp->flags = flags;
2306
2307  out:
2308         return vp;
2309 }
2310
2311 /*
2312  * Set the value of a variable.  The flags argument is ored with the
2313  * flags of the variable.  If val is NULL, the variable is unset.
2314  */
2315 static struct var *
2316 setvar(const char *name, const char *val, int flags)
2317 {
2318         const char *q;
2319         char *p;
2320         char *nameeq;
2321         size_t namelen;
2322         size_t vallen;
2323         struct var *vp;
2324
2325         q = endofname(name);
2326         p = strchrnul(q, '=');
2327         namelen = p - name;
2328         if (!namelen || p != q)
2329                 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2330         vallen = 0;
2331         if (val == NULL) {
2332                 flags |= VUNSET;
2333         } else {
2334                 vallen = strlen(val);
2335         }
2336
2337         INT_OFF;
2338         nameeq = ckmalloc(namelen + vallen + 2);
2339         p = mempcpy(nameeq, name, namelen);
2340         if (val) {
2341                 *p++ = '=';
2342                 p = mempcpy(p, val, vallen);
2343         }
2344         *p = '\0';
2345         vp = setvareq(nameeq, flags | VNOSAVE);
2346         INT_ON;
2347
2348         return vp;
2349 }
2350
2351 static void FAST_FUNC
2352 setvar0(const char *name, const char *val)
2353 {
2354         setvar(name, val, 0);
2355 }
2356
2357 /*
2358  * Unset the specified variable.
2359  */
2360 static void
2361 unsetvar(const char *s)
2362 {
2363         setvar(s, NULL, 0);
2364 }
2365
2366 /*
2367  * Process a linked list of variable assignments.
2368  */
2369 static void
2370 listsetvar(struct strlist *list_set_var, int flags)
2371 {
2372         struct strlist *lp = list_set_var;
2373
2374         if (!lp)
2375                 return;
2376         INT_OFF;
2377         do {
2378                 setvareq(lp->text, flags);
2379                 lp = lp->next;
2380         } while (lp);
2381         INT_ON;
2382 }
2383
2384 /*
2385  * Generate a list of variables satisfying the given conditions.
2386  */
2387 static char **
2388 listvars(int on, int off, char ***end)
2389 {
2390         struct var **vpp;
2391         struct var *vp;
2392         char **ep;
2393         int mask;
2394
2395         STARTSTACKSTR(ep);
2396         vpp = vartab;
2397         mask = on | off;
2398         do {
2399                 for (vp = *vpp; vp; vp = vp->next) {
2400                         if ((vp->flags & mask) == on) {
2401                                 if (ep == stackstrend())
2402                                         ep = growstackstr();
2403                                 *ep++ = (char*)vp->var_text;
2404                         }
2405                 }
2406         } while (++vpp < vartab + VTABSIZE);
2407         if (ep == stackstrend())
2408                 ep = growstackstr();
2409         if (end)
2410                 *end = ep;
2411         *ep++ = NULL;
2412         return grabstackstr(ep);
2413 }
2414
2415
2416 /* ============ Path search helper
2417  *
2418  * The variable path (passed by reference) should be set to the start
2419  * of the path before the first call; path_advance will update
2420  * this value as it proceeds.  Successive calls to path_advance will return
2421  * the possible path expansions in sequence.  If an option (indicated by
2422  * a percent sign) appears in the path entry then the global variable
2423  * pathopt will be set to point to it; otherwise pathopt will be set to
2424  * NULL.
2425  */
2426 static const char *pathopt;     /* set by path_advance */
2427
2428 static char *
2429 path_advance(const char **path, const char *name)
2430 {
2431         const char *p;
2432         char *q;
2433         const char *start;
2434         size_t len;
2435
2436         if (*path == NULL)
2437                 return NULL;
2438         start = *path;
2439         for (p = start; *p && *p != ':' && *p != '%'; p++)
2440                 continue;
2441         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
2442         while (stackblocksize() < len)
2443                 growstackblock();
2444         q = stackblock();
2445         if (p != start) {
2446                 q = mempcpy(q, start, p - start);
2447                 *q++ = '/';
2448         }
2449         strcpy(q, name);
2450         pathopt = NULL;
2451         if (*p == '%') {
2452                 pathopt = ++p;
2453                 while (*p && *p != ':')
2454                         p++;
2455         }
2456         if (*p == ':')
2457                 *path = p + 1;
2458         else
2459                 *path = NULL;
2460         return stalloc(len);
2461 }
2462
2463
2464 /* ============ Prompt */
2465
2466 static smallint doprompt;                   /* if set, prompt the user */
2467 static smallint needprompt;                 /* true if interactive and at start of line */
2468
2469 #if ENABLE_FEATURE_EDITING
2470 static line_input_t *line_input_state;
2471 static const char *cmdedit_prompt;
2472 static void
2473 putprompt(const char *s)
2474 {
2475         if (ENABLE_ASH_EXPAND_PRMT) {
2476                 free((char*)cmdedit_prompt);
2477                 cmdedit_prompt = ckstrdup(s);
2478                 return;
2479         }
2480         cmdedit_prompt = s;
2481 }
2482 #else
2483 static void
2484 putprompt(const char *s)
2485 {
2486         out2str(s);
2487 }
2488 #endif
2489
2490 /* expandstr() needs parsing machinery, so it is far away ahead... */
2491 static const char *expandstr(const char *ps);
2492
2493 static void
2494 setprompt_if(smallint do_set, int whichprompt)
2495 {
2496         const char *prompt;
2497         IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2498
2499         if (!do_set)
2500                 return;
2501
2502         needprompt = 0;
2503
2504         switch (whichprompt) {
2505         case 1:
2506                 prompt = ps1val();
2507                 break;
2508         case 2:
2509                 prompt = ps2val();
2510                 break;
2511         default:                        /* 0 */
2512                 prompt = nullstr;
2513         }
2514 #if ENABLE_ASH_EXPAND_PRMT
2515         pushstackmark(&smark, stackblocksize());
2516         putprompt(expandstr(prompt));
2517         popstackmark(&smark);
2518 #else
2519         putprompt(prompt);
2520 #endif
2521 }
2522
2523
2524 /* ============ The cd and pwd commands */
2525
2526 #define CD_PHYSICAL 1
2527 #define CD_PRINT 2
2528
2529 static int
2530 cdopt(void)
2531 {
2532         int flags = 0;
2533         int i, j;
2534
2535         j = 'L';
2536         while ((i = nextopt("LP")) != '\0') {
2537                 if (i != j) {
2538                         flags ^= CD_PHYSICAL;
2539                         j = i;
2540                 }
2541         }
2542
2543         return flags;
2544 }
2545
2546 /*
2547  * Update curdir (the name of the current directory) in response to a
2548  * cd command.
2549  */
2550 static const char *
2551 updatepwd(const char *dir)
2552 {
2553         char *new;
2554         char *p;
2555         char *cdcomppath;
2556         const char *lim;
2557
2558         cdcomppath = sstrdup(dir);
2559         STARTSTACKSTR(new);
2560         if (*dir != '/') {
2561                 if (curdir == nullstr)
2562                         return 0;
2563                 new = stack_putstr(curdir, new);
2564         }
2565         new = makestrspace(strlen(dir) + 2, new);
2566         lim = (char *)stackblock() + 1;
2567         if (*dir != '/') {
2568                 if (new[-1] != '/')
2569                         USTPUTC('/', new);
2570                 if (new > lim && *lim == '/')
2571                         lim++;
2572         } else {
2573                 USTPUTC('/', new);
2574                 cdcomppath++;
2575                 if (dir[1] == '/' && dir[2] != '/') {
2576                         USTPUTC('/', new);
2577                         cdcomppath++;
2578                         lim++;
2579                 }
2580         }
2581         p = strtok(cdcomppath, "/");
2582         while (p) {
2583                 switch (*p) {
2584                 case '.':
2585                         if (p[1] == '.' && p[2] == '\0') {
2586                                 while (new > lim) {
2587                                         STUNPUTC(new);
2588                                         if (new[-1] == '/')
2589                                                 break;
2590                                 }
2591                                 break;
2592                         }
2593                         if (p[1] == '\0')
2594                                 break;
2595                         /* fall through */
2596                 default:
2597                         new = stack_putstr(p, new);
2598                         USTPUTC('/', new);
2599                 }
2600                 p = strtok(NULL, "/");
2601         }
2602         if (new > lim)
2603                 STUNPUTC(new);
2604         *new = 0;
2605         return stackblock();
2606 }
2607
2608 /*
2609  * Find out what the current directory is. If we already know the current
2610  * directory, this routine returns immediately.
2611  */
2612 static char *
2613 getpwd(void)
2614 {
2615         char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2616         return dir ? dir : nullstr;
2617 }
2618
2619 static void
2620 setpwd(const char *val, int setold)
2621 {
2622         char *oldcur, *dir;
2623
2624         oldcur = dir = curdir;
2625
2626         if (setold) {
2627                 setvar("OLDPWD", oldcur, VEXPORT);
2628         }
2629         INT_OFF;
2630         if (physdir != nullstr) {
2631                 if (physdir != oldcur)
2632                         free(physdir);
2633                 physdir = nullstr;
2634         }
2635         if (oldcur == val || !val) {
2636                 char *s = getpwd();
2637                 physdir = s;
2638                 if (!val)
2639                         dir = s;
2640         } else
2641                 dir = ckstrdup(val);
2642         if (oldcur != dir && oldcur != nullstr) {
2643                 free(oldcur);
2644         }
2645         curdir = dir;
2646         INT_ON;
2647         setvar("PWD", dir, VEXPORT);
2648 }
2649
2650 static void hashcd(void);
2651
2652 /*
2653  * Actually do the chdir.  We also call hashcd to let other routines
2654  * know that the current directory has changed.
2655  */
2656 static int
2657 docd(const char *dest, int flags)
2658 {
2659         const char *dir = NULL;
2660         int err;
2661
2662         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2663
2664         INT_OFF;
2665         if (!(flags & CD_PHYSICAL)) {
2666                 dir = updatepwd(dest);
2667                 if (dir)
2668                         dest = dir;
2669         }
2670         err = chdir(dest);
2671         if (err)
2672                 goto out;
2673         setpwd(dir, 1);
2674         hashcd();
2675  out:
2676         INT_ON;
2677         return err;
2678 }
2679
2680 static int FAST_FUNC
2681 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2682 {
2683         const char *dest;
2684         const char *path;
2685         const char *p;
2686         char c;
2687         struct stat statb;
2688         int flags;
2689
2690         flags = cdopt();
2691         dest = *argptr;
2692         if (!dest)
2693                 dest = bltinlookup("HOME");
2694         else if (LONE_DASH(dest)) {
2695                 dest = bltinlookup("OLDPWD");
2696                 flags |= CD_PRINT;
2697         }
2698         if (!dest)
2699                 dest = nullstr;
2700         if (*dest == '/')
2701                 goto step6;
2702         if (*dest == '.') {
2703                 c = dest[1];
2704  dotdot:
2705                 switch (c) {
2706                 case '\0':
2707                 case '/':
2708                         goto step6;
2709                 case '.':
2710                         c = dest[2];
2711                         if (c != '.')
2712                                 goto dotdot;
2713                 }
2714         }
2715         if (!*dest)
2716                 dest = ".";
2717         path = bltinlookup("CDPATH");
2718         while (path) {
2719                 c = *path;
2720                 p = path_advance(&path, dest);
2721                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2722                         if (c && c != ':')
2723                                 flags |= CD_PRINT;
2724  docd:
2725                         if (!docd(p, flags))
2726                                 goto out;
2727                         goto err;
2728                 }
2729         }
2730
2731  step6:
2732         p = dest;
2733         goto docd;
2734
2735  err:
2736         ash_msg_and_raise_error("can't cd to %s", dest);
2737         /* NOTREACHED */
2738  out:
2739         if (flags & CD_PRINT)
2740                 out1fmt("%s\n", curdir);
2741         return 0;
2742 }
2743
2744 static int FAST_FUNC
2745 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2746 {
2747         int flags;
2748         const char *dir = curdir;
2749
2750         flags = cdopt();
2751         if (flags) {
2752                 if (physdir == nullstr)
2753                         setpwd(dir, 0);
2754                 dir = physdir;
2755         }
2756         out1fmt("%s\n", dir);
2757         return 0;
2758 }
2759
2760
2761 /* ============ ... */
2762
2763
2764 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2765
2766 /* Syntax classes */
2767 #define CWORD     0             /* character is nothing special */
2768 #define CNL       1             /* newline character */
2769 #define CBACK     2             /* a backslash character */
2770 #define CSQUOTE   3             /* single quote */
2771 #define CDQUOTE   4             /* double quote */
2772 #define CENDQUOTE 5             /* a terminating quote */
2773 #define CBQUOTE   6             /* backwards single quote */
2774 #define CVAR      7             /* a dollar sign */
2775 #define CENDVAR   8             /* a '}' character */
2776 #define CLP       9             /* a left paren in arithmetic */
2777 #define CRP      10             /* a right paren in arithmetic */
2778 #define CENDFILE 11             /* end of file */
2779 #define CCTL     12             /* like CWORD, except it must be escaped */
2780 #define CSPCL    13             /* these terminate a word */
2781 #define CIGN     14             /* character should be ignored */
2782
2783 #define PEOF     256
2784 #if ENABLE_ASH_ALIAS
2785 # define PEOA    257
2786 #endif
2787
2788 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2789
2790 #if ENABLE_FEATURE_SH_MATH
2791 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2792 #else
2793 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2794 #endif
2795 static const uint16_t S_I_T[] ALIGN2 = {
2796 #if ENABLE_ASH_ALIAS
2797         SIT_ITEM(CSPCL   , CIGN     , CIGN , CIGN   ),    /* 0, PEOA */
2798 #endif
2799         SIT_ITEM(CSPCL   , CWORD    , CWORD, CWORD  ),    /* 1, ' ' */
2800         SIT_ITEM(CNL     , CNL      , CNL  , CNL    ),    /* 2, \n */
2801         SIT_ITEM(CWORD   , CCTL     , CCTL , CWORD  ),    /* 3, !*-/:=?[]~ */
2802         SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD  ),    /* 4, '"' */
2803         SIT_ITEM(CVAR    , CVAR     , CWORD, CVAR   ),    /* 5, $ */
2804         SIT_ITEM(CSQUOTE , CWORD    , CENDQUOTE, CWORD),  /* 6, "'" */
2805         SIT_ITEM(CSPCL   , CWORD    , CWORD, CLP    ),    /* 7, ( */
2806         SIT_ITEM(CSPCL   , CWORD    , CWORD, CRP    ),    /* 8, ) */
2807         SIT_ITEM(CBACK   , CBACK    , CCTL , CBACK  ),    /* 9, \ */
2808         SIT_ITEM(CBQUOTE , CBQUOTE  , CWORD, CBQUOTE),    /* 10, ` */
2809         SIT_ITEM(CENDVAR , CENDVAR  , CWORD, CENDVAR),    /* 11, } */
2810 #if !USE_SIT_FUNCTION
2811         SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2812         SIT_ITEM(CWORD   , CWORD    , CWORD, CWORD  ),    /* 13, 0-9A-Za-z */
2813         SIT_ITEM(CCTL    , CCTL     , CCTL , CCTL   )     /* 14, CTLESC ... */
2814 #endif
2815 #undef SIT_ITEM
2816 };
2817 /* Constants below must match table above */
2818 enum {
2819 #if ENABLE_ASH_ALIAS
2820         CSPCL_CIGN_CIGN_CIGN               , /*  0 */
2821 #endif
2822         CSPCL_CWORD_CWORD_CWORD            , /*  1 */
2823         CNL_CNL_CNL_CNL                    , /*  2 */
2824         CWORD_CCTL_CCTL_CWORD              , /*  3 */
2825         CDQUOTE_CENDQUOTE_CWORD_CWORD      , /*  4 */
2826         CVAR_CVAR_CWORD_CVAR               , /*  5 */
2827         CSQUOTE_CWORD_CENDQUOTE_CWORD      , /*  6 */
2828         CSPCL_CWORD_CWORD_CLP              , /*  7 */
2829         CSPCL_CWORD_CWORD_CRP              , /*  8 */
2830         CBACK_CBACK_CCTL_CBACK             , /*  9 */
2831         CBQUOTE_CBQUOTE_CWORD_CBQUOTE      , /* 10 */
2832         CENDVAR_CENDVAR_CWORD_CENDVAR      , /* 11 */
2833         CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2834         CWORD_CWORD_CWORD_CWORD            , /* 13 */
2835         CCTL_CCTL_CCTL_CCTL                , /* 14 */
2836 };
2837
2838 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2839  * caller must ensure proper cast on it if c is *char_ptr!
2840  */
2841 /* Values for syntax param */
2842 #define BASESYNTAX 0    /* not in quotes */
2843 #define DQSYNTAX   1    /* in double quotes */
2844 #define SQSYNTAX   2    /* in single quotes */
2845 #define ARISYNTAX  3    /* in arithmetic */
2846 #define PSSYNTAX   4    /* prompt. never passed to SIT() */
2847
2848 #if USE_SIT_FUNCTION
2849
2850 static int
2851 SIT(int c, int syntax)
2852 {
2853         /* Used to also have '/' in this string: "\t\n !\"$&'()*-/:;<=>?[\\]`|}~" */
2854         static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-:;<=>?[\\]`|}~";
2855         /*
2856          * This causes '/' to be prepended with CTLESC in dquoted string,
2857          * making "./file"* treated incorrectly because we feed
2858          * ".\/file*" string to glob(), confusing it (see expandmeta func).
2859          * The "homegrown" glob implementation is okay with that,
2860          * but glibc one isn't. With '/' always treated as CWORD,
2861          * both work fine.
2862          */
2863 # if ENABLE_ASH_ALIAS
2864         static const uint8_t syntax_index_table[] ALIGN1 = {
2865                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
2866                 7, 8, 3, 3,/*3,*/3, 1, 1,       /* "()*-/:;<" */
2867                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
2868                 11, 3                           /* "}~" */
2869         };
2870 # else
2871         static const uint8_t syntax_index_table[] ALIGN1 = {
2872                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
2873                 6, 7, 2, 2,/*2,*/2, 0, 0,       /* "()*-/:;<" */
2874                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
2875                 10, 2                           /* "}~" */
2876         };
2877 # endif
2878         const char *s;
2879         int indx;
2880
2881         if (c == PEOF)
2882                 return CENDFILE;
2883 # if ENABLE_ASH_ALIAS
2884         if (c == PEOA)
2885                 indx = 0;
2886         else
2887 # endif
2888         {
2889                 /* Cast is purely for paranoia here,
2890                  * just in case someone passed signed char to us */
2891                 if ((unsigned char)c >= CTL_FIRST
2892                  && (unsigned char)c <= CTL_LAST
2893                 ) {
2894                         return CCTL;
2895                 }
2896                 s = strchrnul(spec_symbls, c);
2897                 if (*s == '\0')
2898                         return CWORD;
2899                 indx = syntax_index_table[s - spec_symbls];
2900         }
2901         return (S_I_T[indx] >> (syntax*4)) & 0xf;
2902 }
2903
2904 #else   /* !USE_SIT_FUNCTION */
2905
2906 static const uint8_t syntax_index_table[] ALIGN1 = {
2907         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2908         /*   0      */ CWORD_CWORD_CWORD_CWORD,
2909         /*   1      */ CWORD_CWORD_CWORD_CWORD,
2910         /*   2      */ CWORD_CWORD_CWORD_CWORD,
2911         /*   3      */ CWORD_CWORD_CWORD_CWORD,
2912         /*   4      */ CWORD_CWORD_CWORD_CWORD,
2913         /*   5      */ CWORD_CWORD_CWORD_CWORD,
2914         /*   6      */ CWORD_CWORD_CWORD_CWORD,
2915         /*   7      */ CWORD_CWORD_CWORD_CWORD,
2916         /*   8      */ CWORD_CWORD_CWORD_CWORD,
2917         /*   9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2918         /*  10 "\n" */ CNL_CNL_CNL_CNL,
2919         /*  11      */ CWORD_CWORD_CWORD_CWORD,
2920         /*  12      */ CWORD_CWORD_CWORD_CWORD,
2921         /*  13      */ CWORD_CWORD_CWORD_CWORD,
2922         /*  14      */ CWORD_CWORD_CWORD_CWORD,
2923         /*  15      */ CWORD_CWORD_CWORD_CWORD,
2924         /*  16      */ CWORD_CWORD_CWORD_CWORD,
2925         /*  17      */ CWORD_CWORD_CWORD_CWORD,
2926         /*  18      */ CWORD_CWORD_CWORD_CWORD,
2927         /*  19      */ CWORD_CWORD_CWORD_CWORD,
2928         /*  20      */ CWORD_CWORD_CWORD_CWORD,
2929         /*  21      */ CWORD_CWORD_CWORD_CWORD,
2930         /*  22      */ CWORD_CWORD_CWORD_CWORD,
2931         /*  23      */ CWORD_CWORD_CWORD_CWORD,
2932         /*  24      */ CWORD_CWORD_CWORD_CWORD,
2933         /*  25      */ CWORD_CWORD_CWORD_CWORD,
2934         /*  26      */ CWORD_CWORD_CWORD_CWORD,
2935         /*  27      */ CWORD_CWORD_CWORD_CWORD,
2936         /*  28      */ CWORD_CWORD_CWORD_CWORD,
2937         /*  29      */ CWORD_CWORD_CWORD_CWORD,
2938         /*  30      */ CWORD_CWORD_CWORD_CWORD,
2939         /*  31      */ CWORD_CWORD_CWORD_CWORD,
2940         /*  32  " " */ CSPCL_CWORD_CWORD_CWORD,
2941         /*  33  "!" */ CWORD_CCTL_CCTL_CWORD,
2942         /*  34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2943         /*  35  "#" */ CWORD_CWORD_CWORD_CWORD,
2944         /*  36  "$" */ CVAR_CVAR_CWORD_CVAR,
2945         /*  37  "%" */ CWORD_CWORD_CWORD_CWORD,
2946         /*  38  "&" */ CSPCL_CWORD_CWORD_CWORD,
2947         /*  39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2948         /*  40  "(" */ CSPCL_CWORD_CWORD_CLP,
2949         /*  41  ")" */ CSPCL_CWORD_CWORD_CRP,
2950         /*  42  "*" */ CWORD_CCTL_CCTL_CWORD,
2951         /*  43  "+" */ CWORD_CWORD_CWORD_CWORD,
2952         /*  44  "," */ CWORD_CWORD_CWORD_CWORD,
2953         /*  45  "-" */ CWORD_CCTL_CCTL_CWORD,
2954         /*  46  "." */ CWORD_CWORD_CWORD_CWORD,
2955 /* "/" was CWORD_CCTL_CCTL_CWORD, see comment in SIT() function why this is changed: */
2956         /*  47  "/" */ CWORD_CWORD_CWORD_CWORD,
2957         /*  48  "0" */ CWORD_CWORD_CWORD_CWORD,
2958         /*  49  "1" */ CWORD_CWORD_CWORD_CWORD,
2959         /*  50  "2" */ CWORD_CWORD_CWORD_CWORD,
2960         /*  51  "3" */ CWORD_CWORD_CWORD_CWORD,
2961         /*  52  "4" */ CWORD_CWORD_CWORD_CWORD,
2962         /*  53  "5" */ CWORD_CWORD_CWORD_CWORD,
2963         /*  54  "6" */ CWORD_CWORD_CWORD_CWORD,
2964         /*  55  "7" */ CWORD_CWORD_CWORD_CWORD,
2965         /*  56  "8" */ CWORD_CWORD_CWORD_CWORD,
2966         /*  57  "9" */ CWORD_CWORD_CWORD_CWORD,
2967         /*  58  ":" */ CWORD_CCTL_CCTL_CWORD,
2968         /*  59  ";" */ CSPCL_CWORD_CWORD_CWORD,
2969         /*  60  "<" */ CSPCL_CWORD_CWORD_CWORD,
2970         /*  61  "=" */ CWORD_CCTL_CCTL_CWORD,
2971         /*  62  ">" */ CSPCL_CWORD_CWORD_CWORD,
2972         /*  63  "?" */ CWORD_CCTL_CCTL_CWORD,
2973         /*  64  "@" */ CWORD_CWORD_CWORD_CWORD,
2974         /*  65  "A" */ CWORD_CWORD_CWORD_CWORD,
2975         /*  66  "B" */ CWORD_CWORD_CWORD_CWORD,
2976         /*  67  "C" */ CWORD_CWORD_CWORD_CWORD,
2977         /*  68  "D" */ CWORD_CWORD_CWORD_CWORD,
2978         /*  69  "E" */ CWORD_CWORD_CWORD_CWORD,
2979         /*  70  "F" */ CWORD_CWORD_CWORD_CWORD,
2980         /*  71  "G" */ CWORD_CWORD_CWORD_CWORD,
2981         /*  72  "H" */ CWORD_CWORD_CWORD_CWORD,
2982         /*  73  "I" */ CWORD_CWORD_CWORD_CWORD,
2983         /*  74  "J" */ CWORD_CWORD_CWORD_CWORD,
2984         /*  75  "K" */ CWORD_CWORD_CWORD_CWORD,
2985         /*  76  "L" */ CWORD_CWORD_CWORD_CWORD,
2986         /*  77  "M" */ CWORD_CWORD_CWORD_CWORD,
2987         /*  78  "N" */ CWORD_CWORD_CWORD_CWORD,
2988         /*  79  "O" */ CWORD_CWORD_CWORD_CWORD,
2989         /*  80  "P" */ CWORD_CWORD_CWORD_CWORD,
2990         /*  81  "Q" */ CWORD_CWORD_CWORD_CWORD,
2991         /*  82  "R" */ CWORD_CWORD_CWORD_CWORD,
2992         /*  83  "S" */ CWORD_CWORD_CWORD_CWORD,
2993         /*  84  "T" */ CWORD_CWORD_CWORD_CWORD,
2994         /*  85  "U" */ CWORD_CWORD_CWORD_CWORD,
2995         /*  86  "V" */ CWORD_CWORD_CWORD_CWORD,
2996         /*  87  "W" */ CWORD_CWORD_CWORD_CWORD,
2997         /*  88  "X" */ CWORD_CWORD_CWORD_CWORD,
2998         /*  89  "Y" */ CWORD_CWORD_CWORD_CWORD,
2999         /*  90  "Z" */ CWORD_CWORD_CWORD_CWORD,
3000         /*  91  "[" */ CWORD_CCTL_CCTL_CWORD,
3001         /*  92  "\" */ CBACK_CBACK_CCTL_CBACK,
3002         /*  93  "]" */ CWORD_CCTL_CCTL_CWORD,
3003         /*  94  "^" */ CWORD_CWORD_CWORD_CWORD,
3004         /*  95  "_" */ CWORD_CWORD_CWORD_CWORD,
3005         /*  96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
3006         /*  97  "a" */ CWORD_CWORD_CWORD_CWORD,
3007         /*  98  "b" */ CWORD_CWORD_CWORD_CWORD,
3008         /*  99  "c" */ CWORD_CWORD_CWORD_CWORD,
3009         /* 100  "d" */ CWORD_CWORD_CWORD_CWORD,
3010         /* 101  "e" */ CWORD_CWORD_CWORD_CWORD,
3011         /* 102  "f" */ CWORD_CWORD_CWORD_CWORD,
3012         /* 103  "g" */ CWORD_CWORD_CWORD_CWORD,
3013         /* 104  "h" */ CWORD_CWORD_CWORD_CWORD,
3014         /* 105  "i" */ CWORD_CWORD_CWORD_CWORD,
3015         /* 106  "j" */ CWORD_CWORD_CWORD_CWORD,
3016         /* 107  "k" */ CWORD_CWORD_CWORD_CWORD,
3017         /* 108  "l" */ CWORD_CWORD_CWORD_CWORD,
3018         /* 109  "m" */ CWORD_CWORD_CWORD_CWORD,
3019         /* 110  "n" */ CWORD_CWORD_CWORD_CWORD,
3020         /* 111  "o" */ CWORD_CWORD_CWORD_CWORD,
3021         /* 112  "p" */ CWORD_CWORD_CWORD_CWORD,
3022         /* 113  "q" */ CWORD_CWORD_CWORD_CWORD,
3023         /* 114  "r" */ CWORD_CWORD_CWORD_CWORD,
3024         /* 115  "s" */ CWORD_CWORD_CWORD_CWORD,
3025         /* 116  "t" */ CWORD_CWORD_CWORD_CWORD,
3026         /* 117  "u" */ CWORD_CWORD_CWORD_CWORD,
3027         /* 118  "v" */ CWORD_CWORD_CWORD_CWORD,
3028         /* 119  "w" */ CWORD_CWORD_CWORD_CWORD,
3029         /* 120  "x" */ CWORD_CWORD_CWORD_CWORD,
3030         /* 121  "y" */ CWORD_CWORD_CWORD_CWORD,
3031         /* 122  "z" */ CWORD_CWORD_CWORD_CWORD,
3032         /* 123  "{" */ CWORD_CWORD_CWORD_CWORD,
3033         /* 124  "|" */ CSPCL_CWORD_CWORD_CWORD,
3034         /* 125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
3035         /* 126  "~" */ CWORD_CCTL_CCTL_CWORD,
3036         /* 127  del */ CWORD_CWORD_CWORD_CWORD,
3037         /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
3038         /* 129 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
3039         /* 130 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
3040         /* 131 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
3041         /* 132 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
3042         /* 133 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
3043         /* 134 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
3044         /* 135 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
3045         /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
3046         /* 137      */ CWORD_CWORD_CWORD_CWORD,
3047         /* 138      */ CWORD_CWORD_CWORD_CWORD,
3048         /* 139      */ CWORD_CWORD_CWORD_CWORD,
3049         /* 140      */ CWORD_CWORD_CWORD_CWORD,
3050         /* 141      */ CWORD_CWORD_CWORD_CWORD,
3051         /* 142      */ CWORD_CWORD_CWORD_CWORD,
3052         /* 143      */ CWORD_CWORD_CWORD_CWORD,
3053         /* 144      */ CWORD_CWORD_CWORD_CWORD,
3054         /* 145      */ CWORD_CWORD_CWORD_CWORD,
3055         /* 146      */ CWORD_CWORD_CWORD_CWORD,
3056         /* 147      */ CWORD_CWORD_CWORD_CWORD,
3057         /* 148      */ CWORD_CWORD_CWORD_CWORD,
3058         /* 149      */ CWORD_CWORD_CWORD_CWORD,
3059         /* 150      */ CWORD_CWORD_CWORD_CWORD,
3060         /* 151      */ CWORD_CWORD_CWORD_CWORD,
3061         /* 152      */ CWORD_CWORD_CWORD_CWORD,
3062         /* 153      */ CWORD_CWORD_CWORD_CWORD,
3063         /* 154      */ CWORD_CWORD_CWORD_CWORD,
3064         /* 155      */ CWORD_CWORD_CWORD_CWORD,
3065         /* 156      */ CWORD_CWORD_CWORD_CWORD,
3066         /* 157      */ CWORD_CWORD_CWORD_CWORD,
3067         /* 158      */ CWORD_CWORD_CWORD_CWORD,
3068         /* 159      */ CWORD_CWORD_CWORD_CWORD,
3069         /* 160      */ CWORD_CWORD_CWORD_CWORD,
3070         /* 161      */ CWORD_CWORD_CWORD_CWORD,
3071         /* 162      */ CWORD_CWORD_CWORD_CWORD,
3072         /* 163      */ CWORD_CWORD_CWORD_CWORD,
3073         /* 164      */ CWORD_CWORD_CWORD_CWORD,
3074         /* 165      */ CWORD_CWORD_CWORD_CWORD,
3075         /* 166      */ CWORD_CWORD_CWORD_CWORD,
3076         /* 167      */ CWORD_CWORD_CWORD_CWORD,
3077         /* 168      */ CWORD_CWORD_CWORD_CWORD,
3078         /* 169      */ CWORD_CWORD_CWORD_CWORD,
3079         /* 170      */ CWORD_CWORD_CWORD_CWORD,
3080         /* 171      */ CWORD_CWORD_CWORD_CWORD,
3081         /* 172      */ CWORD_CWORD_CWORD_CWORD,
3082         /* 173      */ CWORD_CWORD_CWORD_CWORD,
3083         /* 174      */ CWORD_CWORD_CWORD_CWORD,
3084         /* 175      */ CWORD_CWORD_CWORD_CWORD,
3085         /* 176      */ CWORD_CWORD_CWORD_CWORD,
3086         /* 177      */ CWORD_CWORD_CWORD_CWORD,
3087         /* 178      */ CWORD_CWORD_CWORD_CWORD,
3088         /* 179      */ CWORD_CWORD_CWORD_CWORD,
3089         /* 180      */ CWORD_CWORD_CWORD_CWORD,
3090         /* 181      */ CWORD_CWORD_CWORD_CWORD,
3091         /* 182      */ CWORD_CWORD_CWORD_CWORD,
3092         /* 183      */ CWORD_CWORD_CWORD_CWORD,
3093         /* 184      */ CWORD_CWORD_CWORD_CWORD,
3094         /* 185      */ CWORD_CWORD_CWORD_CWORD,
3095         /* 186      */ CWORD_CWORD_CWORD_CWORD,
3096         /* 187      */ CWORD_CWORD_CWORD_CWORD,
3097         /* 188      */ CWORD_CWORD_CWORD_CWORD,
3098         /* 189      */ CWORD_CWORD_CWORD_CWORD,
3099         /* 190      */ CWORD_CWORD_CWORD_CWORD,
3100         /* 191      */ CWORD_CWORD_CWORD_CWORD,
3101         /* 192      */ CWORD_CWORD_CWORD_CWORD,
3102         /* 193      */ CWORD_CWORD_CWORD_CWORD,
3103         /* 194      */ CWORD_CWORD_CWORD_CWORD,
3104         /* 195      */ CWORD_CWORD_CWORD_CWORD,
3105         /* 196      */ CWORD_CWORD_CWORD_CWORD,
3106         /* 197      */ CWORD_CWORD_CWORD_CWORD,
3107         /* 198      */ CWORD_CWORD_CWORD_CWORD,
3108         /* 199      */ CWORD_CWORD_CWORD_CWORD,
3109         /* 200      */ CWORD_CWORD_CWORD_CWORD,
3110         /* 201      */ CWORD_CWORD_CWORD_CWORD,
3111         /* 202      */ CWORD_CWORD_CWORD_CWORD,
3112         /* 203      */ CWORD_CWORD_CWORD_CWORD,
3113         /* 204      */ CWORD_CWORD_CWORD_CWORD,
3114         /* 205      */ CWORD_CWORD_CWORD_CWORD,
3115         /* 206      */ CWORD_CWORD_CWORD_CWORD,
3116         /* 207      */ CWORD_CWORD_CWORD_CWORD,
3117         /* 208      */ CWORD_CWORD_CWORD_CWORD,
3118         /* 209      */ CWORD_CWORD_CWORD_CWORD,
3119         /* 210      */ CWORD_CWORD_CWORD_CWORD,
3120         /* 211      */ CWORD_CWORD_CWORD_CWORD,
3121         /* 212      */ CWORD_CWORD_CWORD_CWORD,
3122         /* 213      */ CWORD_CWORD_CWORD_CWORD,
3123         /* 214      */ CWORD_CWORD_CWORD_CWORD,
3124         /* 215      */ CWORD_CWORD_CWORD_CWORD,
3125         /* 216      */ CWORD_CWORD_CWORD_CWORD,
3126         /* 217      */ CWORD_CWORD_CWORD_CWORD,
3127         /* 218      */ CWORD_CWORD_CWORD_CWORD,
3128         /* 219      */ CWORD_CWORD_CWORD_CWORD,
3129         /* 220      */ CWORD_CWORD_CWORD_CWORD,
3130         /* 221      */ CWORD_CWORD_CWORD_CWORD,
3131         /* 222      */ CWORD_CWORD_CWORD_CWORD,
3132         /* 223      */ CWORD_CWORD_CWORD_CWORD,
3133         /* 224      */ CWORD_CWORD_CWORD_CWORD,
3134         /* 225      */ CWORD_CWORD_CWORD_CWORD,
3135         /* 226      */ CWORD_CWORD_CWORD_CWORD,
3136         /* 227      */ CWORD_CWORD_CWORD_CWORD,
3137         /* 228      */ CWORD_CWORD_CWORD_CWORD,
3138         /* 229      */ CWORD_CWORD_CWORD_CWORD,
3139         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3140         /* 231      */ CWORD_CWORD_CWORD_CWORD,
3141         /* 232      */ CWORD_CWORD_CWORD_CWORD,
3142         /* 233      */ CWORD_CWORD_CWORD_CWORD,
3143         /* 234      */ CWORD_CWORD_CWORD_CWORD,
3144         /* 235      */ CWORD_CWORD_CWORD_CWORD,
3145         /* 236      */ CWORD_CWORD_CWORD_CWORD,
3146         /* 237      */ CWORD_CWORD_CWORD_CWORD,
3147         /* 238      */ CWORD_CWORD_CWORD_CWORD,
3148         /* 239      */ CWORD_CWORD_CWORD_CWORD,
3149         /* 230      */ CWORD_CWORD_CWORD_CWORD,
3150         /* 241      */ CWORD_CWORD_CWORD_CWORD,
3151         /* 242      */ CWORD_CWORD_CWORD_CWORD,
3152         /* 243      */ CWORD_CWORD_CWORD_CWORD,
3153         /* 244      */ CWORD_CWORD_CWORD_CWORD,
3154         /* 245      */ CWORD_CWORD_CWORD_CWORD,
3155         /* 246      */ CWORD_CWORD_CWORD_CWORD,
3156         /* 247      */ CWORD_CWORD_CWORD_CWORD,
3157         /* 248      */ CWORD_CWORD_CWORD_CWORD,
3158         /* 249      */ CWORD_CWORD_CWORD_CWORD,
3159         /* 250      */ CWORD_CWORD_CWORD_CWORD,
3160         /* 251      */ CWORD_CWORD_CWORD_CWORD,
3161         /* 252      */ CWORD_CWORD_CWORD_CWORD,
3162         /* 253      */ CWORD_CWORD_CWORD_CWORD,
3163         /* 254      */ CWORD_CWORD_CWORD_CWORD,
3164         /* 255      */ CWORD_CWORD_CWORD_CWORD,
3165         /* PEOF */     CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3166 # if ENABLE_ASH_ALIAS
3167         /* PEOA */     CSPCL_CIGN_CIGN_CIGN,
3168 # endif
3169 };
3170
3171 #if 1
3172 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3173 #else /* debug version, caught one signed char bug */
3174 # define SIT(c, syntax) \
3175         ({ \
3176                 if ((c) < 0 || (c) > (PEOF + ENABLE_ASH_ALIAS)) \
3177                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3178                 if ((syntax) < 0 || (syntax) > (2 + ENABLE_FEATURE_SH_MATH)) \
3179                         bb_error_msg_and_die("line:%d c:%d", __LINE__, (c)); \
3180                 ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf); \
3181         })
3182 #endif
3183
3184 #endif  /* !USE_SIT_FUNCTION */
3185
3186
3187 /* ============ Alias handling */
3188
3189 #if ENABLE_ASH_ALIAS
3190
3191 #define ALIASINUSE 1
3192 #define ALIASDEAD  2
3193
3194 struct alias {
3195         struct alias *next;
3196         char *name;
3197         char *val;
3198         int flag;
3199 };
3200
3201
3202 static struct alias **atab; // [ATABSIZE];
3203 #define INIT_G_alias() do { \
3204         atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3205 } while (0)
3206
3207
3208 static struct alias **
3209 __lookupalias(const char *name)
3210 {
3211         unsigned int hashval;
3212         struct alias **app;
3213         const char *p;
3214         unsigned int ch;
3215
3216         p = name;
3217
3218         ch = (unsigned char)*p;
3219         hashval = ch << 4;
3220         while (ch) {
3221                 hashval += ch;
3222                 ch = (unsigned char)*++p;
3223         }
3224         app = &atab[hashval % ATABSIZE];
3225
3226         for (; *app; app = &(*app)->next) {
3227                 if (strcmp(name, (*app)->name) == 0) {
3228                         break;
3229                 }
3230         }
3231
3232         return app;
3233 }
3234
3235 static struct alias *
3236 lookupalias(const char *name, int check)
3237 {
3238         struct alias *ap = *__lookupalias(name);
3239
3240         if (check && ap && (ap->flag & ALIASINUSE))
3241                 return NULL;
3242         return ap;
3243 }
3244
3245 static struct alias *
3246 freealias(struct alias *ap)
3247 {
3248         struct alias *next;
3249
3250         if (ap->flag & ALIASINUSE) {
3251                 ap->flag |= ALIASDEAD;
3252                 return ap;
3253         }
3254
3255         next = ap->next;
3256         free(ap->name);
3257         free(ap->val);
3258         free(ap);
3259         return next;
3260 }
3261
3262 static void
3263 setalias(const char *name, const char *val)
3264 {
3265         struct alias *ap, **app;
3266
3267         app = __lookupalias(name);
3268         ap = *app;
3269         INT_OFF;
3270         if (ap) {
3271                 if (!(ap->flag & ALIASINUSE)) {
3272                         free(ap->val);
3273                 }
3274                 ap->val = ckstrdup(val);
3275                 ap->flag &= ~ALIASDEAD;
3276         } else {
3277                 /* not found */
3278                 ap = ckzalloc(sizeof(struct alias));
3279                 ap->name = ckstrdup(name);
3280                 ap->val = ckstrdup(val);
3281                 /*ap->flag = 0; - ckzalloc did it */
3282                 /*ap->next = NULL;*/
3283                 *app = ap;
3284         }
3285         INT_ON;
3286 }
3287
3288 static int
3289 unalias(const char *name)
3290 {
3291         struct alias **app;
3292
3293         app = __lookupalias(name);
3294
3295         if (*app) {
3296                 INT_OFF;
3297                 *app = freealias(*app);
3298                 INT_ON;
3299                 return 0;
3300         }
3301
3302         return 1;
3303 }
3304
3305 static void
3306 rmaliases(void)
3307 {
3308         struct alias *ap, **app;
3309         int i;
3310
3311         INT_OFF;
3312         for (i = 0; i < ATABSIZE; i++) {
3313                 app = &atab[i];
3314                 for (ap = *app; ap; ap = *app) {
3315                         *app = freealias(*app);
3316                         if (ap == *app) {
3317                                 app = &ap->next;
3318                         }
3319                 }
3320         }
3321         INT_ON;
3322 }
3323
3324 static void
3325 printalias(const struct alias *ap)
3326 {
3327         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3328 }
3329
3330 /*
3331  * TODO - sort output
3332  */
3333 static int FAST_FUNC
3334 aliascmd(int argc UNUSED_PARAM, char **argv)
3335 {
3336         char *n, *v;
3337         int ret = 0;
3338         struct alias *ap;
3339
3340         if (!argv[1]) {
3341                 int i;
3342
3343                 for (i = 0; i < ATABSIZE; i++) {
3344                         for (ap = atab[i]; ap; ap = ap->next) {
3345                                 printalias(ap);
3346                         }
3347                 }
3348                 return 0;
3349         }
3350         while ((n = *++argv) != NULL) {
3351                 v = strchr(n+1, '=');
3352                 if (v == NULL) { /* n+1: funny ksh stuff */
3353                         ap = *__lookupalias(n);
3354                         if (ap == NULL) {
3355                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
3356                                 ret = 1;
3357                         } else
3358                                 printalias(ap);
3359                 } else {
3360                         *v++ = '\0';
3361                         setalias(n, v);
3362                 }
3363         }
3364
3365         return ret;
3366 }
3367
3368 static int FAST_FUNC
3369 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3370 {
3371         int i;
3372
3373         while (nextopt("a") != '\0') {
3374                 rmaliases();
3375                 return 0;
3376         }
3377         for (i = 0; *argptr; argptr++) {
3378                 if (unalias(*argptr)) {
3379                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3380                         i = 1;
3381                 }
3382         }
3383
3384         return i;
3385 }
3386
3387 #endif /* ASH_ALIAS */
3388
3389
3390 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
3391 #define FORK_FG    0
3392 #define FORK_BG    1
3393 #define FORK_NOJOB 2
3394
3395 /* mode flags for showjob(s) */
3396 #define SHOW_ONLY_PGID  0x01    /* show only pgid (jobs -p) */
3397 #define SHOW_PIDS       0x02    /* show individual pids, not just one line per job */
3398 #define SHOW_CHANGED    0x04    /* only jobs whose state has changed */
3399 #define SHOW_STDERR     0x08    /* print to stderr (else stdout) */
3400
3401 /*
3402  * A job structure contains information about a job.  A job is either a
3403  * single process or a set of processes contained in a pipeline.  In the
3404  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3405  * array of pids.
3406  */
3407 struct procstat {
3408         pid_t   ps_pid;         /* process id */
3409         int     ps_status;      /* last process status from wait() */
3410         char    *ps_cmd;        /* text of command being run */
3411 };
3412
3413 struct job {
3414         struct procstat ps0;    /* status of process */
3415         struct procstat *ps;    /* status or processes when more than one */
3416 #if JOBS
3417         int stopstatus;         /* status of a stopped job */
3418 #endif
3419         unsigned nprocs;        /* number of processes */
3420
3421 #define JOBRUNNING      0       /* at least one proc running */
3422 #define JOBSTOPPED      1       /* all procs are stopped */
3423 #define JOBDONE         2       /* all procs are completed */
3424         unsigned
3425                 state: 8,
3426 #if JOBS
3427                 sigint: 1,      /* job was killed by SIGINT */
3428                 jobctl: 1,      /* job running under job control */
3429 #endif
3430                 waited: 1,      /* true if this entry has been waited for */
3431                 used: 1,        /* true if this entry is in used */
3432                 changed: 1;     /* true if status has changed */
3433         struct job *prev_job;   /* previous job */
3434 };
3435
3436 static struct job *makejob(/*union node *,*/ int);
3437 static int forkshell(struct job *, union node *, int);
3438 static int waitforjob(struct job *);
3439
3440 #if !JOBS
3441 enum { doing_jobctl = 0 };
3442 #define setjobctl(on) do {} while (0)
3443 #else
3444 static smallint doing_jobctl; //references:8
3445 static void setjobctl(int);
3446 #endif
3447
3448 /*
3449  * Ignore a signal.
3450  */
3451 static void
3452 ignoresig(int signo)
3453 {
3454         /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3455         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3456                 /* No, need to do it */
3457                 signal(signo, SIG_IGN);
3458         }
3459         sigmode[signo - 1] = S_HARD_IGN;
3460 }
3461
3462 /*
3463  * Only one usage site - in setsignal()
3464  */
3465 static void
3466 signal_handler(int signo)
3467 {
3468         if (signo == SIGCHLD) {
3469                 got_sigchld = 1;
3470                 if (!trap[SIGCHLD])
3471                         return;
3472         }
3473
3474         gotsig[signo - 1] = 1;
3475         pending_sig = signo;
3476
3477         if (signo == SIGINT && !trap[SIGINT]) {
3478                 if (!suppress_int) {
3479                         pending_sig = 0;
3480                         raise_interrupt(); /* does not return */
3481                 }
3482                 pending_int = 1;
3483         }
3484 }
3485
3486 /*
3487  * Set the signal handler for the specified signal.  The routine figures
3488  * out what it should be set to.
3489  */
3490 static void
3491 setsignal(int signo)
3492 {
3493         char *t;
3494         char cur_act, new_act;
3495         struct sigaction act;
3496
3497         t = trap[signo];
3498         new_act = S_DFL;
3499         if (t != NULL) { /* trap for this sig is set */
3500                 new_act = S_CATCH;
3501                 if (t[0] == '\0') /* trap is "": ignore this sig */
3502                         new_act = S_IGN;
3503         }
3504
3505         if (rootshell && new_act == S_DFL) {
3506                 switch (signo) {
3507                 case SIGINT:
3508                         if (iflag || minusc || sflag == 0)
3509                                 new_act = S_CATCH;
3510                         break;
3511                 case SIGQUIT:
3512 #if DEBUG
3513                         if (debug)
3514                                 break;
3515 #endif
3516                         /* man bash:
3517                          * "In all cases, bash ignores SIGQUIT. Non-builtin
3518                          * commands run by bash have signal handlers
3519                          * set to the values inherited by the shell
3520                          * from its parent". */
3521                         new_act = S_IGN;
3522                         break;
3523                 case SIGTERM:
3524                         if (iflag)
3525                                 new_act = S_IGN;
3526                         break;
3527 #if JOBS
3528                 case SIGTSTP:
3529                 case SIGTTOU:
3530                         if (mflag)
3531                                 new_act = S_IGN;
3532                         break;
3533 #endif
3534                 }
3535         }
3536 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3537 //whereas we have to restore it to what shell got on entry
3538 //from the parent. See comment above
3539
3540         if (signo == SIGCHLD)
3541                 new_act = S_CATCH;
3542
3543         t = &sigmode[signo - 1];
3544         cur_act = *t;
3545         if (cur_act == 0) {
3546                 /* current setting is not yet known */
3547                 if (sigaction(signo, NULL, &act)) {
3548                         /* pretend it worked; maybe we should give a warning,
3549                          * but other shells don't. We don't alter sigmode,
3550                          * so we retry every time.
3551                          * btw, in Linux it never fails. --vda */
3552                         return;
3553                 }
3554                 if (act.sa_handler == SIG_IGN) {
3555                         cur_act = S_HARD_IGN;
3556                         if (mflag
3557                          && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3558                         ) {
3559                                 cur_act = S_IGN;   /* don't hard ignore these */
3560                         }
3561                 }
3562         }
3563         if (cur_act == S_HARD_IGN || cur_act == new_act)
3564                 return;
3565
3566         act.sa_handler = SIG_DFL;
3567         switch (new_act) {
3568         case S_CATCH:
3569                 act.sa_handler = signal_handler;
3570                 break;
3571         case S_IGN:
3572                 act.sa_handler = SIG_IGN;
3573                 break;
3574         }
3575
3576         /* flags and mask matter only if !DFL and !IGN, but we do it
3577          * for all cases for more deterministic behavior:
3578          */
3579         act.sa_flags = 0;
3580         sigfillset(&act.sa_mask);
3581
3582         sigaction_set(signo, &act);
3583
3584         *t = new_act;
3585 }
3586
3587 /* mode flags for set_curjob */
3588 #define CUR_DELETE 2
3589 #define CUR_RUNNING 1
3590 #define CUR_STOPPED 0
3591
3592 #if JOBS
3593 /* pgrp of shell on invocation */
3594 static int initialpgrp; //references:2
3595 static int ttyfd = -1; //5
3596 #endif
3597 /* array of jobs */
3598 static struct job *jobtab; //5
3599 /* size of array */
3600 static unsigned njobs; //4
3601 /* current job */
3602 static struct job *curjob; //lots
3603 /* number of presumed living untracked jobs */
3604 static int jobless; //4
3605
3606 #if 0
3607 /* Bash has a feature: it restores termios after a successful wait for
3608  * a foreground job which had at least one stopped or sigkilled member.
3609  * The probable rationale is that SIGSTOP and SIGKILL can preclude task from
3610  * properly restoring tty state. Should we do this too?
3611  * A reproducer: ^Z an interactive python:
3612  *
3613  * # python
3614  * Python 2.7.12 (...)
3615  * >>> ^Z
3616  *      { python leaves tty in -icanon -echo state. We do survive that... }
3617  *  [1]+  Stopped                    python
3618  *      { ...however, next program (python #2) does not survive it well: }
3619  * # python
3620  * Python 2.7.12 (...)
3621  * >>> Traceback (most recent call last):
3622  *      { above, I typed "qwerty<CR>", but -echo state is still in effect }
3623  *   File "<stdin>", line 1, in <module>
3624  * NameError: name 'qwerty' is not defined
3625  *
3626  * The implementation below is modeled on bash code and seems to work.
3627  * However, I'm not sure we should do this. For one: what if I'd fg
3628  * the stopped python instead? It'll be confused by "restored" tty state.
3629  */
3630 static struct termios shell_tty_info;
3631 static void
3632 get_tty_state(void)
3633 {
3634         if (rootshell && ttyfd >= 0)
3635                 tcgetattr(ttyfd, &shell_tty_info);
3636 }
3637 static void
3638 set_tty_state(void)
3639 {
3640         /* if (rootshell) - caller ensures this */
3641         if (ttyfd >= 0)
3642                 tcsetattr(ttyfd, TCSADRAIN, &shell_tty_info);
3643 }
3644 static int
3645 job_signal_status(struct job *jp)
3646 {
3647         int status;
3648         unsigned i;
3649         struct procstat *ps = jp->ps;
3650         for (i = 0; i < jp->nprocs; i++) {
3651                 status = ps[i].ps_status;
3652                 if (WIFSIGNALED(status) || WIFSTOPPED(status))
3653                         return status;
3654         }
3655         return 0;
3656 }
3657 static void
3658 restore_tty_if_stopped_or_signaled(struct job *jp)
3659 {
3660 //TODO: check what happens if we come from waitforjob() in expbackq()
3661         if (rootshell) {
3662                 int s = job_signal_status(jp);
3663                 if (s) /* WIFSIGNALED(s) || WIFSTOPPED(s) */
3664                         set_tty_state();
3665         }
3666 }
3667 #else
3668 # define get_tty_state() ((void)0)
3669 # define restore_tty_if_stopped_or_signaled(jp) ((void)0)
3670 #endif
3671
3672 static void
3673 set_curjob(struct job *jp, unsigned mode)
3674 {
3675         struct job *jp1;
3676         struct job **jpp, **curp;
3677
3678         /* first remove from list */
3679         jpp = curp = &curjob;
3680         while (1) {
3681                 jp1 = *jpp;
3682                 if (jp1 == jp)
3683                         break;
3684                 jpp = &jp1->prev_job;
3685         }
3686         *jpp = jp1->prev_job;
3687
3688         /* Then re-insert in correct position */
3689         jpp = curp;
3690         switch (mode) {
3691         default:
3692 #if DEBUG
3693                 abort();
3694 #endif
3695         case CUR_DELETE:
3696                 /* job being deleted */
3697                 break;
3698         case CUR_RUNNING:
3699                 /* newly created job or backgrounded job,
3700                  * put after all stopped jobs.
3701                  */
3702                 while (1) {
3703                         jp1 = *jpp;
3704 #if JOBS
3705                         if (!jp1 || jp1->state != JOBSTOPPED)
3706 #endif
3707                                 break;
3708                         jpp = &jp1->prev_job;
3709                 }
3710                 /* FALLTHROUGH */
3711 #if JOBS
3712         case CUR_STOPPED:
3713 #endif
3714                 /* newly stopped job - becomes curjob */
3715                 jp->prev_job = *jpp;
3716                 *jpp = jp;
3717                 break;
3718         }
3719 }
3720
3721 #if JOBS || DEBUG
3722 static int
3723 jobno(const struct job *jp)
3724 {
3725         return jp - jobtab + 1;
3726 }
3727 #endif
3728
3729 /*
3730  * Convert a job name to a job structure.
3731  */
3732 #if !JOBS
3733 #define getjob(name, getctl) getjob(name)
3734 #endif
3735 static struct job *
3736 getjob(const char *name, int getctl)
3737 {
3738         struct job *jp;
3739         struct job *found;
3740         const char *err_msg = "%s: no such job";
3741         unsigned num;
3742         int c;
3743         const char *p;
3744         char *(*match)(const char *, const char *);
3745
3746         jp = curjob;
3747         p = name;
3748         if (!p)
3749                 goto currentjob;
3750
3751         if (*p != '%')
3752                 goto err;
3753
3754         c = *++p;
3755         if (!c)
3756                 goto currentjob;
3757
3758         if (!p[1]) {
3759                 if (c == '+' || c == '%') {
3760  currentjob:
3761                         err_msg = "No current job";
3762                         goto check;
3763                 }
3764                 if (c == '-') {
3765                         if (jp)
3766                                 jp = jp->prev_job;
3767                         err_msg = "No previous job";
3768  check:
3769                         if (!jp)
3770                                 goto err;
3771                         goto gotit;
3772                 }
3773         }
3774
3775         if (is_number(p)) {
3776                 num = atoi(p);
3777                 if (num > 0 && num <= njobs) {
3778                         jp = jobtab + num - 1;
3779                         if (jp->used)
3780                                 goto gotit;
3781                         goto err;
3782                 }
3783         }
3784
3785         match = prefix;
3786         if (*p == '?') {
3787                 match = strstr;
3788                 p++;
3789         }
3790
3791         found = NULL;
3792         while (jp) {
3793                 if (match(jp->ps[0].ps_cmd, p)) {
3794                         if (found)
3795                                 goto err;
3796                         found = jp;
3797                         err_msg = "%s: ambiguous";
3798                 }
3799                 jp = jp->prev_job;
3800         }
3801         if (!found)
3802                 goto err;
3803         jp = found;
3804
3805  gotit:
3806 #if JOBS
3807         err_msg = "job %s not created under job control";
3808         if (getctl && jp->jobctl == 0)
3809                 goto err;
3810 #endif
3811         return jp;
3812  err:
3813         ash_msg_and_raise_error(err_msg, name);
3814 }
3815
3816 /*
3817  * Mark a job structure as unused.
3818  */
3819 static void
3820 freejob(struct job *jp)
3821 {
3822         struct procstat *ps;
3823         int i;
3824
3825         INT_OFF;
3826         for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3827                 if (ps->ps_cmd != nullstr)
3828                         free(ps->ps_cmd);
3829         }
3830         if (jp->ps != &jp->ps0)
3831                 free(jp->ps);
3832         jp->used = 0;
3833         set_curjob(jp, CUR_DELETE);
3834         INT_ON;
3835 }
3836
3837 #if JOBS
3838 static void
3839 xtcsetpgrp(int fd, pid_t pgrp)
3840 {
3841         if (tcsetpgrp(fd, pgrp))
3842                 ash_msg_and_raise_perror("can't set tty process group");
3843 }
3844
3845 /*
3846  * Turn job control on and off.
3847  *
3848  * Note:  This code assumes that the third arg to ioctl is a character
3849  * pointer, which is true on Berkeley systems but not System V.  Since
3850  * System V doesn't have job control yet, this isn't a problem now.
3851  *
3852  * Called with interrupts off.
3853  */
3854 static void
3855 setjobctl(int on)
3856 {
3857         int fd;
3858         int pgrp;
3859
3860         if (on == doing_jobctl || rootshell == 0)
3861                 return;
3862         if (on) {
3863                 int ofd;
3864                 ofd = fd = open(_PATH_TTY, O_RDWR);
3865                 if (fd < 0) {
3866         /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3867          * That sometimes helps to acquire controlling tty.
3868          * Obviously, a workaround for bugs when someone
3869          * failed to provide a controlling tty to bash! :) */
3870                         fd = 2;
3871                         while (!isatty(fd))
3872                                 if (--fd < 0)
3873                                         goto out;
3874                 }
3875                 /* fd is a tty at this point */
3876                 fd = fcntl(fd, F_DUPFD, 10);
3877                 if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
3878                         close(ofd);
3879                 if (fd < 0)
3880                         goto out; /* F_DUPFD failed */
3881                 close_on_exec_on(fd);
3882                 while (1) { /* while we are in the background */
3883                         pgrp = tcgetpgrp(fd);
3884                         if (pgrp < 0) {
3885  out:
3886                                 ash_msg("can't access tty; job control turned off");
3887                                 mflag = on = 0;
3888                                 goto close;
3889                         }
3890                         if (pgrp == getpgrp())
3891                                 break;
3892                         killpg(0, SIGTTIN);
3893                 }
3894                 initialpgrp = pgrp;
3895
3896                 setsignal(SIGTSTP);
3897                 setsignal(SIGTTOU);
3898                 setsignal(SIGTTIN);
3899                 pgrp = rootpid;
3900                 setpgid(0, pgrp);
3901                 xtcsetpgrp(fd, pgrp);
3902         } else {
3903                 /* turning job control off */
3904                 fd = ttyfd;
3905                 pgrp = initialpgrp;
3906                 /* was xtcsetpgrp, but this can make exiting ash
3907                  * loop forever if pty is already deleted */
3908                 tcsetpgrp(fd, pgrp);
3909                 setpgid(0, pgrp);
3910                 setsignal(SIGTSTP);
3911                 setsignal(SIGTTOU);
3912                 setsignal(SIGTTIN);
3913  close:
3914                 if (fd >= 0)
3915                         close(fd);
3916                 fd = -1;
3917         }
3918         ttyfd = fd;
3919         doing_jobctl = on;
3920 }
3921
3922 static int FAST_FUNC
3923 killcmd(int argc, char **argv)
3924 {
3925         if (argv[1] && strcmp(argv[1], "-l") != 0) {
3926                 int i = 1;
3927                 do {
3928                         if (argv[i][0] == '%') {
3929                                 /*
3930                                  * "kill %N" - job kill
3931                                  * Converting to pgrp / pid kill
3932                                  */
3933                                 struct job *jp;
3934                                 char *dst;
3935                                 int j, n;
3936
3937                                 jp = getjob(argv[i], 0);
3938                                 /*
3939                                  * In jobs started under job control, we signal
3940                                  * entire process group by kill -PGRP_ID.
3941                                  * This happens, f.e., in interactive shell.
3942                                  *
3943                                  * Otherwise, we signal each child via
3944                                  * kill PID1 PID2 PID3.
3945                                  * Testcases:
3946                                  * sh -c 'sleep 1|sleep 1 & kill %1'
3947                                  * sh -c 'true|sleep 2 & sleep 1; kill %1'
3948                                  * sh -c 'true|sleep 1 & sleep 2; kill %1'
3949                                  */
3950                                 n = jp->nprocs; /* can't be 0 (I hope) */
3951                                 if (jp->jobctl)
3952                                         n = 1;
3953                                 dst = alloca(n * sizeof(int)*4);
3954                                 argv[i] = dst;
3955                                 for (j = 0; j < n; j++) {
3956                                         struct procstat *ps = &jp->ps[j];
3957                                         /* Skip non-running and not-stopped members
3958                                          * (i.e. dead members) of the job
3959                                          */
3960                                         if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3961                                                 continue;
3962                                         /*
3963                                          * kill_main has matching code to expect
3964                                          * leading space. Needed to not confuse
3965                                          * negative pids with "kill -SIGNAL_NO" syntax
3966                                          */
3967                                         dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3968                                 }
3969                                 *dst = '\0';
3970                         }
3971                 } while (argv[++i]);
3972         }
3973         return kill_main(argc, argv);
3974 }
3975
3976 static void
3977 showpipe(struct job *jp /*, FILE *out*/)
3978 {
3979         struct procstat *ps;
3980         struct procstat *psend;
3981
3982         psend = jp->ps + jp->nprocs;
3983         for (ps = jp->ps + 1; ps < psend; ps++)
3984                 printf(" | %s", ps->ps_cmd);
3985         newline_and_flush(stdout);
3986         flush_stdout_stderr();
3987 }
3988
3989
3990 static int
3991 restartjob(struct job *jp, int mode)
3992 {
3993         struct procstat *ps;
3994         int i;
3995         int status;
3996         pid_t pgid;
3997
3998         INT_OFF;
3999         if (jp->state == JOBDONE)
4000                 goto out;
4001         jp->state = JOBRUNNING;
4002         pgid = jp->ps[0].ps_pid;
4003         if (mode == FORK_FG) {
4004                 get_tty_state();
4005                 xtcsetpgrp(ttyfd, pgid);
4006         }
4007         killpg(pgid, SIGCONT);
4008         ps = jp->ps;
4009         i = jp->nprocs;
4010         do {
4011                 if (WIFSTOPPED(ps->ps_status)) {
4012                         ps->ps_status = -1;
4013                 }
4014                 ps++;
4015         } while (--i);
4016  out:
4017         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
4018         INT_ON;
4019         return status;
4020 }
4021
4022 static int FAST_FUNC
4023 fg_bgcmd(int argc UNUSED_PARAM, char **argv)
4024 {
4025         struct job *jp;
4026         int mode;
4027         int retval;
4028
4029         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
4030         nextopt(nullstr);
4031         argv = argptr;
4032         do {
4033                 jp = getjob(*argv, 1);
4034                 if (mode == FORK_BG) {
4035                         set_curjob(jp, CUR_RUNNING);
4036                         printf("[%d] ", jobno(jp));
4037                 }
4038                 out1str(jp->ps[0].ps_cmd);
4039                 showpipe(jp /*, stdout*/);
4040                 retval = restartjob(jp, mode);
4041         } while (*argv && *++argv);
4042         return retval;
4043 }
4044 #endif
4045
4046 static int
4047 sprint_status48(char *s, int status, int sigonly)
4048 {
4049         int col;
4050         int st;
4051
4052         col = 0;
4053         if (!WIFEXITED(status)) {
4054 #if JOBS
4055                 if (WIFSTOPPED(status))
4056                         st = WSTOPSIG(status);
4057                 else
4058 #endif
4059                         st = WTERMSIG(status);
4060                 if (sigonly) {
4061                         if (st == SIGINT || st == SIGPIPE)
4062                                 goto out;
4063 #if JOBS
4064                         if (WIFSTOPPED(status))
4065                                 goto out;
4066 #endif
4067                 }
4068                 st &= 0x7f;
4069 //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
4070                 col = fmtstr(s, 32, strsignal(st));
4071                 if (WCOREDUMP(status)) {
4072                         strcpy(s + col, " (core dumped)");
4073                         col += sizeof(" (core dumped)")-1;
4074                 }
4075         } else if (!sigonly) {
4076                 st = WEXITSTATUS(status);
4077                 col = fmtstr(s, 16, (st ? "Done(%d)" : "Done"), st);
4078         }
4079  out:
4080         return col;
4081 }
4082
4083 static int
4084 wait_block_or_sig(int *status)
4085 {
4086         int pid;
4087
4088         do {
4089                 sigset_t mask;
4090
4091                 /* Poll all children for changes in their state */
4092                 got_sigchld = 0;
4093                 /* if job control is active, accept stopped processes too */
4094                 pid = waitpid(-1, status, doing_jobctl ? (WNOHANG|WUNTRACED) : WNOHANG);
4095                 if (pid != 0)
4096                         break; /* Error (e.g. EINTR, ECHILD) or pid */
4097
4098                 /* Children exist, but none are ready. Sleep until interesting signal */
4099 #if 1
4100                 sigfillset(&mask);
4101                 sigprocmask(SIG_SETMASK, &mask, &mask);
4102                 while (!got_sigchld && !pending_sig)
4103                         sigsuspend(&mask);
4104                 sigprocmask(SIG_SETMASK, &mask, NULL);
4105 #else /* unsafe: a signal can set pending_sig after check, but before pause() */
4106                 while (!got_sigchld && !pending_sig)
4107                         pause();
4108 #endif
4109
4110                 /* If it was SIGCHLD, poll children again */
4111         } while (got_sigchld);
4112
4113         return pid;
4114 }
4115
4116 #define DOWAIT_NONBLOCK 0
4117 #define DOWAIT_BLOCK    1
4118 #define DOWAIT_BLOCK_OR_SIG 2
4119
4120 static int
4121 dowait(int block, struct job *job)
4122 {
4123         int pid;
4124         int status;
4125         struct job *jp;
4126         struct job *thisjob = NULL;
4127
4128         TRACE(("dowait(0x%x) called\n", block));
4129
4130         /* It's wrong to call waitpid() outside of INT_OFF region:
4131          * signal can arrive just after syscall return and handler can
4132          * longjmp away, losing stop/exit notification processing.
4133          * Thus, for "jobs" builtin, and for waiting for a fg job,
4134          * we call waitpid() (blocking or non-blocking) inside INT_OFF.
4135          *
4136          * However, for "wait" builtin it is wrong to simply call waitpid()
4137          * in INT_OFF region: "wait" needs to wait for any running job
4138          * to change state, but should exit on any trap too.
4139          * In INT_OFF region, a signal just before syscall entry can set
4140          * pending_sig variables, but we can't check them, and we would
4141          * either enter a sleeping waitpid() (BUG), or need to busy-loop.
4142          *
4143          * Because of this, we run inside INT_OFF, but use a special routine
4144          * which combines waitpid() and sigsuspend().
4145          * This is the reason why we need to have a handler for SIGCHLD:
4146          * SIG_DFL handler does not wake sigsuspend().
4147          */
4148         INT_OFF;
4149         if (block == DOWAIT_BLOCK_OR_SIG) {
4150                 pid = wait_block_or_sig(&status);
4151         } else {
4152                 int wait_flags = 0;
4153                 if (block == DOWAIT_NONBLOCK)
4154                         wait_flags = WNOHANG;
4155                 /* if job control is active, accept stopped processes too */
4156                 if (doing_jobctl)
4157                         wait_flags |= WUNTRACED;
4158                 /* NB: _not_ safe_waitpid, we need to detect EINTR */
4159                 pid = waitpid(-1, &status, wait_flags);
4160         }
4161         TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
4162                                 pid, status, errno, strerror(errno)));
4163         if (pid <= 0)
4164                 goto out;
4165
4166         thisjob = NULL;
4167         for (jp = curjob; jp; jp = jp->prev_job) {
4168                 int jobstate;
4169                 struct procstat *ps;
4170                 struct procstat *psend;
4171                 if (jp->state == JOBDONE)
4172                         continue;
4173                 jobstate = JOBDONE;
4174                 ps = jp->ps;
4175                 psend = ps + jp->nprocs;
4176                 do {
4177                         if (ps->ps_pid == pid) {
4178                                 TRACE(("Job %d: changing status of proc %d "
4179                                         "from 0x%x to 0x%x\n",
4180                                         jobno(jp), pid, ps->ps_status, status));
4181                                 ps->ps_status = status;
4182                                 thisjob = jp;
4183                         }
4184                         if (ps->ps_status == -1)
4185                                 jobstate = JOBRUNNING;
4186 #if JOBS
4187                         if (jobstate == JOBRUNNING)
4188                                 continue;
4189                         if (WIFSTOPPED(ps->ps_status)) {
4190                                 jp->stopstatus = ps->ps_status;
4191                                 jobstate = JOBSTOPPED;
4192                         }
4193 #endif
4194                 } while (++ps < psend);
4195                 if (!thisjob)
4196                         continue;
4197
4198                 /* Found the job where one of its processes changed its state.
4199                  * Is there at least one live and running process in this job? */
4200                 if (jobstate != JOBRUNNING) {
4201                         /* No. All live processes in the job are stopped
4202                          * (JOBSTOPPED) or there are no live processes (JOBDONE)
4203                          */
4204                         thisjob->changed = 1;
4205                         if (thisjob->state != jobstate) {
4206                                 TRACE(("Job %d: changing state from %d to %d\n",
4207                                         jobno(thisjob), thisjob->state, jobstate));
4208                                 thisjob->state = jobstate;
4209 #if JOBS
4210                                 if (jobstate == JOBSTOPPED)
4211                                         set_curjob(thisjob, CUR_STOPPED);
4212 #endif
4213                         }
4214                 }
4215                 goto out;
4216         }
4217         /* The process wasn't found in job list */
4218 #if JOBS
4219         if (!WIFSTOPPED(status))
4220                 jobless--;
4221 #endif
4222  out:
4223         INT_ON;
4224
4225         if (thisjob && thisjob == job) {
4226                 char s[48 + 1];
4227                 int len;
4228
4229                 len = sprint_status48(s, status, 1);
4230                 if (len) {
4231                         s[len] = '\n';
4232                         s[len + 1] = '\0';
4233                         out2str(s);
4234                 }
4235         }
4236         return pid;
4237 }
4238
4239 #if JOBS
4240 static void
4241 showjob(struct job *jp, int mode)
4242 {
4243         struct procstat *ps;
4244         struct procstat *psend;
4245         int col;
4246         int indent_col;
4247         char s[16 + 16 + 48];
4248         FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
4249
4250         ps = jp->ps;
4251
4252         if (mode & SHOW_ONLY_PGID) { /* jobs -p */
4253                 /* just output process (group) id of pipeline */
4254                 fprintf(out, "%d\n", ps->ps_pid);
4255                 return;
4256         }
4257
4258         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
4259         indent_col = col;
4260
4261         if (jp == curjob)
4262                 s[col - 3] = '+';
4263         else if (curjob && jp == curjob->prev_job)
4264                 s[col - 3] = '-';
4265
4266         if (mode & SHOW_PIDS)
4267                 col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
4268
4269         psend = ps + jp->nprocs;
4270
4271         if (jp->state == JOBRUNNING) {
4272                 strcpy(s + col, "Running");
4273                 col += sizeof("Running") - 1;
4274         } else {
4275                 int status = psend[-1].ps_status;
4276                 if (jp->state == JOBSTOPPED)
4277                         status = jp->stopstatus;
4278                 col += sprint_status48(s + col, status, 0);
4279         }
4280         /* By now, "[JOBID]*  [maybe PID] STATUS" is printed */
4281
4282         /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
4283          * or prints several "PID             | <cmdN>" lines,
4284          * depending on SHOW_PIDS bit.
4285          * We do not print status of individual processes
4286          * between PID and <cmdN>. bash does it, but not very well:
4287          * first line shows overall job status, not process status,
4288          * making it impossible to know 1st process status.
4289          */
4290         goto start;
4291         do {
4292                 /* for each process */
4293                 s[0] = '\0';
4294                 col = 33;
4295                 if (mode & SHOW_PIDS)
4296                         col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
4297  start:
4298                 fprintf(out, "%s%*c%s%s",
4299                                 s,
4300                                 33 - col >= 0 ? 33 - col : 0, ' ',
4301                                 ps == jp->ps ? "" : "| ",
4302                                 ps->ps_cmd
4303                 );
4304         } while (++ps != psend);
4305         newline_and_flush(out);
4306
4307         jp->changed = 0;
4308
4309         if (jp->state == JOBDONE) {
4310                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
4311                 freejob(jp);
4312         }
4313 }
4314
4315 /*
4316  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
4317  * statuses have changed since the last call to showjobs.
4318  */
4319 static void
4320 showjobs(int mode)
4321 {
4322         struct job *jp;
4323
4324         TRACE(("showjobs(0x%x) called\n", mode));
4325
4326         /* Handle all finished jobs */
4327         while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
4328                 continue;
4329
4330         for (jp = curjob; jp; jp = jp->prev_job) {
4331                 if (!(mode & SHOW_CHANGED) || jp->changed) {
4332                         showjob(jp, mode);
4333                 }
4334         }
4335 }
4336
4337 static int FAST_FUNC
4338 jobscmd(int argc UNUSED_PARAM, char **argv)
4339 {
4340         int mode, m;
4341
4342         mode = 0;
4343         while ((m = nextopt("lp")) != '\0') {
4344                 if (m == 'l')
4345                         mode |= SHOW_PIDS;
4346                 else
4347                         mode |= SHOW_ONLY_PGID;
4348         }
4349
4350         argv = argptr;
4351         if (*argv) {
4352                 do
4353                         showjob(getjob(*argv, 0), mode);
4354                 while (*++argv);
4355         } else {
4356                 showjobs(mode);
4357         }
4358
4359         return 0;
4360 }
4361 #endif /* JOBS */
4362
4363 /* Called only on finished or stopped jobs (no members are running) */
4364 static int
4365 getstatus(struct job *job)
4366 {
4367         int status;
4368         int retval;
4369         struct procstat *ps;
4370
4371         /* Fetch last member's status */
4372         ps = job->ps + job->nprocs - 1;
4373         status = ps->ps_status;
4374         if (pipefail) {
4375                 /* "set -o pipefail" mode: use last _nonzero_ status */
4376                 while (status == 0 && --ps >= job->ps)
4377                         status = ps->ps_status;
4378         }
4379
4380         retval = WEXITSTATUS(status);
4381         if (!WIFEXITED(status)) {
4382 #if JOBS
4383                 retval = WSTOPSIG(status);
4384                 if (!WIFSTOPPED(status))
4385 #endif
4386                 {
4387                         /* XXX: limits number of signals */
4388                         retval = WTERMSIG(status);
4389 #if JOBS
4390                         if (retval == SIGINT)
4391                                 job->sigint = 1;
4392 #endif
4393                 }
4394                 retval += 128;
4395         }
4396         TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
4397                 jobno(job), job->nprocs, status, retval));
4398         return retval;
4399 }
4400
4401 static int FAST_FUNC
4402 waitcmd(int argc UNUSED_PARAM, char **argv)
4403 {
4404         struct job *job;
4405         int retval;
4406         struct job *jp;
4407
4408         nextopt(nullstr);
4409         retval = 0;
4410
4411         argv = argptr;
4412         if (!*argv) {
4413                 /* wait for all jobs */
4414                 for (;;) {
4415                         jp = curjob;
4416                         while (1) {
4417                                 if (!jp) /* no running procs */
4418                                         goto ret;
4419                                 if (jp->state == JOBRUNNING)
4420                                         break;
4421                                 jp->waited = 1;
4422                                 jp = jp->prev_job;
4423                         }
4424         /* man bash:
4425          * "When bash is waiting for an asynchronous command via
4426          * the wait builtin, the reception of a signal for which a trap
4427          * has been set will cause the wait builtin to return immediately
4428          * with an exit status greater than 128, immediately after which
4429          * the trap is executed."
4430          */
4431                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4432         /* if child sends us a signal *and immediately exits*,
4433          * dowait() returns pid > 0. Check this case,
4434          * not "if (dowait() < 0)"!
4435          */
4436                         if (pending_sig)
4437                                 goto sigout;
4438                 }
4439         }
4440
4441         retval = 127;
4442         do {
4443                 if (**argv != '%') {
4444                         pid_t pid = number(*argv);
4445                         job = curjob;
4446                         while (1) {
4447                                 if (!job)
4448                                         goto repeat;
4449                                 if (job->ps[job->nprocs - 1].ps_pid == pid)
4450                                         break;
4451                                 job = job->prev_job;
4452                         }
4453                 } else {
4454                         job = getjob(*argv, 0);
4455                 }
4456                 /* loop until process terminated or stopped */
4457                 while (job->state == JOBRUNNING) {
4458                         dowait(DOWAIT_BLOCK_OR_SIG, NULL);
4459                         if (pending_sig)
4460                                 goto sigout;
4461                 }
4462                 job->waited = 1;
4463                 retval = getstatus(job);
4464  repeat: ;
4465         } while (*++argv);
4466
4467  ret:
4468         return retval;
4469  sigout:
4470         retval = 128 + pending_sig;
4471         return retval;
4472 }
4473
4474 static struct job *
4475 growjobtab(void)
4476 {
4477         size_t len;
4478         ptrdiff_t offset;
4479         struct job *jp, *jq;
4480
4481         len = njobs * sizeof(*jp);
4482         jq = jobtab;
4483         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
4484
4485         offset = (char *)jp - (char *)jq;
4486         if (offset) {
4487                 /* Relocate pointers */
4488                 size_t l = len;
4489
4490                 jq = (struct job *)((char *)jq + l);
4491                 while (l) {
4492                         l -= sizeof(*jp);
4493                         jq--;
4494 #define joff(p) ((struct job *)((char *)(p) + l))
4495 #define jmove(p) (p) = (void *)((char *)(p) + offset)
4496                         if (joff(jp)->ps == &jq->ps0)
4497                                 jmove(joff(jp)->ps);
4498                         if (joff(jp)->prev_job)
4499                                 jmove(joff(jp)->prev_job);
4500                 }
4501                 if (curjob)
4502                         jmove(curjob);
4503 #undef joff
4504 #undef jmove
4505         }
4506
4507         njobs += 4;
4508         jobtab = jp;
4509         jp = (struct job *)((char *)jp + len);
4510         jq = jp + 3;
4511         do {
4512                 jq->used = 0;
4513         } while (--jq >= jp);
4514         return jp;
4515 }
4516
4517 /*
4518  * Return a new job structure.
4519  * Called with interrupts off.
4520  */
4521 static struct job *
4522 makejob(/*union node *node,*/ int nprocs)
4523 {
4524         int i;
4525         struct job *jp;
4526
4527         for (i = njobs, jp = jobtab; ; jp++) {
4528                 if (--i < 0) {
4529                         jp = growjobtab();
4530                         break;
4531                 }
4532                 if (jp->used == 0)
4533                         break;
4534                 if (jp->state != JOBDONE || !jp->waited)
4535                         continue;
4536 #if JOBS
4537                 if (doing_jobctl)
4538                         continue;
4539 #endif
4540                 freejob(jp);
4541                 break;
4542         }
4543         memset(jp, 0, sizeof(*jp));
4544 #if JOBS
4545         /* jp->jobctl is a bitfield.
4546          * "jp->jobctl |= doing_jobctl" likely to give awful code */
4547         if (doing_jobctl)
4548                 jp->jobctl = 1;
4549 #endif
4550         jp->prev_job = curjob;
4551         curjob = jp;
4552         jp->used = 1;
4553         jp->ps = &jp->ps0;
4554         if (nprocs > 1) {
4555                 jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
4556         }
4557         TRACE(("makejob(%d) returns %%%d\n", nprocs,
4558                                 jobno(jp)));
4559         return jp;
4560 }
4561
4562 #if JOBS
4563 /*
4564  * Return a string identifying a command (to be printed by the
4565  * jobs command).
4566  */
4567 static char *cmdnextc;
4568
4569 static void
4570 cmdputs(const char *s)
4571 {
4572         static const char vstype[VSTYPE + 1][3] = {
4573                 "", "}", "-", "+", "?", "=",
4574                 "%", "%%", "#", "##"
4575                 IF_BASH_SUBSTR(, ":")
4576                 IF_BASH_PATTERN_SUBST(, "/", "//")
4577         };
4578
4579         const char *p, *str;
4580         char cc[2];
4581         char *nextc;
4582         unsigned char c;
4583         unsigned char subtype = 0;
4584         int quoted = 0;
4585
4586         cc[1] = '\0';
4587         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
4588         p = s;
4589         while ((c = *p++) != '\0') {
4590                 str = NULL;
4591                 switch (c) {
4592                 case CTLESC:
4593                         c = *p++;
4594                         break;
4595                 case CTLVAR:
4596                         subtype = *p++;
4597                         if ((subtype & VSTYPE) == VSLENGTH)
4598                                 str = "${#";
4599                         else
4600                                 str = "${";
4601                         goto dostr;
4602                 case CTLENDVAR:
4603                         str = "\"}" + !(quoted & 1);
4604                         quoted >>= 1;
4605                         subtype = 0;
4606                         goto dostr;
4607                 case CTLBACKQ:
4608                         str = "$(...)";
4609                         goto dostr;
4610 #if ENABLE_FEATURE_SH_MATH
4611                 case CTLARI:
4612                         str = "$((";
4613                         goto dostr;
4614                 case CTLENDARI:
4615                         str = "))";
4616                         goto dostr;
4617 #endif
4618                 case CTLQUOTEMARK:
4619                         quoted ^= 1;
4620                         c = '"';
4621                         break;
4622                 case '=':
4623                         if (subtype == 0)
4624                                 break;
4625                         if ((subtype & VSTYPE) != VSNORMAL)
4626                                 quoted <<= 1;
4627                         str = vstype[subtype & VSTYPE];
4628                         if (subtype & VSNUL)
4629                                 c = ':';
4630                         else
4631                                 goto checkstr;
4632                         break;
4633                 case '\'':
4634                 case '\\':
4635                 case '"':
4636                 case '$':
4637                         /* These can only happen inside quotes */
4638                         cc[0] = c;
4639                         str = cc;
4640                         c = '\\';
4641                         break;
4642                 default:
4643                         break;
4644                 }
4645                 USTPUTC(c, nextc);
4646  checkstr:
4647                 if (!str)
4648                         continue;
4649  dostr:
4650                 while ((c = *str++) != '\0') {
4651                         USTPUTC(c, nextc);
4652                 }
4653         } /* while *p++ not NUL */
4654
4655         if (quoted & 1) {
4656                 USTPUTC('"', nextc);
4657         }
4658         *nextc = 0;
4659         cmdnextc = nextc;
4660 }
4661
4662 /* cmdtxt() and cmdlist() call each other */
4663 static void cmdtxt(union node *n);
4664
4665 static void
4666 cmdlist(union node *np, int sep)
4667 {
4668         for (; np; np = np->narg.next) {
4669                 if (!sep)
4670                         cmdputs(" ");
4671                 cmdtxt(np);
4672                 if (sep && np->narg.next)
4673                         cmdputs(" ");
4674         }
4675 }
4676
4677 static void
4678 cmdtxt(union node *n)
4679 {
4680         union node *np;
4681         struct nodelist *lp;
4682         const char *p;
4683
4684         if (!n)
4685                 return;
4686         switch (n->type) {
4687         default:
4688 #if DEBUG
4689                 abort();
4690 #endif
4691         case NPIPE:
4692                 lp = n->npipe.cmdlist;
4693                 for (;;) {
4694                         cmdtxt(lp->n);
4695                         lp = lp->next;
4696                         if (!lp)
4697                                 break;
4698                         cmdputs(" | ");
4699                 }
4700                 break;
4701         case NSEMI:
4702                 p = "; ";
4703                 goto binop;
4704         case NAND:
4705                 p = " && ";
4706                 goto binop;
4707         case NOR:
4708                 p = " || ";
4709  binop:
4710                 cmdtxt(n->nbinary.ch1);
4711                 cmdputs(p);
4712                 n = n->nbinary.ch2;
4713                 goto donode;
4714         case NREDIR:
4715         case NBACKGND:
4716                 n = n->nredir.n;
4717                 goto donode;
4718         case NNOT:
4719                 cmdputs("!");
4720                 n = n->nnot.com;
4721  donode:
4722                 cmdtxt(n);
4723                 break;
4724         case NIF:
4725                 cmdputs("if ");
4726                 cmdtxt(n->nif.test);
4727                 cmdputs("; then ");
4728                 if (n->nif.elsepart) {
4729                         cmdtxt(n->nif.ifpart);
4730                         cmdputs("; else ");
4731                         n = n->nif.elsepart;
4732                 } else {
4733                         n = n->nif.ifpart;
4734                 }
4735                 p = "; fi";
4736                 goto dotail;
4737         case NSUBSHELL:
4738                 cmdputs("(");
4739                 n = n->nredir.n;
4740                 p = ")";
4741                 goto dotail;
4742         case NWHILE:
4743                 p = "while ";
4744                 goto until;
4745         case NUNTIL:
4746                 p = "until ";
4747  until:
4748                 cmdputs(p);
4749                 cmdtxt(n->nbinary.ch1);
4750                 n = n->nbinary.ch2;
4751                 p = "; done";
4752  dodo:
4753                 cmdputs("; do ");
4754  dotail:
4755                 cmdtxt(n);
4756                 goto dotail2;
4757         case NFOR:
4758                 cmdputs("for ");
4759                 cmdputs(n->nfor.var);
4760                 cmdputs(" in ");
4761                 cmdlist(n->nfor.args, 1);
4762                 n = n->nfor.body;
4763                 p = "; done";
4764                 goto dodo;
4765         case NDEFUN:
4766                 cmdputs(n->narg.text);
4767                 p = "() { ... }";
4768                 goto dotail2;
4769         case NCMD:
4770                 cmdlist(n->ncmd.args, 1);
4771                 cmdlist(n->ncmd.redirect, 0);
4772                 break;
4773         case NARG:
4774                 p = n->narg.text;
4775  dotail2:
4776                 cmdputs(p);
4777                 break;
4778         case NHERE:
4779         case NXHERE:
4780                 p = "<<...";
4781                 goto dotail2;
4782         case NCASE:
4783                 cmdputs("case ");
4784                 cmdputs(n->ncase.expr->narg.text);
4785                 cmdputs(" in ");
4786                 for (np = n->ncase.cases; np; np = np->nclist.next) {
4787                         cmdtxt(np->nclist.pattern);
4788                         cmdputs(") ");
4789                         cmdtxt(np->nclist.body);
4790                         cmdputs(";; ");
4791                 }
4792                 p = "esac";
4793                 goto dotail2;
4794         case NTO:
4795                 p = ">";
4796                 goto redir;
4797         case NCLOBBER:
4798                 p = ">|";
4799                 goto redir;
4800         case NAPPEND:
4801                 p = ">>";
4802                 goto redir;
4803 #if BASH_REDIR_OUTPUT
4804         case NTO2:
4805 #endif
4806         case NTOFD:
4807                 p = ">&";
4808                 goto redir;
4809         case NFROM:
4810                 p = "<";
4811                 goto redir;
4812         case NFROMFD:
4813                 p = "<&";
4814                 goto redir;
4815         case NFROMTO:
4816                 p = "<>";
4817  redir:
4818                 cmdputs(utoa(n->nfile.fd));
4819                 cmdputs(p);
4820                 if (n->type == NTOFD || n->type == NFROMFD) {
4821                         cmdputs(utoa(n->ndup.dupfd));
4822                         break;
4823                 }
4824                 n = n->nfile.fname;
4825                 goto donode;
4826         }
4827 }
4828
4829 static char *
4830 commandtext(union node *n)
4831 {
4832         char *name;
4833
4834         STARTSTACKSTR(cmdnextc);
4835         cmdtxt(n);
4836         name = stackblock();
4837         TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
4838         return ckstrdup(name);
4839 }
4840 #endif /* JOBS */
4841
4842 /*
4843  * Fork off a subshell.  If we are doing job control, give the subshell its
4844  * own process group.  Jp is a job structure that the job is to be added to.
4845  * N is the command that will be evaluated by the child.  Both jp and n may
4846  * be NULL.  The mode parameter can be one of the following:
4847  *      FORK_FG - Fork off a foreground process.
4848  *      FORK_BG - Fork off a background process.
4849  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
4850  *                   process group even if job control is on.
4851  *
4852  * When job control is turned off, background processes have their standard
4853  * input redirected to /dev/null (except for the second and later processes
4854  * in a pipeline).
4855  *
4856  * Called with interrupts off.
4857  */
4858 /*
4859  * Clear traps on a fork.
4860  */
4861 static void
4862 clear_traps(void)
4863 {
4864         char **tp;
4865
4866         INT_OFF;
4867         for (tp = trap; tp < &trap[NSIG]; tp++) {
4868                 if (*tp && **tp) {      /* trap not NULL or "" (SIG_IGN) */
4869                         if (trap_ptr == trap)
4870                                 free(*tp);
4871                         /* else: it "belongs" to trap_ptr vector, don't free */
4872                         *tp = NULL;
4873                         if ((tp - trap) != 0)
4874                                 setsignal(tp - trap);
4875                 }
4876         }
4877         may_have_traps = 0;
4878         INT_ON;
4879 }
4880
4881 /* Lives far away from here, needed for forkchild */
4882 static void closescript(void);
4883
4884 /* Called after fork(), in child */
4885 /* jp and n are NULL when called by openhere() for heredoc support */
4886 static NOINLINE void
4887 forkchild(struct job *jp, union node *n, int mode)
4888 {
4889         int oldlvl;
4890
4891         TRACE(("Child shell %d\n", getpid()));
4892         oldlvl = shlvl;
4893         shlvl++;
4894
4895         /* man bash: "Non-builtin commands run by bash have signal handlers
4896          * set to the values inherited by the shell from its parent".
4897          * Do we do it correctly? */
4898
4899         closescript();
4900
4901         if (mode == FORK_NOJOB          /* is it `xxx` ? */
4902          && n && n->type == NCMD        /* is it single cmd? */
4903         /* && n->ncmd.args->type == NARG - always true? */
4904          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
4905          && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
4906         /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
4907         ) {
4908                 TRACE(("Trap hack\n"));
4909                 /* Awful hack for `trap` or $(trap).
4910                  *
4911                  * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
4912                  * contains an example where "trap" is executed in a subshell:
4913                  *
4914                  * save_traps=$(trap)
4915                  * ...
4916                  * eval "$save_traps"
4917                  *
4918                  * Standard does not say that "trap" in subshell shall print
4919                  * parent shell's traps. It only says that its output
4920                  * must have suitable form, but then, in the above example
4921                  * (which is not supposed to be normative), it implies that.
4922                  *
4923                  * bash (and probably other shell) does implement it
4924                  * (traps are reset to defaults, but "trap" still shows them),
4925                  * but as a result, "trap" logic is hopelessly messed up:
4926                  *
4927                  * # trap
4928                  * trap -- 'echo Ho' SIGWINCH  <--- we have a handler
4929                  * # (trap)        <--- trap is in subshell - no output (correct, traps are reset)
4930                  * # true | trap   <--- trap is in subshell - no output (ditto)
4931                  * # echo `true | trap`    <--- in subshell - output (but traps are reset!)
4932                  * trap -- 'echo Ho' SIGWINCH
4933                  * # echo `(trap)`         <--- in subshell in subshell - output
4934                  * trap -- 'echo Ho' SIGWINCH
4935                  * # echo `true | (trap)`  <--- in subshell in subshell in subshell - output!
4936                  * trap -- 'echo Ho' SIGWINCH
4937                  *
4938                  * The rules when to forget and when to not forget traps
4939                  * get really complex and nonsensical.
4940                  *
4941                  * Our solution: ONLY bare $(trap) or `trap` is special.
4942                  */
4943                 /* Save trap handler strings for trap builtin to print */
4944                 trap_ptr = xmemdup(trap, sizeof(trap));
4945                 /* Fall through into clearing traps */
4946         }
4947         clear_traps();
4948 #if JOBS
4949         /* do job control only in root shell */
4950         doing_jobctl = 0;
4951         if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
4952                 pid_t pgrp;
4953
4954                 if (jp->nprocs == 0)
4955                         pgrp = getpid();
4956                 else
4957                         pgrp = jp->ps[0].ps_pid;
4958                 /* this can fail because we are doing it in the parent also */
4959                 setpgid(0, pgrp);
4960                 if (mode == FORK_FG)
4961                         xtcsetpgrp(ttyfd, pgrp);
4962                 setsignal(SIGTSTP);
4963                 setsignal(SIGTTOU);
4964         } else
4965 #endif
4966         if (mode == FORK_BG) {
4967                 /* man bash: "When job control is not in effect,
4968                  * asynchronous commands ignore SIGINT and SIGQUIT" */
4969                 ignoresig(SIGINT);
4970                 ignoresig(SIGQUIT);
4971                 if (jp->nprocs == 0) {
4972                         close(0);
4973                         if (open(bb_dev_null, O_RDONLY) != 0)
4974                                 ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
4975                 }
4976         }
4977         if (oldlvl == 0) {
4978                 if (iflag) { /* why if iflag only? */
4979                         setsignal(SIGINT);
4980                         setsignal(SIGTERM);
4981                 }
4982                 /* man bash:
4983                  * "In all cases, bash ignores SIGQUIT. Non-builtin
4984                  * commands run by bash have signal handlers
4985                  * set to the values inherited by the shell
4986                  * from its parent".
4987                  * Take care of the second rule: */
4988                 setsignal(SIGQUIT);
4989         }
4990 #if JOBS
4991         if (n && n->type == NCMD
4992          && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
4993         ) {
4994                 TRACE(("Job hack\n"));
4995                 /* "jobs": we do not want to clear job list for it,
4996                  * instead we remove only _its_ own_ job from job list.
4997                  * This makes "jobs .... | cat" more useful.
4998                  */
4999                 freejob(curjob);
5000                 return;
5001         }
5002 #endif
5003         for (jp = curjob; jp; jp = jp->prev_job)
5004                 freejob(jp);
5005         jobless = 0;
5006 }
5007
5008 /* Called after fork(), in parent */
5009 #if !JOBS
5010 #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
5011 #endif
5012 static void
5013 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
5014 {
5015         TRACE(("In parent shell: child = %d\n", pid));
5016         if (!jp) {
5017                 /* jp is NULL when called by openhere() for heredoc support */
5018                 while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
5019                         continue;
5020                 jobless++;
5021                 return;
5022         }
5023 #if JOBS
5024         if (mode != FORK_NOJOB && jp->jobctl) {
5025                 int pgrp;
5026
5027                 if (jp->nprocs == 0)
5028                         pgrp = pid;
5029                 else
5030                         pgrp = jp->ps[0].ps_pid;
5031                 /* This can fail because we are doing it in the child also */
5032                 setpgid(pid, pgrp);
5033         }
5034 #endif
5035         if (mode == FORK_BG) {
5036                 backgndpid = pid;               /* set $! */
5037                 set_curjob(jp, CUR_RUNNING);
5038         }
5039         if (jp) {
5040                 struct procstat *ps = &jp->ps[jp->nprocs++];
5041                 ps->ps_pid = pid;
5042                 ps->ps_status = -1;
5043                 ps->ps_cmd = nullstr;
5044 #if JOBS
5045                 if (doing_jobctl && n)
5046                         ps->ps_cmd = commandtext(n);
5047 #endif
5048         }
5049 }
5050
5051 /* jp and n are NULL when called by openhere() for heredoc support */
5052 static int
5053 forkshell(struct job *jp, union node *n, int mode)
5054 {
5055         int pid;
5056
5057         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
5058         pid = fork();
5059         if (pid < 0) {
5060                 TRACE(("Fork failed, errno=%d", errno));
5061                 if (jp)
5062                         freejob(jp);
5063                 ash_msg_and_raise_error("can't fork");
5064         }
5065         if (pid == 0) {
5066                 CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
5067                 forkchild(jp, n, mode);
5068         } else {
5069                 forkparent(jp, n, mode, pid);
5070         }
5071         return pid;
5072 }
5073
5074 /*
5075  * Wait for job to finish.
5076  *
5077  * Under job control we have the problem that while a child process
5078  * is running interrupts generated by the user are sent to the child
5079  * but not to the shell.  This means that an infinite loop started by
5080  * an interactive user may be hard to kill.  With job control turned off,
5081  * an interactive user may place an interactive program inside a loop.
5082  * If the interactive program catches interrupts, the user doesn't want
5083  * these interrupts to also abort the loop.  The approach we take here
5084  * is to have the shell ignore interrupt signals while waiting for a
5085  * foreground process to terminate, and then send itself an interrupt
5086  * signal if the child process was terminated by an interrupt signal.
5087  * Unfortunately, some programs want to do a bit of cleanup and then
5088  * exit on interrupt; unless these processes terminate themselves by
5089  * sending a signal to themselves (instead of calling exit) they will
5090  * confuse this approach.
5091  *
5092  * Called with interrupts off.
5093  */
5094 static int
5095 waitforjob(struct job *jp)
5096 {
5097         int st;
5098
5099         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
5100
5101         INT_OFF;
5102         while (jp->state == JOBRUNNING) {
5103                 /* In non-interactive shells, we _can_ get
5104                  * a keyboard signal here and be EINTRed,
5105                  * but we just loop back, waiting for command to complete.
5106                  *
5107                  * man bash:
5108                  * "If bash is waiting for a command to complete and receives
5109                  * a signal for which a trap has been set, the trap
5110                  * will not be executed until the command completes."
5111                  *
5112                  * Reality is that even if trap is not set, bash
5113                  * will not act on the signal until command completes.
5114                  * Try this. sleep5intoff.c:
5115                  * #include <signal.h>
5116                  * #include <unistd.h>
5117                  * int main() {
5118                  *         sigset_t set;
5119                  *         sigemptyset(&set);
5120                  *         sigaddset(&set, SIGINT);
5121                  *         sigaddset(&set, SIGQUIT);
5122                  *         sigprocmask(SIG_BLOCK, &set, NULL);
5123                  *         sleep(5);
5124                  *         return 0;
5125                  * }
5126                  * $ bash -c './sleep5intoff; echo hi'
5127                  * ^C^C^C^C <--- pressing ^C once a second
5128                  * $ _
5129                  * $ bash -c './sleep5intoff; echo hi'
5130                  * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
5131                  * $ _
5132                  */
5133                 dowait(DOWAIT_BLOCK, jp);
5134         }
5135         INT_ON;
5136
5137         st = getstatus(jp);
5138 #if JOBS
5139         if (jp->jobctl) {
5140                 xtcsetpgrp(ttyfd, rootpid);
5141                 restore_tty_if_stopped_or_signaled(jp);
5142
5143                 /*
5144                  * This is truly gross.
5145                  * If we're doing job control, then we did a TIOCSPGRP which
5146                  * caused us (the shell) to no longer be in the controlling
5147                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
5148                  * intuit from the subprocess exit status whether a SIGINT
5149                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
5150                  */
5151                 if (jp->sigint) /* TODO: do the same with all signals */
5152                         raise(SIGINT); /* ... by raise(jp->sig) instead? */
5153         }
5154         if (jp->state == JOBDONE)
5155 #endif
5156                 freejob(jp);
5157         return st;
5158 }
5159
5160 /*
5161  * return 1 if there are stopped jobs, otherwise 0
5162  */
5163 static int
5164 stoppedjobs(void)
5165 {
5166         struct job *jp;
5167         int retval;
5168
5169         retval = 0;
5170         if (job_warning)
5171                 goto out;
5172         jp = curjob;
5173         if (jp && jp->state == JOBSTOPPED) {
5174                 out2str("You have stopped jobs.\n");
5175                 job_warning = 2;
5176                 retval++;
5177         }
5178  out:
5179         return retval;
5180 }
5181
5182
5183 /*
5184  * Code for dealing with input/output redirection.
5185  */
5186
5187 #undef EMPTY
5188 #undef CLOSED
5189 #define EMPTY -2                /* marks an unused slot in redirtab */
5190 #define CLOSED -3               /* marks a slot of previously-closed fd */
5191
5192 /*
5193  * Handle here documents.  Normally we fork off a process to write the
5194  * data to a pipe.  If the document is short, we can stuff the data in
5195  * the pipe without forking.
5196  */
5197 /* openhere needs this forward reference */
5198 static void expandhere(union node *arg, int fd);
5199 static int
5200 openhere(union node *redir)
5201 {
5202         int pip[2];
5203         size_t len = 0;
5204
5205         if (pipe(pip) < 0)
5206                 ash_msg_and_raise_error("pipe call failed");
5207         if (redir->type == NHERE) {
5208                 len = strlen(redir->nhere.doc->narg.text);
5209                 if (len <= PIPE_BUF) {
5210                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5211                         goto out;
5212                 }
5213         }
5214         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
5215                 /* child */
5216                 close(pip[0]);
5217                 ignoresig(SIGINT);  //signal(SIGINT, SIG_IGN);
5218                 ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
5219                 ignoresig(SIGHUP);  //signal(SIGHUP, SIG_IGN);
5220                 ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
5221                 signal(SIGPIPE, SIG_DFL);
5222                 if (redir->type == NHERE)
5223                         full_write(pip[1], redir->nhere.doc->narg.text, len);
5224                 else /* NXHERE */
5225                         expandhere(redir->nhere.doc, pip[1]);
5226                 _exit(EXIT_SUCCESS);
5227         }
5228  out:
5229         close(pip[1]);
5230         return pip[0];
5231 }
5232
5233 static int
5234 openredirect(union node *redir)
5235 {
5236         struct stat sb;
5237         char *fname;
5238         int f;
5239
5240         switch (redir->nfile.type) {
5241 /* Can't happen, our single caller does this itself */
5242 //      case NTOFD:
5243 //      case NFROMFD:
5244 //              return -1;
5245         case NHERE:
5246         case NXHERE:
5247                 return openhere(redir);
5248         }
5249
5250         /* For N[X]HERE, reading redir->nfile.expfname would touch beyond
5251          * allocated space. Do it only when we know it is safe.
5252          */
5253         fname = redir->nfile.expfname;
5254
5255         switch (redir->nfile.type) {
5256         default:
5257 #if DEBUG
5258                 abort();
5259 #endif
5260         case NFROM:
5261                 f = open(fname, O_RDONLY);
5262                 if (f < 0)
5263                         goto eopen;
5264                 break;
5265         case NFROMTO:
5266                 f = open(fname, O_RDWR|O_CREAT, 0666);
5267                 if (f < 0)
5268                         goto ecreate;
5269                 break;
5270         case NTO:
5271 #if BASH_REDIR_OUTPUT
5272         case NTO2:
5273 #endif
5274                 /* Take care of noclobber mode. */
5275                 if (Cflag) {
5276                         if (stat(fname, &sb) < 0) {
5277                                 f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
5278                                 if (f < 0)
5279                                         goto ecreate;
5280                         } else if (!S_ISREG(sb.st_mode)) {
5281                                 f = open(fname, O_WRONLY, 0666);
5282                                 if (f < 0)
5283                                         goto ecreate;
5284                                 if (fstat(f, &sb) < 0 && S_ISREG(sb.st_mode)) {
5285                                         close(f);
5286                                         errno = EEXIST;
5287                                         goto ecreate;
5288                                 }
5289                         } else {
5290                                 errno = EEXIST;
5291                                 goto ecreate;
5292                         }
5293                         break;
5294                 }
5295                 /* FALLTHROUGH */
5296         case NCLOBBER:
5297                 f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
5298                 if (f < 0)
5299                         goto ecreate;
5300                 break;
5301         case NAPPEND:
5302                 f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
5303                 if (f < 0)
5304                         goto ecreate;
5305                 break;
5306         }
5307
5308         return f;
5309  ecreate:
5310         ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
5311  eopen:
5312         ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
5313 }
5314
5315 /*
5316  * Copy a file descriptor to be >= 10. Throws exception on error.
5317  */
5318 static int
5319 savefd(int from)
5320 {
5321         int newfd;
5322         int err;
5323
5324         newfd = fcntl(from, F_DUPFD, 10);
5325         err = newfd < 0 ? errno : 0;
5326         if (err != EBADF) {
5327                 if (err)
5328                         ash_msg_and_raise_perror("%d", from);
5329                 close(from);
5330                 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5331         }
5332
5333         return newfd;
5334 }
5335 static int
5336 dup2_or_raise(int from, int to)
5337 {
5338         int newfd;
5339
5340         newfd = (from != to) ? dup2(from, to) : to;
5341         if (newfd < 0) {
5342                 /* Happens when source fd is not open: try "echo >&99" */
5343                 ash_msg_and_raise_perror("%d", from);
5344         }
5345         return newfd;
5346 }
5347
5348 /* Struct def and variable are moved down to the first usage site */
5349 struct two_fd_t {
5350         int orig, copy;
5351 };
5352 struct redirtab {
5353         struct redirtab *next;
5354         int pair_count;
5355         struct two_fd_t two_fd[];
5356 };
5357 #define redirlist (G_var.redirlist)
5358 enum {
5359         COPYFD_RESTORE = (int)~(INT_MAX),
5360 };
5361
5362 static int
5363 need_to_remember(struct redirtab *rp, int fd)
5364 {
5365         int i;
5366
5367         if (!rp) /* remembering was not requested */
5368                 return 0;
5369
5370         for (i = 0; i < rp->pair_count; i++) {
5371                 if (rp->two_fd[i].orig == fd) {
5372                         /* already remembered */
5373                         return 0;
5374                 }
5375         }
5376         return 1;
5377 }
5378
5379 /* "hidden" fd is a fd used to read scripts, or a copy of such */
5380 static int
5381 is_hidden_fd(struct redirtab *rp, int fd)
5382 {
5383         int i;
5384         struct parsefile *pf;
5385
5386         if (fd == -1)
5387                 return 0;
5388         /* Check open scripts' fds */
5389         pf = g_parsefile;
5390         while (pf) {
5391                 /* We skip pf_fd == 0 case because of the following case:
5392                  * $ ash  # running ash interactively
5393                  * $ . ./script.sh
5394                  * and in script.sh: "exec 9>&0".
5395                  * Even though top-level pf_fd _is_ 0,
5396                  * it's still ok to use it: "read" builtin uses it,
5397                  * why should we cripple "exec" builtin?
5398                  */
5399                 if (pf->pf_fd > 0 && fd == pf->pf_fd) {
5400                         return 1;
5401                 }
5402                 pf = pf->prev;
5403         }
5404
5405         if (!rp)
5406                 return 0;
5407         /* Check saved fds of redirects */
5408         fd |= COPYFD_RESTORE;
5409         for (i = 0; i < rp->pair_count; i++) {
5410                 if (rp->two_fd[i].copy == fd) {
5411                         return 1;
5412                 }
5413         }
5414         return 0;
5415 }
5416
5417 /*
5418  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
5419  * old file descriptors are stashed away so that the redirection can be
5420  * undone by calling popredir.
5421  */
5422 /* flags passed to redirect */
5423 #define REDIR_PUSH    01        /* save previous values of file descriptors */
5424 #define REDIR_SAVEFD2 03        /* set preverrout */
5425 static void
5426 redirect(union node *redir, int flags)
5427 {
5428         struct redirtab *sv;
5429         int sv_pos;
5430         int i;
5431         int fd;
5432         int newfd;
5433         int copied_fd2 = -1;
5434
5435         if (!redir) {
5436                 return;
5437         }
5438
5439         sv = NULL;
5440         sv_pos = 0;
5441         INT_OFF;
5442         if (flags & REDIR_PUSH) {
5443                 union node *tmp = redir;
5444                 do {
5445                         sv_pos++;
5446 #if BASH_REDIR_OUTPUT
5447                         if (tmp->nfile.type == NTO2)
5448                                 sv_pos++;
5449 #endif
5450                         tmp = tmp->nfile.next;
5451                 } while (tmp);
5452                 sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
5453                 sv->next = redirlist;
5454                 sv->pair_count = sv_pos;
5455                 redirlist = sv;
5456                 while (sv_pos > 0) {
5457                         sv_pos--;
5458                         sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
5459                 }
5460         }
5461
5462         do {
5463                 int right_fd = -1;
5464                 fd = redir->nfile.fd;
5465                 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
5466                         right_fd = redir->ndup.dupfd;
5467                         //bb_error_msg("doing %d > %d", fd, right_fd);
5468                         /* redirect from/to same file descriptor? */
5469                         if (right_fd == fd)
5470                                 continue;
5471                         /* "echo >&10" and 10 is a fd opened to a sh script? */
5472                         if (is_hidden_fd(sv, right_fd)) {
5473                                 errno = EBADF; /* as if it is closed */
5474                                 ash_msg_and_raise_perror("%d", right_fd);
5475                         }
5476                         newfd = -1;
5477                 } else {
5478                         newfd = openredirect(redir); /* always >= 0 */
5479                         if (fd == newfd) {
5480                                 /* Descriptor wasn't open before redirect.
5481                                  * Mark it for close in the future */
5482                                 if (need_to_remember(sv, fd)) {
5483                                         goto remember_to_close;
5484                                 }
5485                                 continue;
5486                         }
5487                 }
5488 #if BASH_REDIR_OUTPUT
5489  redirect_more:
5490 #endif
5491                 if (need_to_remember(sv, fd)) {
5492                         /* Copy old descriptor */
5493                         /* Careful to not accidentally "save"
5494                          * to the same fd as right side fd in N>&M */
5495                         int minfd = right_fd < 10 ? 10 : right_fd + 1;
5496 #if defined(F_DUPFD_CLOEXEC)
5497                         i = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
5498 #else
5499                         i = fcntl(fd, F_DUPFD, minfd);
5500 #endif
5501                         if (i == -1) {
5502                                 i = errno;
5503                                 if (i != EBADF) {
5504                                         /* Strange error (e.g. "too many files" EMFILE?) */
5505                                         if (newfd >= 0)
5506                                                 close(newfd);
5507                                         errno = i;
5508                                         ash_msg_and_raise_perror("%d", fd);
5509                                         /* NOTREACHED */
5510                                 }
5511                                 /* EBADF: it is not open - good, remember to close it */
5512  remember_to_close:
5513                                 i = CLOSED;
5514                         } else { /* fd is open, save its copy */
5515 #if !defined(F_DUPFD_CLOEXEC)
5516                                 fcntl(i, F_SETFD, FD_CLOEXEC);
5517 #endif
5518                                 /* "exec fd>&-" should not close fds
5519                                  * which point to script file(s).
5520                                  * Force them to be restored afterwards */
5521                                 if (is_hidden_fd(sv, fd))
5522                                         i |= COPYFD_RESTORE;
5523                         }
5524                         if (fd == 2)
5525                                 copied_fd2 = i;
5526                         sv->two_fd[sv_pos].orig = fd;
5527                         sv->two_fd[sv_pos].copy = i;
5528                         sv_pos++;
5529                 }
5530                 if (newfd < 0) {
5531                         /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
5532                         if (redir->ndup.dupfd < 0) { /* "fd>&-" */
5533                                 /* Don't want to trigger debugging */
5534                                 if (fd != -1)
5535                                         close(fd);
5536                         } else {
5537                                 dup2_or_raise(redir->ndup.dupfd, fd);
5538                         }
5539                 } else if (fd != newfd) { /* move newfd to fd */
5540                         dup2_or_raise(newfd, fd);
5541 #if BASH_REDIR_OUTPUT
5542                         if (!(redir->nfile.type == NTO2 && fd == 2))
5543 #endif
5544                                 close(newfd);
5545                 }
5546 #if BASH_REDIR_OUTPUT
5547                 if (redir->nfile.type == NTO2 && fd == 1) {
5548                         /* We already redirected it to fd 1, now copy it to 2 */
5549                         newfd = 1;
5550                         fd = 2;
5551                         goto redirect_more;
5552                 }
5553 #endif
5554         } while ((redir = redir->nfile.next) != NULL);
5555
5556         INT_ON;
5557         if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
5558                 preverrout_fd = copied_fd2;
5559 }
5560
5561 static int
5562 redirectsafe(union node *redir, int flags)
5563 {
5564         int err;
5565         volatile int saveint;
5566         struct jmploc *volatile savehandler = exception_handler;
5567         struct jmploc jmploc;
5568
5569         SAVE_INT(saveint);
5570         /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
5571         err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
5572         if (!err) {
5573                 exception_handler = &jmploc;
5574                 redirect(redir, flags);
5575         }
5576         exception_handler = savehandler;
5577         if (err && exception_type != EXERROR)
5578                 longjmp(exception_handler->loc, 1);
5579         RESTORE_INT(saveint);
5580         return err;
5581 }
5582
5583 /*
5584  * Undo the effects of the last redirection.
5585  */
5586 static void
5587 popredir(int drop, int restore)
5588 {
5589         struct redirtab *rp;
5590         int i;
5591
5592         if (redirlist == NULL)
5593                 return;
5594         INT_OFF;
5595         rp = redirlist;
5596         for (i = 0; i < rp->pair_count; i++) {
5597                 int fd = rp->two_fd[i].orig;
5598                 int copy = rp->two_fd[i].copy;
5599                 if (copy == CLOSED) {
5600                         if (!drop)
5601                                 close(fd);
5602                         continue;
5603                 }
5604                 if (copy != EMPTY) {
5605                         if (!drop || (restore && (copy & COPYFD_RESTORE))) {
5606                                 copy &= ~COPYFD_RESTORE;
5607                                 /*close(fd);*/
5608                                 dup2_or_raise(copy, fd);
5609                         }
5610                         close(copy & ~COPYFD_RESTORE);
5611                 }
5612         }
5613         redirlist = rp->next;
5614         free(rp);
5615         INT_ON;
5616 }
5617
5618
5619 /* ============ Routines to expand arguments to commands
5620  *
5621  * We have to deal with backquotes, shell variables, and file metacharacters.
5622  */
5623
5624 #if ENABLE_FEATURE_SH_MATH
5625 static arith_t
5626 ash_arith(const char *s)
5627 {
5628         arith_state_t math_state;
5629         arith_t result;
5630
5631         math_state.lookupvar = lookupvar;
5632         math_state.setvar    = setvar0;
5633         //math_state.endofname = endofname;
5634
5635         INT_OFF;
5636         result = arith(&math_state, s);
5637         if (math_state.errmsg)
5638                 ash_msg_and_raise_error(math_state.errmsg);
5639         INT_ON;
5640
5641         return result;
5642 }
5643 #endif
5644
5645 /*
5646  * expandarg flags
5647  */
5648 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
5649 #define EXP_TILDE       0x2     /* do normal tilde expansion */
5650 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
5651 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
5652 /* ^^^^^^^^^^^^^^ this is meant to support constructs such as "cmd >file*.txt"
5653  * POSIX says for this case:
5654  *  Pathname expansion shall not be performed on the word by a
5655  *  non-interactive shell; an interactive shell may perform it, but shall
5656  *  do so only when the expansion would result in one word.
5657  * Currently, our code complies to the above rule by never globbing
5658  * redirection filenames.
5659  * Bash performs globbing, unless it is non-interactive and in POSIX mode.
5660  * (this means that on a typical Linux distro, bash almost always
5661  * performs globbing, and thus diverges from what we do).
5662  */
5663 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
5664 #define EXP_QPAT        0x20    /* pattern in quoted parameter expansion */
5665 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
5666 #define EXP_WORD        0x80    /* expand word in parameter expansion */
5667 #define EXP_QUOTED      0x100   /* expand word in double quotes */
5668 /*
5669  * rmescape() flags
5670  */
5671 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
5672 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
5673 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
5674 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
5675 #define RMESCAPE_SLASH  0x20    /* Stop globbing after slash */
5676
5677 /* Add CTLESC when necessary. */
5678 #define QUOTES_ESC     (EXP_FULL | EXP_CASE | EXP_QPAT)
5679 /* Do not skip NUL characters. */
5680 #define QUOTES_KEEPNUL EXP_TILDE
5681
5682 /*
5683  * Structure specifying which parts of the string should be searched
5684  * for IFS characters.
5685  */
5686 struct ifsregion {
5687         struct ifsregion *next; /* next region in list */
5688         int begoff;             /* offset of start of region */
5689         int endoff;             /* offset of end of region */
5690         int nulonly;            /* search for nul bytes only */
5691 };
5692
5693 struct arglist {
5694         struct strlist *list;
5695         struct strlist **lastp;
5696 };
5697
5698 /* output of current string */
5699 static char *expdest;
5700 /* list of back quote expressions */
5701 static struct nodelist *argbackq;
5702 /* first struct in list of ifs regions */
5703 static struct ifsregion ifsfirst;
5704 /* last struct in list */
5705 static struct ifsregion *ifslastp;
5706 /* holds expanded arg list */
5707 static struct arglist exparg;
5708
5709 /*
5710  * Our own itoa().
5711  * cvtnum() is used even if math support is off (to prepare $? values and such).
5712  */
5713 static int
5714 cvtnum(arith_t num)
5715 {
5716         int len;
5717
5718         /* 32-bit and wider ints require buffer size of bytes*3 (or less) */
5719         len = sizeof(arith_t) * 3;
5720         /* If narrower: worst case, 1-byte ints: need 5 bytes: "-127<NUL>" */
5721         if (sizeof(arith_t) < 4) len += 2;
5722
5723         expdest = makestrspace(len, expdest);
5724         len = fmtstr(expdest, len, ARITH_FMT, num);
5725         STADJUST(len, expdest);
5726         return len;
5727 }
5728
5729 /*
5730  * Break the argument string into pieces based upon IFS and add the
5731  * strings to the argument list.  The regions of the string to be
5732  * searched for IFS characters have been stored by recordregion.
5733  */
5734 static void
5735 ifsbreakup(char *string, struct arglist *arglist)
5736 {
5737         struct ifsregion *ifsp;
5738         struct strlist *sp;
5739         char *start;
5740         char *p;
5741         char *q;
5742         const char *ifs, *realifs;
5743         int ifsspc;
5744         int nulonly;
5745
5746         start = string;
5747         if (ifslastp != NULL) {
5748                 ifsspc = 0;
5749                 nulonly = 0;
5750                 realifs = ifsset() ? ifsval() : defifs;
5751                 ifsp = &ifsfirst;
5752                 do {
5753                         p = string + ifsp->begoff;
5754                         nulonly = ifsp->nulonly;
5755                         ifs = nulonly ? nullstr : realifs;
5756                         ifsspc = 0;
5757                         while (p < string + ifsp->endoff) {
5758                                 q = p;
5759                                 if ((unsigned char)*p == CTLESC)
5760                                         p++;
5761                                 if (!strchr(ifs, *p)) {
5762                                         p++;
5763                                         continue;
5764                                 }
5765                                 if (!nulonly)
5766                                         ifsspc = (strchr(defifs, *p) != NULL);
5767                                 /* Ignore IFS whitespace at start */
5768                                 if (q == start && ifsspc) {
5769                                         p++;
5770                                         start = p;
5771                                         continue;
5772                                 }
5773                                 *q = '\0';
5774                                 sp = stzalloc(sizeof(*sp));
5775                                 sp->text = start;
5776                                 *arglist->lastp = sp;
5777                                 arglist->lastp = &sp->next;
5778                                 p++;
5779                                 if (!nulonly) {
5780                                         for (;;) {
5781                                                 if (p >= string + ifsp->endoff) {
5782                                                         break;
5783                                                 }
5784                                                 q = p;
5785                                                 if ((unsigned char)*p == CTLESC)
5786                                                         p++;
5787                                                 if (strchr(ifs, *p) == NULL) {
5788                                                         p = q;
5789                                                         break;
5790                                                 }
5791                                                 if (strchr(defifs, *p) == NULL) {
5792                                                         if (ifsspc) {
5793                                                                 p++;
5794                                                                 ifsspc = 0;
5795                                                         } else {
5796                                                                 p = q;
5797                                                                 break;
5798                                                         }
5799                                                 } else
5800                                                         p++;
5801                                         }
5802                                 }
5803                                 start = p;
5804                         } /* while */
5805                         ifsp = ifsp->next;
5806                 } while (ifsp != NULL);
5807                 if (nulonly)
5808                         goto add;
5809         }
5810
5811         if (!*start)
5812                 return;
5813
5814  add:
5815         sp = stzalloc(sizeof(*sp));
5816         sp->text = start;
5817         *arglist->lastp = sp;
5818         arglist->lastp = &sp->next;
5819 }
5820
5821 static void
5822 ifsfree(void)
5823 {
5824         struct ifsregion *p = ifsfirst.next;
5825
5826         if (!p)
5827                 goto out;
5828
5829         INT_OFF;
5830         do {
5831                 struct ifsregion *ifsp;
5832                 ifsp = p->next;
5833                 free(p);
5834                 p = ifsp;
5835         } while (p);
5836         ifsfirst.next = NULL;
5837         INT_ON;
5838  out:
5839         ifslastp = NULL;
5840 }
5841
5842 static size_t
5843 esclen(const char *start, const char *p)
5844 {
5845         size_t esc = 0;
5846
5847         while (p > start && (unsigned char)*--p == CTLESC) {
5848                 esc++;
5849         }
5850         return esc;
5851 }
5852
5853 /*
5854  * Remove any CTLESC characters from a string.
5855  */
5856 static char *
5857 rmescapes(char *str, int flag)
5858 {
5859         static const char qchars[] ALIGN1 = {
5860                 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5861
5862         char *p, *q, *r;
5863         unsigned inquotes;
5864         unsigned protect_against_glob;
5865         unsigned globbing;
5866         IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5867
5868         p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5869         if (!p)
5870                 return str;
5871
5872         q = p;
5873         r = str;
5874         if (flag & RMESCAPE_ALLOC) {
5875                 size_t len = p - str;
5876                 size_t fulllen = len + strlen(p) + 1;
5877
5878                 if (flag & RMESCAPE_GROW) {
5879                         int strloc = str - (char *)stackblock();
5880                         r = makestrspace(fulllen, expdest);
5881                         /* p and str may be invalidated by makestrspace */
5882                         str = (char *)stackblock() + strloc;
5883                         p = str + len;
5884                 } else if (flag & RMESCAPE_HEAP) {
5885                         r = ckmalloc(fulllen);
5886                 } else {
5887                         r = stalloc(fulllen);
5888                 }
5889                 q = r;
5890                 if (len > 0) {
5891                         q = (char *)mempcpy(q, str, len);
5892                 }
5893         }
5894
5895         inquotes = 0;
5896         globbing = flag & RMESCAPE_GLOB;
5897         protect_against_glob = globbing;
5898         while (*p) {
5899                 if ((unsigned char)*p == CTLQUOTEMARK) {
5900 // Note: both inquotes and protect_against_glob only affect whether
5901 // CTLESC,<ch> gets converted to <ch> or to \<ch>
5902                         inquotes = ~inquotes;
5903                         p++;
5904                         protect_against_glob = globbing;
5905                         continue;
5906                 }
5907                 if ((unsigned char)*p == CTLESC) {
5908                         p++;
5909 #if DEBUG
5910                         if (*p == '\0')
5911                                 ash_msg_and_raise_error("CTLESC at EOL (shouldn't happen)");
5912 #endif
5913                         if (protect_against_glob) {
5914                                 /*
5915                                  * We used to trust glob() and fnmatch() to eat
5916                                  * superfluous escapes (\z where z has no
5917                                  * special meaning anyway). But this causes
5918                                  * bugs such as string of one greek letter rho
5919                                  * (unicode-encoded as two bytes "cf,81")
5920                                  * getting encoded as "cf,CTLESC,81"
5921                                  * and here, converted to "cf,\,81" -
5922                                  * which does not go well with some flavors
5923                                  * of fnmatch() in unicode locales
5924                                  * (for example, glibc <= 2.22).
5925                                  *
5926                                  * Lets add "\" only on the chars which need it.
5927                                  * Testcases for less obvious chars are shown.
5928                                  */
5929                                 if (*p == '*'
5930                                  || *p == '?'
5931                                  || *p == '['
5932                                  || *p == '\\' /* case '\' in \\ ) echo ok;; *) echo WRONG;; esac */
5933                                  || *p == ']' /* case ']' in [a\]] ) echo ok;; *) echo WRONG;; esac */
5934                                  || *p == '-' /* case '-' in [a\-c]) echo ok;; *) echo WRONG;; esac */
5935                                  || *p == '!' /* case '!' in [\!] ) echo ok;; *) echo WRONG;; esac */
5936                                 /* Some libc support [^negate], that's why "^" also needs love */
5937                                  || *p == '^' /* case '^' in [\^] ) echo ok;; *) echo WRONG;; esac */
5938                                 ) {
5939                                         *q++ = '\\';
5940                                 }
5941                         }
5942                 } else if (*p == '\\' && !inquotes) {
5943                         /* naked back slash */
5944                         protect_against_glob = 0;
5945                         goto copy;
5946                 }
5947 #if BASH_PATTERN_SUBST
5948                 else if (*p == '/' && slash) {
5949                         /* stop handling globbing and mark location of slash */
5950                         globbing = slash = 0;
5951                         *p = CTLESC;
5952                 }
5953 #endif
5954                 protect_against_glob = globbing;
5955  copy:
5956                 *q++ = *p++;
5957         }
5958         *q = '\0';
5959         if (flag & RMESCAPE_GROW) {
5960                 expdest = r;
5961                 STADJUST(q - r + 1, expdest);
5962         }
5963         return r;
5964 }
5965 #define pmatch(a, b) !fnmatch((a), (b), 0)
5966
5967 /*
5968  * Prepare a pattern for a expmeta (internal glob(3)) call.
5969  *
5970  * Returns an stalloced string.
5971  */
5972 static char *
5973 preglob(const char *pattern, int flag)
5974 {
5975         return rmescapes((char *)pattern, flag | RMESCAPE_GLOB);
5976 }
5977
5978 /*
5979  * Put a string on the stack.
5980  */
5981 static void
5982 memtodest(const char *p, size_t len, int syntax, int quotes)
5983 {
5984         char *q;
5985
5986         if (!len)
5987                 return;
5988
5989         q = makestrspace((quotes & QUOTES_ESC) ? len * 2 : len, expdest);
5990
5991         do {
5992                 unsigned char c = *p++;
5993                 if (c) {
5994                         if (quotes & QUOTES_ESC) {
5995                                 int n = SIT(c, syntax);
5996                                 if (n == CCTL
5997                                  || (((quotes & EXP_FULL) || syntax != BASESYNTAX)
5998                                      && n == CBACK
5999                                     )
6000                                 ) {
6001                                         USTPUTC(CTLESC, q);
6002                                 }
6003                         }
6004                 } else if (!(quotes & QUOTES_KEEPNUL))
6005                         continue;
6006                 USTPUTC(c, q);
6007         } while (--len);
6008
6009         expdest = q;
6010 }
6011
6012 static size_t
6013 strtodest(const char *p, int syntax, int quotes)
6014 {
6015         size_t len = strlen(p);
6016         memtodest(p, len, syntax, quotes);
6017         return len;
6018 }
6019
6020 /*
6021  * Record the fact that we have to scan this region of the
6022  * string for IFS characters.
6023  */
6024 static void
6025 recordregion(int start, int end, int nulonly)
6026 {
6027         struct ifsregion *ifsp;
6028
6029         if (ifslastp == NULL) {
6030                 ifsp = &ifsfirst;
6031         } else {
6032                 INT_OFF;
6033                 ifsp = ckzalloc(sizeof(*ifsp));
6034                 /*ifsp->next = NULL; - ckzalloc did it */
6035                 ifslastp->next = ifsp;
6036                 INT_ON;
6037         }
6038         ifslastp = ifsp;
6039         ifslastp->begoff = start;
6040         ifslastp->endoff = end;
6041         ifslastp->nulonly = nulonly;
6042 }
6043
6044 static void
6045 removerecordregions(int endoff)
6046 {
6047         if (ifslastp == NULL)
6048                 return;
6049
6050         if (ifsfirst.endoff > endoff) {
6051                 while (ifsfirst.next) {
6052                         struct ifsregion *ifsp;
6053                         INT_OFF;
6054                         ifsp = ifsfirst.next->next;
6055                         free(ifsfirst.next);
6056                         ifsfirst.next = ifsp;
6057                         INT_ON;
6058                 }
6059                 if (ifsfirst.begoff > endoff) {
6060                         ifslastp = NULL;
6061                 } else {
6062                         ifslastp = &ifsfirst;
6063                         ifsfirst.endoff = endoff;
6064                 }
6065                 return;
6066         }
6067
6068         ifslastp = &ifsfirst;
6069         while (ifslastp->next && ifslastp->next->begoff < endoff)
6070                 ifslastp = ifslastp->next;
6071         while (ifslastp->next) {
6072                 struct ifsregion *ifsp;
6073                 INT_OFF;
6074                 ifsp = ifslastp->next->next;
6075                 free(ifslastp->next);
6076                 ifslastp->next = ifsp;
6077                 INT_ON;
6078         }
6079         if (ifslastp->endoff > endoff)
6080                 ifslastp->endoff = endoff;
6081 }
6082
6083 static char *
6084 exptilde(char *startp, char *p, int flags)
6085 {
6086         unsigned char c;
6087         char *name;
6088         struct passwd *pw;
6089         const char *home;
6090         int quotes = flags & QUOTES_ESC;
6091
6092         name = p + 1;
6093
6094         while ((c = *++p) != '\0') {
6095                 switch (c) {
6096                 case CTLESC:
6097                         return startp;
6098                 case CTLQUOTEMARK:
6099                         return startp;
6100                 case ':':
6101                         if (flags & EXP_VARTILDE)
6102                                 goto done;
6103                         break;
6104                 case '/':
6105                 case CTLENDVAR:
6106                         goto done;
6107                 }
6108         }
6109  done:
6110         *p = '\0';
6111         if (*name == '\0') {
6112                 home = lookupvar("HOME");
6113         } else {
6114                 pw = getpwnam(name);
6115                 if (pw == NULL)
6116                         goto lose;
6117                 home = pw->pw_dir;
6118         }
6119         if (!home || !*home)
6120                 goto lose;
6121         *p = c;
6122         strtodest(home, SQSYNTAX, quotes);
6123         return p;
6124  lose:
6125         *p = c;
6126         return startp;
6127 }
6128
6129 /*
6130  * Execute a command inside back quotes.  If it's a builtin command, we
6131  * want to save its output in a block obtained from malloc.  Otherwise
6132  * we fork off a subprocess and get the output of the command via a pipe.
6133  * Should be called with interrupts off.
6134  */
6135 struct backcmd {                /* result of evalbackcmd */
6136         int fd;                 /* file descriptor to read from */
6137         int nleft;              /* number of chars in buffer */
6138         char *buf;              /* buffer */
6139         struct job *jp;         /* job structure for command */
6140 };
6141
6142 /* These forward decls are needed to use "eval" code for backticks handling: */
6143 /* flags in argument to evaltree */
6144 #define EV_EXIT    01           /* exit after evaluating tree */
6145 #define EV_TESTED  02           /* exit status is checked; ignore -e flag */
6146 static int evaltree(union node *, int);
6147
6148 /* An evaltree() which is known to never return.
6149  * Used to use an alias:
6150  * static int evaltreenr(union node *, int) __attribute__((alias("evaltree"),__noreturn__));
6151  * but clang was reported to "transfer" noreturn-ness to evaltree() as well.
6152  */
6153 static ALWAYS_INLINE NORETURN void
6154 evaltreenr(union node *n, int flags)
6155 {
6156         evaltree(n, flags);
6157         bb_unreachable(abort());
6158         /* NOTREACHED */
6159 }
6160
6161 static void FAST_FUNC
6162 evalbackcmd(union node *n, struct backcmd *result)
6163 {
6164         int pip[2];
6165         struct job *jp;
6166
6167         result->fd = -1;
6168         result->buf = NULL;
6169         result->nleft = 0;
6170         result->jp = NULL;
6171         if (n == NULL) {
6172                 goto out;
6173         }
6174
6175         if (pipe(pip) < 0)
6176                 ash_msg_and_raise_error("pipe call failed");
6177         jp = makejob(/*n,*/ 1);
6178         if (forkshell(jp, n, FORK_NOJOB) == 0) {
6179                 /* child */
6180                 FORCE_INT_ON;
6181                 close(pip[0]);
6182                 if (pip[1] != 1) {
6183                         /*close(1);*/
6184                         dup2_or_raise(pip[1], 1);
6185                         close(pip[1]);
6186                 }
6187 /* TODO: eflag clearing makes the following not abort:
6188  *  ash -c 'set -e; z=$(false;echo foo); echo $z'
6189  * which is what bash does (unless it is in POSIX mode).
6190  * dash deleted "eflag = 0" line in the commit
6191  *  Date: Mon, 28 Jun 2010 17:11:58 +1000
6192  *  [EVAL] Don't clear eflag in evalbackcmd
6193  * For now, preserve bash-like behavior, it seems to be somewhat more useful:
6194  */
6195                 eflag = 0;
6196                 ifsfree();
6197                 evaltreenr(n, EV_EXIT);
6198                 /* NOTREACHED */
6199         }
6200         /* parent */
6201         close(pip[1]);
6202         result->fd = pip[0];
6203         result->jp = jp;
6204
6205  out:
6206         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
6207                 result->fd, result->buf, result->nleft, result->jp));
6208 }
6209
6210 /*
6211  * Expand stuff in backwards quotes.
6212  */
6213 static void
6214 expbackq(union node *cmd, int flag)
6215 {
6216         struct backcmd in;
6217         int i;
6218         char buf[128];
6219         char *p;
6220         char *dest;
6221         int startloc;
6222         int syntax = flag & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
6223         struct stackmark smark;
6224
6225         INT_OFF;
6226         startloc = expdest - (char *)stackblock();
6227         pushstackmark(&smark, startloc);
6228         evalbackcmd(cmd, &in);
6229         popstackmark(&smark);
6230
6231         p = in.buf;
6232         i = in.nleft;
6233         if (i == 0)
6234                 goto read;
6235         for (;;) {
6236                 memtodest(p, i, syntax, flag & QUOTES_ESC);
6237  read:
6238                 if (in.fd < 0)
6239                         break;
6240                 i = nonblock_immune_read(in.fd, buf, sizeof(buf));
6241                 TRACE(("expbackq: read returns %d\n", i));
6242                 if (i <= 0)
6243                         break;
6244                 p = buf;
6245         }
6246
6247         free(in.buf);
6248         if (in.fd >= 0) {
6249                 close(in.fd);
6250                 back_exitstatus = waitforjob(in.jp);
6251         }
6252         INT_ON;
6253
6254         /* Eat all trailing newlines */
6255         dest = expdest;
6256         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
6257                 STUNPUTC(dest);
6258         expdest = dest;
6259
6260         if (!(flag & EXP_QUOTED))
6261                 recordregion(startloc, dest - (char *)stackblock(), 0);
6262         TRACE(("evalbackq: size:%d:'%.*s'\n",
6263                 (int)((dest - (char *)stackblock()) - startloc),
6264                 (int)((dest - (char *)stackblock()) - startloc),
6265                 stackblock() + startloc));
6266 }
6267
6268 #if ENABLE_FEATURE_SH_MATH
6269 /*
6270  * Expand arithmetic expression.  Backup to start of expression,
6271  * evaluate, place result in (backed up) result, adjust string position.
6272  */
6273 static void
6274 expari(int flag)
6275 {
6276         char *p, *start;
6277         int begoff;
6278         int len;
6279
6280         /* ifsfree(); */
6281
6282         /*
6283          * This routine is slightly over-complicated for
6284          * efficiency.  Next we scan backwards looking for the
6285          * start of arithmetic.
6286          */
6287         start = stackblock();
6288         p = expdest - 1;
6289         *p = '\0';
6290         p--;
6291         while (1) {
6292                 int esc;
6293
6294                 while ((unsigned char)*p != CTLARI) {
6295                         p--;
6296 #if DEBUG
6297                         if (p < start) {
6298                                 ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
6299                         }
6300 #endif
6301                 }
6302
6303                 esc = esclen(start, p);
6304                 if (!(esc % 2)) {
6305                         break;
6306                 }
6307
6308                 p -= esc + 1;
6309         }
6310
6311         begoff = p - start;
6312
6313         removerecordregions(begoff);
6314
6315         expdest = p;
6316
6317         if (flag & QUOTES_ESC)
6318                 rmescapes(p + 1, 0);
6319
6320         len = cvtnum(ash_arith(p + 1));
6321
6322         if (!(flag & EXP_QUOTED))
6323                 recordregion(begoff, begoff + len, 0);
6324 }
6325 #endif
6326
6327 /* argstr needs it */
6328 static char *evalvar(char *p, int flags);
6329
6330 /*
6331  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
6332  * characters to allow for further processing.  Otherwise treat
6333  * $@ like $* since no splitting will be performed.
6334  */
6335 static void
6336 argstr(char *p, int flags)
6337 {
6338         static const char spclchars[] ALIGN1 = {
6339                 '=',
6340                 ':',
6341                 CTLQUOTEMARK,
6342                 CTLENDVAR,
6343                 CTLESC,
6344                 CTLVAR,
6345                 CTLBACKQ,
6346 #if ENABLE_FEATURE_SH_MATH
6347                 CTLENDARI,
6348 #endif
6349                 '\0'
6350         };
6351         const char *reject = spclchars;
6352         int breakall = (flags & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
6353         int inquotes;
6354         size_t length;
6355         int startloc;
6356
6357         if (!(flags & EXP_VARTILDE)) {
6358                 reject += 2;
6359         } else if (flags & EXP_VARTILDE2) {
6360                 reject++;
6361         }
6362         inquotes = 0;
6363         length = 0;
6364         if (flags & EXP_TILDE) {
6365                 char *q;
6366
6367                 flags &= ~EXP_TILDE;
6368  tilde:
6369                 q = p;
6370                 if (*q == '~')
6371                         p = exptilde(p, q, flags);
6372         }
6373  start:
6374         startloc = expdest - (char *)stackblock();
6375         for (;;) {
6376                 unsigned char c;
6377
6378                 length += strcspn(p + length, reject);
6379                 c = p[length];
6380                 if (c) {
6381                         if (!(c & 0x80)
6382                         IF_FEATURE_SH_MATH(|| c == CTLENDARI)
6383                         ) {
6384                                 /* c == '=' || c == ':' || c == CTLENDARI */
6385                                 length++;
6386                         }
6387                 }
6388                 if (length > 0) {
6389                         int newloc;
6390                         expdest = stack_nputstr(p, length, expdest);
6391                         newloc = expdest - (char *)stackblock();
6392                         if (breakall && !inquotes && newloc > startloc) {
6393                                 recordregion(startloc, newloc, 0);
6394                         }
6395                         startloc = newloc;
6396                 }
6397                 p += length + 1;
6398                 length = 0;
6399
6400                 switch (c) {
6401                 case '\0':
6402                         goto breakloop;
6403                 case '=':
6404                         if (flags & EXP_VARTILDE2) {
6405                                 p--;
6406                                 continue;
6407                         }
6408                         flags |= EXP_VARTILDE2;
6409                         reject++;
6410                         /* fall through */
6411                 case ':':
6412                         /*
6413                          * sort of a hack - expand tildes in variable
6414                          * assignments (after the first '=' and after ':'s).
6415                          */
6416                         if (*--p == '~') {
6417                                 goto tilde;
6418                         }
6419                         continue;
6420                 }
6421
6422                 switch (c) {
6423                 case CTLENDVAR: /* ??? */
6424                         goto breakloop;
6425                 case CTLQUOTEMARK:
6426                         inquotes ^= EXP_QUOTED;
6427                         /* "$@" syntax adherence hack */
6428                         if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
6429                                 p = evalvar(p + 1, flags | inquotes) + 1;
6430                                 goto start;
6431                         }
6432  addquote:
6433                         if (flags & QUOTES_ESC) {
6434                                 p--;
6435                                 length++;
6436                                 startloc++;
6437                         }
6438                         break;
6439                 case CTLESC:
6440                         startloc++;
6441                         length++;
6442
6443                         /*
6444                          * Quoted parameter expansion pattern: remove quote
6445                          * unless inside inner quotes or we have a literal
6446                          * backslash.
6447                          */
6448                         if (((flags | inquotes) & (EXP_QPAT | EXP_QUOTED)) ==
6449                             EXP_QPAT && *p != '\\')
6450                                 break;
6451
6452                         goto addquote;
6453                 case CTLVAR:
6454                         TRACE(("argstr: evalvar('%s')\n", p));
6455                         p = evalvar(p, flags | inquotes);
6456                         TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
6457                         goto start;
6458                 case CTLBACKQ:
6459                         expbackq(argbackq->n, flags | inquotes);
6460                         argbackq = argbackq->next;
6461                         goto start;
6462 #if ENABLE_FEATURE_SH_MATH
6463                 case CTLENDARI:
6464                         p--;
6465                         expari(flags | inquotes);
6466                         goto start;
6467 #endif
6468                 }
6469         }
6470  breakloop: ;
6471 }
6472
6473 static char *
6474 scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
6475                 char *pattern, int quotes, int zero)
6476 {
6477         char *loc, *loc2;
6478         char c;
6479
6480         loc = startp;
6481         loc2 = rmesc;
6482         do {
6483                 int match;
6484                 const char *s = loc2;
6485
6486                 c = *loc2;
6487                 if (zero) {
6488                         *loc2 = '\0';
6489                         s = rmesc;
6490                 }
6491                 match = pmatch(pattern, s);
6492
6493                 *loc2 = c;
6494                 if (match)
6495                         return loc;
6496                 if (quotes && (unsigned char)*loc == CTLESC)
6497                         loc++;
6498                 loc++;
6499                 loc2++;
6500         } while (c);
6501         return NULL;
6502 }
6503
6504 static char *
6505 scanright(char *startp, char *rmesc, char *rmescend,
6506                 char *pattern, int quotes, int match_at_start)
6507 {
6508 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6509         int try2optimize = match_at_start;
6510 #endif
6511         int esc = 0;
6512         char *loc;
6513         char *loc2;
6514
6515         /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
6516          * startp="escaped_value_of_v" rmesc="raw_value_of_v"
6517          * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
6518          * Logic:
6519          * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
6520          * and on each iteration they go back two/one char until they reach the beginning.
6521          * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
6522          */
6523         /* TODO: document in what other circumstances we are called. */
6524
6525         for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
6526                 int match;
6527                 char c = *loc2;
6528                 const char *s = loc2;
6529                 if (match_at_start) {
6530                         *loc2 = '\0';
6531                         s = rmesc;
6532                 }
6533                 match = pmatch(pattern, s);
6534                 //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
6535                 *loc2 = c;
6536                 if (match)
6537                         return loc;
6538 #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
6539                 if (try2optimize) {
6540                         /* Maybe we can optimize this:
6541                          * if pattern ends with unescaped *, we can avoid checking
6542                          * shorter strings: if "foo*" doesn't match "raw_value_of_v",
6543                          * it won't match truncated "raw_value_of_" strings too.
6544                          */
6545                         unsigned plen = strlen(pattern);
6546                         /* Does it end with "*"? */
6547                         if (plen != 0 && pattern[--plen] == '*') {
6548                                 /* "xxxx*" is not escaped */
6549                                 /* "xxx\*" is escaped */
6550                                 /* "xx\\*" is not escaped */
6551                                 /* "x\\\*" is escaped */
6552                                 int slashes = 0;
6553                                 while (plen != 0 && pattern[--plen] == '\\')
6554                                         slashes++;
6555                                 if (!(slashes & 1))
6556                                         break; /* ends with unescaped "*" */
6557                         }
6558                         try2optimize = 0;
6559                 }
6560 #endif
6561                 loc--;
6562                 if (quotes) {
6563                         if (--esc < 0) {
6564                                 esc = esclen(startp, loc);
6565                         }
6566                         if (esc % 2) {
6567                                 esc--;
6568                                 loc--;
6569                         }
6570                 }
6571         }
6572         return NULL;
6573 }
6574
6575 static void varunset(const char *, const char *, const char *, int) NORETURN;
6576 static void
6577 varunset(const char *end, const char *var, const char *umsg, int varflags)
6578 {
6579         const char *msg;
6580         const char *tail;
6581
6582         tail = nullstr;
6583         msg = "parameter not set";
6584         if (umsg) {
6585                 if ((unsigned char)*end == CTLENDVAR) {
6586                         if (varflags & VSNUL)
6587                                 tail = " or null";
6588                 } else {
6589                         msg = umsg;
6590                 }
6591         }
6592         ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
6593 }
6594
6595 static const char *
6596 subevalvar(char *p, char *varname, int strloc, int subtype,
6597                 int startloc, int varflags, int flag)
6598 {
6599         struct nodelist *saveargbackq = argbackq;
6600         int quotes = flag & QUOTES_ESC;
6601         char *startp;
6602         char *loc;
6603         char *rmesc, *rmescend;
6604         char *str;
6605         int amount, resetloc;
6606         IF_BASH_PATTERN_SUBST(int workloc;)
6607         IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6608         int zero;
6609         char *(*scan)(char*, char*, char*, char*, int, int);
6610
6611         //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
6612         //              p, varname, strloc, subtype, startloc, varflags, quotes);
6613
6614         argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
6615                         (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0)
6616         );
6617         STPUTC('\0', expdest);
6618         argbackq = saveargbackq;
6619         startp = (char *)stackblock() + startloc;
6620
6621         switch (subtype) {
6622         case VSASSIGN:
6623                 setvar0(varname, startp);
6624                 amount = startp - expdest;
6625                 STADJUST(amount, expdest);
6626                 return startp;
6627
6628         case VSQUESTION:
6629                 varunset(p, varname, startp, varflags);
6630                 /* NOTREACHED */
6631
6632 #if BASH_SUBSTR
6633         case VSSUBSTR: {
6634                 int pos, len, orig_len;
6635                 char *colon;
6636
6637                 loc = str = stackblock() + strloc;
6638
6639 # if !ENABLE_FEATURE_SH_MATH
6640 #  define ash_arith number
6641 # endif
6642                 /* Read POS in ${var:POS:LEN} */
6643                 colon = strchr(loc, ':');
6644                 if (colon) *colon = '\0';
6645                 pos = ash_arith(loc);
6646                 if (colon) *colon = ':';
6647
6648                 /* Read LEN in ${var:POS:LEN} */
6649                 len = str - startp - 1;
6650                 /* *loc != '\0', guaranteed by parser */
6651                 if (quotes) {
6652                         char *ptr;
6653
6654                         /* Adjust the length by the number of escapes */
6655                         for (ptr = startp; ptr < (str - 1); ptr++) {
6656                                 if ((unsigned char)*ptr == CTLESC) {
6657                                         len--;
6658                                         ptr++;
6659                                 }
6660                         }
6661                 }
6662                 orig_len = len;
6663                 if (*loc++ == ':') {
6664                         /* ${var::LEN} */
6665                         len = ash_arith(loc);
6666                 } else {
6667                         /* Skip POS in ${var:POS:LEN} */
6668                         len = orig_len;
6669                         while (*loc && *loc != ':') {
6670                                 loc++;
6671                         }
6672                         if (*loc++ == ':') {
6673                                 len = ash_arith(loc);
6674                         }
6675                 }
6676 #  undef ash_arith
6677
6678                 if (pos < 0) {
6679                         /* ${VAR:$((-n)):l} starts n chars from the end */
6680                         pos = orig_len + pos;
6681                 }
6682                 if ((unsigned)pos >= orig_len) {
6683                         /* apart from obvious ${VAR:999999:l},
6684                          * covers ${VAR:$((-9999999)):l} - result is ""
6685                          * (bash compat)
6686                          */
6687                         pos = 0;
6688                         len = 0;
6689                 }
6690                 if (len < 0) {
6691                         /* ${VAR:N:-M} sets LEN to strlen()-M */
6692                         len = (orig_len - pos) + len;
6693                 }
6694                 if ((unsigned)len > (orig_len - pos))
6695                         len = orig_len - pos;
6696
6697                 for (str = startp; pos; str++, pos--) {
6698                         if (quotes && (unsigned char)*str == CTLESC)
6699                                 str++;
6700                 }
6701                 for (loc = startp; len; len--) {
6702                         if (quotes && (unsigned char)*str == CTLESC)
6703                                 *loc++ = *str++;
6704                         *loc++ = *str++;
6705                 }
6706                 *loc = '\0';
6707                 amount = loc - expdest;
6708                 STADJUST(amount, expdest);
6709                 return loc;
6710         }
6711 #endif /* BASH_SUBSTR */
6712         }
6713
6714         resetloc = expdest - (char *)stackblock();
6715
6716 #if BASH_PATTERN_SUBST
6717         /* We'll comeback here if we grow the stack while handling
6718          * a VSREPLACE or VSREPLACEALL, since our pointers into the
6719          * stack will need rebasing, and we'll need to remove our work
6720          * areas each time
6721          */
6722  restart:
6723 #endif
6724
6725         amount = expdest - ((char *)stackblock() + resetloc);
6726         STADJUST(-amount, expdest);
6727         startp = (char *)stackblock() + startloc;
6728
6729         rmesc = startp;
6730         rmescend = (char *)stackblock() + strloc;
6731         if (quotes) {
6732                 rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
6733                 if (rmesc != startp) {
6734                         rmescend = expdest;
6735                         startp = (char *)stackblock() + startloc;
6736                 }
6737         }
6738         rmescend--;
6739         str = (char *)stackblock() + strloc;
6740         /*
6741          * Example: v='a\bc'; echo ${v/\\b/_\\_\z_}
6742          * The result is a_\_z_c (not a\_\_z_c)!
6743          *
6744          * The search pattern and replace string treat backslashes differently!
6745          * RMESCAPE_SLASH causes preglob to work differently on the pattern
6746          * and string.  It's only used on the first call.
6747          */
6748         preglob(str, IF_BASH_PATTERN_SUBST(
6749                 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6750                         RMESCAPE_SLASH : ) 0);
6751
6752 #if BASH_PATTERN_SUBST
6753         workloc = expdest - (char *)stackblock();
6754         if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6755                 int len;
6756                 char *idx, *end;
6757
6758                 if (!repl) {
6759                         repl = strchr(str, CTLESC);
6760                         if (repl)
6761                                 *repl++ = '\0';
6762                         else
6763                                 repl = nullstr;
6764                 }
6765                 //bb_error_msg("str:'%s' repl:'%s'", str, repl);
6766
6767                 /* If there's no pattern to match, return the expansion unmolested */
6768                 if (str[0] == '\0')
6769                         return NULL;
6770
6771                 len = 0;
6772                 idx = startp;
6773                 end = str - 1;
6774                 while (idx < end) {
6775  try_to_match:
6776                         loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6777                         //bb_error_msg("scanright('%s'):'%s'", str, loc);
6778                         if (!loc) {
6779                                 /* No match, advance */
6780                                 char *restart_detect = stackblock();
6781  skip_matching:
6782                                 STPUTC(*idx, expdest);
6783                                 if (quotes && (unsigned char)*idx == CTLESC) {
6784                                         idx++;
6785                                         len++;
6786                                         STPUTC(*idx, expdest);
6787                                 }
6788                                 if (stackblock() != restart_detect)
6789                                         goto restart;
6790                                 idx++;
6791                                 len++;
6792                                 rmesc++;
6793                                 /* continue; - prone to quadratic behavior, smarter code: */
6794                                 if (idx >= end)
6795                                         break;
6796                                 if (str[0] == '*') {
6797                                         /* Pattern is "*foo". If "*foo" does not match "long_string",
6798                                          * it would never match "ong_string" etc, no point in trying.
6799                                          */
6800                                         goto skip_matching;
6801                                 }
6802                                 goto try_to_match;
6803                         }
6804
6805                         if (subtype == VSREPLACEALL) {
6806                                 while (idx < loc) {
6807                                         if (quotes && (unsigned char)*idx == CTLESC)
6808                                                 idx++;
6809                                         idx++;
6810                                         rmesc++;
6811                                 }
6812                         } else {
6813                                 idx = loc;
6814                         }
6815
6816                         //bb_error_msg("repl:'%s'", repl);
6817                         for (loc = (char*)repl; *loc; loc++) {
6818                                 char *restart_detect = stackblock();
6819                                 if (quotes && *loc == '\\') {
6820                                         STPUTC(CTLESC, expdest);
6821                                         len++;
6822                                 }
6823                                 STPUTC(*loc, expdest);
6824                                 if (stackblock() != restart_detect)
6825                                         goto restart;
6826                                 len++;
6827                         }
6828
6829                         if (subtype == VSREPLACE) {
6830                                 //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
6831                                 while (*idx) {
6832                                         char *restart_detect = stackblock();
6833                                         STPUTC(*idx, expdest);
6834                                         if (stackblock() != restart_detect)
6835                                                 goto restart;
6836                                         len++;
6837                                         idx++;
6838                                 }
6839                                 break;
6840                         }
6841                 }
6842
6843                 /* We've put the replaced text into a buffer at workloc, now
6844                  * move it to the right place and adjust the stack.
6845                  */
6846                 STPUTC('\0', expdest);
6847                 startp = (char *)stackblock() + startloc;
6848                 memmove(startp, (char *)stackblock() + workloc, len + 1);
6849                 //bb_error_msg("startp:'%s'", startp);
6850                 amount = expdest - (startp + len);
6851                 STADJUST(-amount, expdest);
6852                 return startp;
6853         }
6854 #endif /* BASH_PATTERN_SUBST */
6855
6856         subtype -= VSTRIMRIGHT;
6857 #if DEBUG
6858         if (subtype < 0 || subtype > 7)
6859                 abort();
6860 #endif
6861         /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
6862         zero = subtype >> 1;
6863         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
6864         scan = (subtype & 1) ^ zero ? scanleft : scanright;
6865
6866         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
6867         if (loc) {
6868                 if (zero) {
6869                         memmove(startp, loc, str - loc);
6870                         loc = startp + (str - loc) - 1;
6871                 }
6872                 *loc = '\0';
6873                 amount = loc - expdest;
6874                 STADJUST(amount, expdest);
6875         }
6876         return loc;
6877 }
6878
6879 /*
6880  * Add the value of a specialized variable to the stack string.
6881  * name parameter (examples):
6882  * ash -c 'echo $1'      name:'1='
6883  * ash -c 'echo $qwe'    name:'qwe='
6884  * ash -c 'echo $$'      name:'$='
6885  * ash -c 'echo ${$}'    name:'$='
6886  * ash -c 'echo ${$##q}' name:'$=q'
6887  * ash -c 'echo ${#$}'   name:'$='
6888  * note: examples with bad shell syntax:
6889  * ash -c 'echo ${#$1}'  name:'$=1'
6890  * ash -c 'echo ${#1#}'  name:'1=#'
6891  */
6892 static NOINLINE ssize_t
6893 varvalue(char *name, int varflags, int flags, int *quotedp)
6894 {
6895         const char *p;
6896         int num;
6897         int i;
6898         ssize_t len = 0;
6899         int sep;
6900         int quoted = *quotedp;
6901         int subtype = varflags & VSTYPE;
6902         int discard = subtype == VSPLUS || subtype == VSLENGTH;
6903         int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
6904         int syntax;
6905
6906         sep = (flags & EXP_FULL) << CHAR_BIT;
6907         syntax = quoted ? DQSYNTAX : BASESYNTAX;
6908
6909         switch (*name) {
6910         case '$':
6911                 num = rootpid;
6912                 goto numvar;
6913         case '?':
6914                 num = exitstatus;
6915                 goto numvar;
6916         case '#':
6917                 num = shellparam.nparam;
6918                 goto numvar;
6919         case '!':
6920                 num = backgndpid;
6921                 if (num == 0)
6922                         return -1;
6923  numvar:
6924                 len = cvtnum(num);
6925                 goto check_1char_name;
6926         case '-':
6927                 expdest = makestrspace(NOPTS, expdest);
6928                 for (i = NOPTS - 1; i >= 0; i--) {
6929                         if (optlist[i]) {
6930                                 USTPUTC(optletters(i), expdest);
6931                                 len++;
6932                         }
6933                 }
6934  check_1char_name:
6935 #if 0
6936                 /* handles cases similar to ${#$1} */
6937                 if (name[2] != '\0')
6938                         raise_error_syntax("bad substitution");
6939 #endif
6940                 break;
6941         case '@':
6942                 if (quoted && sep)
6943                         goto param;
6944                 /* fall through */
6945         case '*': {
6946                 char **ap;
6947                 char sepc;
6948
6949                 if (quoted)
6950                         sep = 0;
6951                 sep |= ifsset() ? ifsval()[0] : ' ';
6952  param:
6953                 sepc = sep;
6954                 *quotedp = !sepc;
6955                 ap = shellparam.p;
6956                 if (!ap)
6957                         return -1;
6958                 while ((p = *ap++) != NULL) {
6959                         len += strtodest(p, syntax, quotes);
6960
6961                         if (*ap && sep) {
6962                                 len++;
6963                                 memtodest(&sepc, 1, syntax, quotes);
6964                         }
6965                 }
6966                 break;
6967         } /* case '*' */
6968         case '0':
6969         case '1':
6970         case '2':
6971         case '3':
6972         case '4':
6973         case '5':
6974         case '6':
6975         case '7':
6976         case '8':
6977         case '9':
6978                 num = atoi(name); /* number(name) fails on ${N#str} etc */
6979                 if (num < 0 || num > shellparam.nparam)
6980                         return -1;
6981                 p = num ? shellparam.p[num - 1] : arg0;
6982                 goto value;
6983         default:
6984                 /* NB: name has form "VAR=..." */
6985                 p = lookupvar(name);
6986  value:
6987                 if (!p)
6988                         return -1;
6989
6990                 len = strtodest(p, syntax, quotes);
6991 #if ENABLE_UNICODE_SUPPORT
6992                 if (subtype == VSLENGTH && len > 0) {
6993                         reinit_unicode_for_ash();
6994                         if (unicode_status == UNICODE_ON) {
6995                                 STADJUST(-len, expdest);
6996                                 discard = 0;
6997                                 len = unicode_strlen(p);
6998                         }
6999                 }
7000 #endif
7001                 break;
7002         }
7003
7004         if (discard)
7005                 STADJUST(-len, expdest);
7006         return len;
7007 }
7008
7009 /*
7010  * Expand a variable, and return a pointer to the next character in the
7011  * input string.
7012  */
7013 static char *
7014 evalvar(char *p, int flag)
7015 {
7016         char varflags;
7017         char subtype;
7018         int quoted;
7019         char easy;
7020         char *var;
7021         int patloc;
7022         int startloc;
7023         ssize_t varlen;
7024
7025         varflags = (unsigned char) *p++;
7026         subtype = varflags & VSTYPE;
7027
7028         if (!subtype)
7029                 raise_error_syntax("bad substitution");
7030
7031         quoted = flag & EXP_QUOTED;
7032         var = p;
7033         easy = (!quoted || (*var == '@' && shellparam.nparam));
7034         startloc = expdest - (char *)stackblock();
7035         p = strchr(p, '=') + 1; //TODO: use var_end(p)?
7036
7037  again:
7038         varlen = varvalue(var, varflags, flag, &quoted);
7039         if (varflags & VSNUL)
7040                 varlen--;
7041
7042         if (subtype == VSPLUS) {
7043                 varlen = -1 - varlen;
7044                 goto vsplus;
7045         }
7046
7047         if (subtype == VSMINUS) {
7048  vsplus:
7049                 if (varlen < 0) {
7050                         argstr(
7051                                 p,
7052                                 flag | EXP_TILDE | EXP_WORD
7053                         );
7054                         goto end;
7055                 }
7056                 goto record;
7057         }
7058
7059         if (subtype == VSASSIGN || subtype == VSQUESTION) {
7060                 if (varlen >= 0)
7061                         goto record;
7062
7063                 subevalvar(p, var, 0, subtype, startloc, varflags,
7064                            flag & ~QUOTES_ESC);
7065                 varflags &= ~VSNUL;
7066                 /*
7067                  * Remove any recorded regions beyond
7068                  * start of variable
7069                  */
7070                 removerecordregions(startloc);
7071                 goto again;
7072         }
7073
7074         if (varlen < 0 && uflag)
7075                 varunset(p, var, 0, 0);
7076
7077         if (subtype == VSLENGTH) {
7078                 cvtnum(varlen > 0 ? varlen : 0);
7079                 goto record;
7080         }
7081
7082         if (subtype == VSNORMAL) {
7083  record:
7084                 if (!easy)
7085                         goto end;
7086                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
7087                 goto end;
7088         }
7089
7090 #if DEBUG
7091         switch (subtype) {
7092         case VSTRIMLEFT:
7093         case VSTRIMLEFTMAX:
7094         case VSTRIMRIGHT:
7095         case VSTRIMRIGHTMAX:
7096 #if BASH_SUBSTR
7097         case VSSUBSTR:
7098 #endif
7099 #if BASH_PATTERN_SUBST
7100         case VSREPLACE:
7101         case VSREPLACEALL:
7102 #endif
7103                 break;
7104         default:
7105                 abort();
7106         }
7107 #endif
7108
7109         if (varlen >= 0) {
7110                 /*
7111                  * Terminate the string and start recording the pattern
7112                  * right after it
7113                  */
7114                 STPUTC('\0', expdest);
7115                 patloc = expdest - (char *)stackblock();
7116                 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
7117                                 startloc, varflags, flag)) {
7118                         int amount = expdest - (
7119                                 (char *)stackblock() + patloc - 1
7120                         );
7121                         STADJUST(-amount, expdest);
7122                 }
7123                 /* Remove any recorded regions beyond start of variable */
7124                 removerecordregions(startloc);
7125                 goto record;
7126         }
7127
7128  end:
7129         if (subtype != VSNORMAL) {      /* skip to end of alternative */
7130                 int nesting = 1;
7131                 for (;;) {
7132                         unsigned char c = *p++;
7133                         if (c == CTLESC)
7134                                 p++;
7135                         else if (c == CTLBACKQ) {
7136                                 if (varlen >= 0)
7137                                         argbackq = argbackq->next;
7138                         } else if (c == CTLVAR) {
7139                                 if ((*p++ & VSTYPE) != VSNORMAL)
7140                                         nesting++;
7141                         } else if (c == CTLENDVAR) {
7142                                 if (--nesting == 0)
7143                                         break;
7144                         }
7145                 }
7146         }
7147         return p;
7148 }
7149
7150 /*
7151  * Add a file name to the list.
7152  */
7153 static void
7154 addfname(const char *name)
7155 {
7156         struct strlist *sp;
7157
7158         sp = stzalloc(sizeof(*sp));
7159         sp->text = sstrdup(name);
7160         *exparg.lastp = sp;
7161         exparg.lastp = &sp->next;
7162 }
7163
7164 /* Avoid glob() (and thus, stat() et al) for words like "echo" */
7165 static int
7166 hasmeta(const char *p)
7167 {
7168         static const char chars[] ALIGN1 = {
7169                 '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0
7170         };
7171
7172         for (;;) {
7173                 p = strpbrk(p, chars);
7174                 if (!p)
7175                         break;
7176                 switch ((unsigned char) *p) {
7177                 case CTLQUOTEMARK:
7178                         for (;;) {
7179                                 p++;
7180                                 if (*p == CTLQUOTEMARK)
7181                                         break;
7182                                 if (*p == CTLESC)
7183                                         p++;
7184                                 if (*p == '\0') /* huh? */
7185                                         return 0;
7186                         }
7187                         break;
7188                 case '\\':
7189                 case CTLESC:
7190                         p++;
7191                         if (*p == '\0')
7192                                 return 0;
7193                         break;
7194                 case '[':
7195                         if (!strchr(p + 1, ']')) {
7196                                 /* It's not a properly closed [] pattern,
7197                                  * but other metas may follow. Continue checking.
7198                                  * my[file* _is_ globbed by bash
7199                                  * and matches filenames like "my[file1".
7200                                  */
7201                                 break;
7202                         }
7203                         /* fallthrough */
7204                 default:
7205                 /* case '*': */
7206                 /* case '?': */
7207                         return 1;
7208                 }
7209                 p++;
7210         }
7211
7212         return 0;
7213 }
7214
7215 /* If we want to use glob() from libc... */
7216 #if !ENABLE_ASH_INTERNAL_GLOB
7217
7218 /* Add the result of glob() to the list */
7219 static void
7220 addglob(const glob_t *pglob)
7221 {
7222         char **p = pglob->gl_pathv;
7223
7224         do {
7225                 addfname(*p);
7226         } while (*++p);
7227 }
7228 static void
7229 expandmeta(struct strlist *str /*, int flag*/)
7230 {
7231         /* TODO - EXP_REDIR */
7232
7233         while (str) {
7234                 char *p;
7235                 glob_t pglob;
7236                 int i;
7237
7238                 if (fflag)
7239                         goto nometa;
7240
7241                 if (!hasmeta(str->text))
7242                         goto nometa;
7243
7244                 INT_OFF;
7245                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7246 // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match
7247 // GLOB_NOCHECK: if no match, return unchanged pattern (sans \* escapes?)
7248 //
7249 // glibc 2.24.90 glob(GLOB_NOMAGIC) does not remove backslashes used for escaping:
7250 // if you pass it "file\?", it returns "file\?", not "file?", if no match.
7251 // Which means you need to unescape the string, right? Not so fast:
7252 // if there _is_ a file named "file\?" (with backslash), it is returned
7253 // as "file\?" too (whichever pattern you used to find it, say, "file*").
7254 // You DON'T KNOW by looking at the result whether you need to unescape it.
7255 //
7256 // Worse, globbing of "file\?" in a directory with two files, "file?" and "file\?",
7257 // returns "file\?" - which is WRONG: "file\?" pattern matches "file?" file.
7258 // Without GLOB_NOMAGIC, this works correctly ("file?" is returned as a match).
7259 // With GLOB_NOMAGIC | GLOB_NOCHECK, this also works correctly.
7260 //              i = glob(p, GLOB_NOMAGIC | GLOB_NOCHECK, NULL, &pglob);
7261 //              i = glob(p, GLOB_NOMAGIC, NULL, &pglob);
7262                 i = glob(p, 0, NULL, &pglob);
7263                 //bb_error_msg("glob('%s'):%d '%s'...", p, i, pglob.gl_pathv ? pglob.gl_pathv[0] : "-");
7264                 if (p != str->text)
7265                         free(p);
7266                 switch (i) {
7267                 case 0:
7268 #if 0 // glibc 2.24.90 bug? Patterns like "*/file", when match, don't set GLOB_MAGCHAR
7269                         /* GLOB_MAGCHAR is set if *?[ chars were seen (GNU) */
7270                         if (!(pglob.gl_flags & GLOB_MAGCHAR))
7271                                 goto nometa2;
7272 #endif
7273                         addglob(&pglob);
7274                         globfree(&pglob);
7275                         INT_ON;
7276                         break;
7277                 case GLOB_NOMATCH:
7278  //nometa2:
7279                         globfree(&pglob);
7280                         INT_ON;
7281  nometa:
7282                         *exparg.lastp = str;
7283                         rmescapes(str->text, 0);
7284                         exparg.lastp = &str->next;
7285                         break;
7286                 default:        /* GLOB_NOSPACE */
7287                         globfree(&pglob);
7288                         INT_ON;
7289                         ash_msg_and_raise_error(bb_msg_memory_exhausted);
7290                 }
7291                 str = str->next;
7292         }
7293 }
7294
7295 #else
7296 /* ENABLE_ASH_INTERNAL_GLOB: Homegrown globbing code. (dash also has both, uses homegrown one.) */
7297
7298 /*
7299  * Do metacharacter (i.e. *, ?, [...]) expansion.
7300  */
7301 static void
7302 expmeta(char *expdir, char *enddir, char *name)
7303 {
7304         char *p;
7305         const char *cp;
7306         char *start;
7307         char *endname;
7308         int metaflag;
7309         struct stat statb;
7310         DIR *dirp;
7311         struct dirent *dp;
7312         int atend;
7313         int matchdot;
7314         int esc;
7315
7316         metaflag = 0;
7317         start = name;
7318         for (p = name; esc = 0, *p; p += esc + 1) {
7319                 if (*p == '*' || *p == '?')
7320                         metaflag = 1;
7321                 else if (*p == '[') {
7322                         char *q = p + 1;
7323                         if (*q == '!')
7324                                 q++;
7325                         for (;;) {
7326                                 if (*q == '\\')
7327                                         q++;
7328                                 if (*q == '/' || *q == '\0')
7329                                         break;
7330                                 if (*++q == ']') {
7331                                         metaflag = 1;
7332                                         break;
7333                                 }
7334                         }
7335                 } else {
7336                         if (*p == '\\')
7337                                 esc++;
7338                         if (p[esc] == '/') {
7339                                 if (metaflag)
7340                                         break;
7341                                 start = p + esc + 1;
7342                         }
7343                 }
7344         }
7345         if (metaflag == 0) {    /* we've reached the end of the file name */
7346                 if (enddir != expdir)
7347                         metaflag++;
7348                 p = name;
7349                 do {
7350                         if (*p == '\\')
7351                                 p++;
7352                         *enddir++ = *p;
7353                 } while (*p++);
7354                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
7355                         addfname(expdir);
7356                 return;
7357         }
7358         endname = p;
7359         if (name < start) {
7360                 p = name;
7361                 do {
7362                         if (*p == '\\')
7363                                 p++;
7364                         *enddir++ = *p++;
7365                 } while (p < start);
7366         }
7367         if (enddir == expdir) {
7368                 cp = ".";
7369         } else if (enddir == expdir + 1 && *expdir == '/') {
7370                 cp = "/";
7371         } else {
7372                 cp = expdir;
7373                 enddir[-1] = '\0';
7374         }
7375         dirp = opendir(cp);
7376         if (dirp == NULL)
7377                 return;
7378         if (enddir != expdir)
7379                 enddir[-1] = '/';
7380         if (*endname == 0) {
7381                 atend = 1;
7382         } else {
7383                 atend = 0;
7384                 *endname = '\0';
7385                 endname += esc + 1;
7386         }
7387         matchdot = 0;
7388         p = start;
7389         if (*p == '\\')
7390                 p++;
7391         if (*p == '.')
7392                 matchdot++;
7393         while (!pending_int && (dp = readdir(dirp)) != NULL) {
7394                 if (dp->d_name[0] == '.' && !matchdot)
7395                         continue;
7396                 if (pmatch(start, dp->d_name)) {
7397                         if (atend) {
7398                                 strcpy(enddir, dp->d_name);
7399                                 addfname(expdir);
7400                         } else {
7401                                 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
7402                                         continue;
7403                                 p[-1] = '/';
7404                                 expmeta(expdir, p, endname);
7405                         }
7406                 }
7407         }
7408         closedir(dirp);
7409         if (!atend)
7410                 endname[-esc - 1] = esc ? '\\' : '/';
7411 }
7412
7413 static struct strlist *
7414 msort(struct strlist *list, int len)
7415 {
7416         struct strlist *p, *q = NULL;
7417         struct strlist **lpp;
7418         int half;
7419         int n;
7420
7421         if (len <= 1)
7422                 return list;
7423         half = len >> 1;
7424         p = list;
7425         for (n = half; --n >= 0;) {
7426                 q = p;
7427                 p = p->next;
7428         }
7429         q->next = NULL;                 /* terminate first half of list */
7430         q = msort(list, half);          /* sort first half of list */
7431         p = msort(p, len - half);               /* sort second half */
7432         lpp = &list;
7433         for (;;) {
7434 #if ENABLE_LOCALE_SUPPORT
7435                 if (strcoll(p->text, q->text) < 0)
7436 #else
7437                 if (strcmp(p->text, q->text) < 0)
7438 #endif
7439                                                 {
7440                         *lpp = p;
7441                         lpp = &p->next;
7442                         p = *lpp;
7443                         if (p == NULL) {
7444                                 *lpp = q;
7445                                 break;
7446                         }
7447                 } else {
7448                         *lpp = q;
7449                         lpp = &q->next;
7450                         q = *lpp;
7451                         if (q == NULL) {
7452                                 *lpp = p;
7453                                 break;
7454                         }
7455                 }
7456         }
7457         return list;
7458 }
7459
7460 /*
7461  * Sort the results of file name expansion.  It calculates the number of
7462  * strings to sort and then calls msort (short for merge sort) to do the
7463  * work.
7464  */
7465 static struct strlist *
7466 expsort(struct strlist *str)
7467 {
7468         int len;
7469         struct strlist *sp;
7470
7471         len = 0;
7472         for (sp = str; sp; sp = sp->next)
7473                 len++;
7474         return msort(str, len);
7475 }
7476
7477 static void
7478 expandmeta(struct strlist *str /*, int flag*/)
7479 {
7480         /* TODO - EXP_REDIR */
7481
7482         while (str) {
7483                 char *expdir;
7484                 struct strlist **savelastp;
7485                 struct strlist *sp;
7486                 char *p;
7487
7488                 if (fflag)
7489                         goto nometa;
7490                 if (!hasmeta(str->text))
7491                         goto nometa;
7492                 savelastp = exparg.lastp;
7493
7494                 INT_OFF;
7495                 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
7496                 {
7497                         int i = strlen(str->text);
7498 //BUGGY estimation of how long expanded name can be
7499                         expdir = ckmalloc(i < 2048 ? 2048 : i+1);
7500                 }
7501                 expmeta(expdir, expdir, p);
7502                 free(expdir);
7503                 if (p != str->text)
7504                         free(p);
7505                 INT_ON;
7506                 if (exparg.lastp == savelastp) {
7507                         /*
7508                          * no matches
7509                          */
7510  nometa:
7511                         *exparg.lastp = str;
7512                         rmescapes(str->text, 0);
7513                         exparg.lastp = &str->next;
7514                 } else {
7515                         *exparg.lastp = NULL;
7516                         *savelastp = sp = expsort(*savelastp);
7517                         while (sp->next != NULL)
7518                                 sp = sp->next;
7519                         exparg.lastp = &sp->next;
7520                 }
7521                 str = str->next;
7522         }
7523 }
7524 #endif /* ENABLE_ASH_INTERNAL_GLOB */
7525
7526 /*
7527  * Perform variable substitution and command substitution on an argument,
7528  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
7529  * perform splitting and file name expansion.  When arglist is NULL, perform
7530  * here document expansion.
7531  */
7532 static void
7533 expandarg(union node *arg, struct arglist *arglist, int flag)
7534 {
7535         struct strlist *sp;
7536         char *p;
7537
7538         argbackq = arg->narg.backquote;
7539         STARTSTACKSTR(expdest);
7540         TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
7541         argstr(arg->narg.text, flag);
7542         p = _STPUTC('\0', expdest);
7543         expdest = p - 1;
7544         if (arglist == NULL) {
7545                 /* here document expanded */
7546                 goto out;
7547         }
7548         p = grabstackstr(p);
7549         TRACE(("expandarg: p:'%s'\n", p));
7550         exparg.lastp = &exparg.list;
7551         /*
7552          * TODO - EXP_REDIR
7553          */
7554         if (flag & EXP_FULL) {
7555                 ifsbreakup(p, &exparg);
7556                 *exparg.lastp = NULL;
7557                 exparg.lastp = &exparg.list;
7558                 expandmeta(exparg.list /*, flag*/);
7559         } else {
7560                 sp = stzalloc(sizeof(*sp));
7561                 sp->text = p;
7562                 *exparg.lastp = sp;
7563                 exparg.lastp = &sp->next;
7564         }
7565         *exparg.lastp = NULL;
7566         if (exparg.list) {
7567                 *arglist->lastp = exparg.list;
7568                 arglist->lastp = exparg.lastp;
7569         }
7570
7571  out:
7572         ifsfree();
7573 }
7574
7575 /*
7576  * Expand shell variables and backquotes inside a here document.
7577  */
7578 static void
7579 expandhere(union node *arg, int fd)
7580 {
7581         expandarg(arg, (struct arglist *)NULL, EXP_QUOTED);
7582         full_write(fd, stackblock(), expdest - (char *)stackblock());
7583 }
7584
7585 /*
7586  * Returns true if the pattern matches the string.
7587  */
7588 static int
7589 patmatch(char *pattern, const char *string)
7590 {
7591         char *p = preglob(pattern, 0);
7592         //bb_error_msg("fnmatch(pattern:'%s',str:'%s')", p, string);
7593         return pmatch(p, string);
7594 }
7595
7596 /*
7597  * See if a pattern matches in a case statement.
7598  */
7599 static int
7600 casematch(union node *pattern, char *val)
7601 {
7602         struct stackmark smark;
7603         int result;
7604
7605         setstackmark(&smark);
7606         argbackq = pattern->narg.backquote;
7607         STARTSTACKSTR(expdest);
7608         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
7609         STACKSTRNUL(expdest);
7610         ifsfree();
7611         result = patmatch(stackblock(), val);
7612         popstackmark(&smark);
7613         return result;
7614 }
7615
7616
7617 /* ============ find_command */
7618
7619 struct builtincmd {
7620         const char *name;
7621         int (*builtin)(int, char **) FAST_FUNC;
7622         /* unsigned flags; */
7623 };
7624 #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
7625 /* "regular" builtins always take precedence over commands,
7626  * regardless of PATH=....%builtin... position */
7627 #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
7628 #define IS_BUILTIN_ASSIGN(b)  ((b)->name[0] & 4)
7629
7630 struct cmdentry {
7631         smallint cmdtype;       /* CMDxxx */
7632         union param {
7633                 int index;
7634                 /* index >= 0 for commands without path (slashes) */
7635                 /* (TODO: what exactly does the value mean? PATH position?) */
7636                 /* index == -1 for commands with slashes */
7637                 /* index == (-2 - applet_no) for NOFORK applets */
7638                 const struct builtincmd *cmd;
7639                 struct funcnode *func;
7640         } u;
7641 };
7642 /* values of cmdtype */
7643 #define CMDUNKNOWN      -1      /* no entry in table for command */
7644 #define CMDNORMAL       0       /* command is an executable program */
7645 #define CMDFUNCTION     1       /* command is a shell function */
7646 #define CMDBUILTIN      2       /* command is a shell builtin */
7647
7648 /* action to find_command() */
7649 #define DO_ERR          0x01    /* prints errors */
7650 #define DO_ABS          0x02    /* checks absolute paths */
7651 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
7652 #define DO_ALTPATH      0x08    /* using alternate path */
7653 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
7654
7655 static void find_command(char *, struct cmdentry *, int, const char *);
7656
7657
7658 /* ============ Hashing commands */
7659
7660 /*
7661  * When commands are first encountered, they are entered in a hash table.
7662  * This ensures that a full path search will not have to be done for them
7663  * on each invocation.
7664  *
7665  * We should investigate converting to a linear search, even though that
7666  * would make the command name "hash" a misnomer.
7667  */
7668
7669 struct tblentry {
7670         struct tblentry *next;  /* next entry in hash chain */
7671         union param param;      /* definition of builtin function */
7672         smallint cmdtype;       /* CMDxxx */
7673         char rehash;            /* if set, cd done since entry created */
7674         char cmdname[1];        /* name of command */
7675 };
7676
7677 static struct tblentry **cmdtable;
7678 #define INIT_G_cmdtable() do { \
7679         cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
7680 } while (0)
7681
7682 static int builtinloc = -1;     /* index in path of %builtin, or -1 */
7683
7684
7685 static void
7686 tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) const char *cmd, char **argv, char **envp)
7687 {
7688 #if ENABLE_FEATURE_SH_STANDALONE
7689         if (applet_no >= 0) {
7690                 if (APPLET_IS_NOEXEC(applet_no)) {
7691                         clearenv();
7692                         while (*envp)
7693                                 putenv(*envp++);
7694                         popredir(/*drop:*/ 1, /*restore:*/ 0);
7695                         run_applet_no_and_exit(applet_no, cmd, argv);
7696                 }
7697                 /* re-exec ourselves with the new arguments */
7698                 execve(bb_busybox_exec_path, argv, envp);
7699                 /* If they called chroot or otherwise made the binary no longer
7700                  * executable, fall through */
7701         }
7702 #endif
7703
7704  repeat:
7705 #ifdef SYSV
7706         do {
7707                 execve(cmd, argv, envp);
7708         } while (errno == EINTR);
7709 #else
7710         execve(cmd, argv, envp);
7711 #endif
7712         if (cmd != bb_busybox_exec_path && errno == ENOEXEC) {
7713                 /* Run "cmd" as a shell script:
7714                  * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7715                  * "If the execve() function fails with ENOEXEC, the shell
7716                  * shall execute a command equivalent to having a shell invoked
7717                  * with the command name as its first operand,
7718                  * with any remaining arguments passed to the new shell"
7719                  *
7720                  * That is, do not use $SHELL, user's shell, or /bin/sh;
7721                  * just call ourselves.
7722                  *
7723                  * Note that bash reads ~80 chars of the file, and if it sees
7724                  * a zero byte before it sees newline, it doesn't try to
7725                  * interpret it, but fails with "cannot execute binary file"
7726                  * message and exit code 126. For one, this prevents attempts
7727                  * to interpret foreign ELF binaries as shell scripts.
7728                  */
7729                 argv[0] = (char*) cmd;
7730                 cmd = bb_busybox_exec_path;
7731                 /* NB: this is only possible because all callers of shellexec()
7732                  * ensure that the argv[-1] slot exists!
7733                  */
7734                 argv--;
7735                 argv[0] = (char*) "ash";
7736                 goto repeat;
7737         }
7738 }
7739
7740 /*
7741  * Exec a program.  Never returns.  If you change this routine, you may
7742  * have to change the find_command routine as well.
7743  * argv[-1] must exist and be writable! See tryexec() for why.
7744  */
7745 static void shellexec(char *prog, char **argv, const char *path, int idx) NORETURN;
7746 static void shellexec(char *prog, char **argv, const char *path, int idx)
7747 {
7748         char *cmdname;
7749         int e;
7750         char **envp;
7751         int exerrno;
7752         int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
7753
7754         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
7755         if (strchr(prog, '/') != NULL
7756 #if ENABLE_FEATURE_SH_STANDALONE
7757          || (applet_no = find_applet_by_name(prog)) >= 0
7758 #endif
7759         ) {
7760                 tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) prog, argv, envp);
7761                 if (applet_no >= 0) {
7762                         /* We tried execing ourself, but it didn't work.
7763                          * Maybe /proc/self/exe doesn't exist?
7764                          * Try $PATH search.
7765                          */
7766                         goto try_PATH;
7767                 }
7768                 e = errno;
7769         } else {
7770  try_PATH:
7771                 e = ENOENT;
7772                 while ((cmdname = path_advance(&path, prog)) != NULL) {
7773                         if (--idx < 0 && pathopt == NULL) {
7774                                 tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
7775                                 if (errno != ENOENT && errno != ENOTDIR)
7776                                         e = errno;
7777                         }
7778                         stunalloc(cmdname);
7779                 }
7780         }
7781
7782         /* Map to POSIX errors */
7783         switch (e) {
7784         case EACCES:
7785                 exerrno = 126;
7786                 break;
7787         case ENOENT:
7788                 exerrno = 127;
7789                 break;
7790         default:
7791                 exerrno = 2;
7792                 break;
7793         }
7794         exitstatus = exerrno;
7795         TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
7796                 prog, e, suppress_int));
7797         ash_msg_and_raise(EXEXIT, "%s: %s", prog, errmsg(e, "not found"));
7798         /* NOTREACHED */
7799 }
7800
7801 static void
7802 printentry(struct tblentry *cmdp)
7803 {
7804         int idx;
7805         const char *path;
7806         char *name;
7807
7808         idx = cmdp->param.index;
7809         path = pathval();
7810         do {
7811                 name = path_advance(&path, cmdp->cmdname);
7812                 stunalloc(name);
7813         } while (--idx >= 0);
7814         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
7815 }
7816
7817 /*
7818  * Clear out command entries.  The argument specifies the first entry in
7819  * PATH which has changed.
7820  */
7821 static void
7822 clearcmdentry(int firstchange)
7823 {
7824         struct tblentry **tblp;
7825         struct tblentry **pp;
7826         struct tblentry *cmdp;
7827
7828         INT_OFF;
7829         for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
7830                 pp = tblp;
7831                 while ((cmdp = *pp) != NULL) {
7832                         if ((cmdp->cmdtype == CMDNORMAL &&
7833                              cmdp->param.index >= firstchange)
7834                          || (cmdp->cmdtype == CMDBUILTIN &&
7835                              builtinloc >= firstchange)
7836                         ) {
7837                                 *pp = cmdp->next;
7838                                 free(cmdp);
7839                         } else {
7840                                 pp = &cmdp->next;
7841                         }
7842                 }
7843         }
7844         INT_ON;
7845 }
7846
7847 /*
7848  * Locate a command in the command hash table.  If "add" is nonzero,
7849  * add the command to the table if it is not already present.  The
7850  * variable "lastcmdentry" is set to point to the address of the link
7851  * pointing to the entry, so that delete_cmd_entry can delete the
7852  * entry.
7853  *
7854  * Interrupts must be off if called with add != 0.
7855  */
7856 static struct tblentry **lastcmdentry;
7857
7858 static struct tblentry *
7859 cmdlookup(const char *name, int add)
7860 {
7861         unsigned int hashval;
7862         const char *p;
7863         struct tblentry *cmdp;
7864         struct tblentry **pp;
7865
7866         p = name;
7867         hashval = (unsigned char)*p << 4;
7868         while (*p)
7869                 hashval += (unsigned char)*p++;
7870         hashval &= 0x7FFF;
7871         pp = &cmdtable[hashval % CMDTABLESIZE];
7872         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7873                 if (strcmp(cmdp->cmdname, name) == 0)
7874                         break;
7875                 pp = &cmdp->next;
7876         }
7877         if (add && cmdp == NULL) {
7878                 cmdp = *pp = ckzalloc(sizeof(struct tblentry)
7879                                 + strlen(name)
7880                                 /* + 1 - already done because
7881                                  * tblentry::cmdname is char[1] */);
7882                 /*cmdp->next = NULL; - ckzalloc did it */
7883                 cmdp->cmdtype = CMDUNKNOWN;
7884                 strcpy(cmdp->cmdname, name);
7885         }
7886         lastcmdentry = pp;
7887         return cmdp;
7888 }
7889
7890 /*
7891  * Delete the command entry returned on the last lookup.
7892  */
7893 static void
7894 delete_cmd_entry(void)
7895 {
7896         struct tblentry *cmdp;
7897
7898         INT_OFF;
7899         cmdp = *lastcmdentry;
7900         *lastcmdentry = cmdp->next;
7901         if (cmdp->cmdtype == CMDFUNCTION)
7902                 freefunc(cmdp->param.func);
7903         free(cmdp);
7904         INT_ON;
7905 }
7906
7907 /*
7908  * Add a new command entry, replacing any existing command entry for
7909  * the same name - except special builtins.
7910  */
7911 static void
7912 addcmdentry(char *name, struct cmdentry *entry)
7913 {
7914         struct tblentry *cmdp;
7915
7916         cmdp = cmdlookup(name, 1);
7917         if (cmdp->cmdtype == CMDFUNCTION) {
7918                 freefunc(cmdp->param.func);
7919         }
7920         cmdp->cmdtype = entry->cmdtype;
7921         cmdp->param = entry->u;
7922         cmdp->rehash = 0;
7923 }
7924
7925 static int FAST_FUNC
7926 hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
7927 {
7928         struct tblentry **pp;
7929         struct tblentry *cmdp;
7930         int c;
7931         struct cmdentry entry;
7932         char *name;
7933
7934         if (nextopt("r") != '\0') {
7935                 clearcmdentry(0);
7936                 return 0;
7937         }
7938
7939         if (*argptr == NULL) {
7940                 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7941                         for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7942                                 if (cmdp->cmdtype == CMDNORMAL)
7943                                         printentry(cmdp);
7944                         }
7945                 }
7946                 return 0;
7947         }
7948
7949         c = 0;
7950         while ((name = *argptr) != NULL) {
7951                 cmdp = cmdlookup(name, 0);
7952                 if (cmdp != NULL
7953                  && (cmdp->cmdtype == CMDNORMAL
7954                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
7955                 ) {
7956                         delete_cmd_entry();
7957                 }
7958                 find_command(name, &entry, DO_ERR, pathval());
7959                 if (entry.cmdtype == CMDUNKNOWN)
7960                         c = 1;
7961                 argptr++;
7962         }
7963         return c;
7964 }
7965
7966 /*
7967  * Called when a cd is done.  Marks all commands so the next time they
7968  * are executed they will be rehashed.
7969  */
7970 static void
7971 hashcd(void)
7972 {
7973         struct tblentry **pp;
7974         struct tblentry *cmdp;
7975
7976         for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
7977                 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
7978                         if (cmdp->cmdtype == CMDNORMAL
7979                          || (cmdp->cmdtype == CMDBUILTIN
7980                              && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
7981                              && builtinloc > 0)
7982                         ) {
7983                                 cmdp->rehash = 1;
7984                         }
7985                 }
7986         }
7987 }
7988
7989 /*
7990  * Fix command hash table when PATH changed.
7991  * Called before PATH is changed.  The argument is the new value of PATH;
7992  * pathval() still returns the old value at this point.
7993  * Called with interrupts off.
7994  */
7995 static void FAST_FUNC
7996 changepath(const char *new)
7997 {
7998         const char *old;
7999         int firstchange;
8000         int idx;
8001         int idx_bltin;
8002
8003         old = pathval();
8004         firstchange = 9999;     /* assume no change */
8005         idx = 0;
8006         idx_bltin = -1;
8007         for (;;) {
8008                 if (*old != *new) {
8009                         firstchange = idx;
8010                         if ((*old == '\0' && *new == ':')
8011                          || (*old == ':' && *new == '\0')
8012                         ) {
8013                                 firstchange++;
8014                         }
8015                         old = new;      /* ignore subsequent differences */
8016                 }
8017                 if (*new == '\0')
8018                         break;
8019                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
8020                         idx_bltin = idx;
8021                 if (*new == ':')
8022                         idx++;
8023                 new++;
8024                 old++;
8025         }
8026         if (builtinloc < 0 && idx_bltin >= 0)
8027                 builtinloc = idx_bltin;             /* zap builtins */
8028         if (builtinloc >= 0 && idx_bltin < 0)
8029                 firstchange = 0;
8030         clearcmdentry(firstchange);
8031         builtinloc = idx_bltin;
8032 }
8033 enum {
8034         TEOF,
8035         TNL,
8036         TREDIR,
8037         TWORD,
8038         TSEMI,
8039         TBACKGND,
8040         TAND,
8041         TOR,
8042         TPIPE,
8043         TLP,
8044         TRP,
8045         TENDCASE,
8046         TENDBQUOTE,
8047         TNOT,
8048         TCASE,
8049         TDO,
8050         TDONE,
8051         TELIF,
8052         TELSE,
8053         TESAC,
8054         TFI,
8055         TFOR,
8056 #if BASH_FUNCTION
8057         TFUNCTION,
8058 #endif
8059         TIF,
8060         TIN,
8061         TTHEN,
8062         TUNTIL,
8063         TWHILE,
8064         TBEGIN,
8065         TEND
8066 };
8067 typedef smallint token_id_t;
8068
8069 /* Nth bit indicates if token marks the end of a list */
8070 enum {
8071         tokendlist = 0
8072         /*  0 */ | (1u << TEOF)
8073         /*  1 */ | (0u << TNL)
8074         /*  2 */ | (0u << TREDIR)
8075         /*  3 */ | (0u << TWORD)
8076         /*  4 */ | (0u << TSEMI)
8077         /*  5 */ | (0u << TBACKGND)
8078         /*  6 */ | (0u << TAND)
8079         /*  7 */ | (0u << TOR)
8080         /*  8 */ | (0u << TPIPE)
8081         /*  9 */ | (0u << TLP)
8082         /* 10 */ | (1u << TRP)
8083         /* 11 */ | (1u << TENDCASE)
8084         /* 12 */ | (1u << TENDBQUOTE)
8085         /* 13 */ | (0u << TNOT)
8086         /* 14 */ | (0u << TCASE)
8087         /* 15 */ | (1u << TDO)
8088         /* 16 */ | (1u << TDONE)
8089         /* 17 */ | (1u << TELIF)
8090         /* 18 */ | (1u << TELSE)
8091         /* 19 */ | (1u << TESAC)
8092         /* 20 */ | (1u << TFI)
8093         /* 21 */ | (0u << TFOR)
8094 #if BASH_FUNCTION
8095         /* 22 */ | (0u << TFUNCTION)
8096 #endif
8097         /* 23 */ | (0u << TIF)
8098         /* 24 */ | (0u << TIN)
8099         /* 25 */ | (1u << TTHEN)
8100         /* 26 */ | (0u << TUNTIL)
8101         /* 27 */ | (0u << TWHILE)
8102         /* 28 */ | (0u << TBEGIN)
8103         /* 29 */ | (1u << TEND)
8104         , /* thus far 29 bits used */
8105 };
8106
8107 static const char *const tokname_array[] = {
8108         "end of file",
8109         "newline",
8110         "redirection",
8111         "word",
8112         ";",
8113         "&",
8114         "&&",
8115         "||",
8116         "|",
8117         "(",
8118         ")",
8119         ";;",
8120         "`",
8121 #define KWDOFFSET 13
8122         /* the following are keywords */
8123         "!",
8124         "case",
8125         "do",
8126         "done",
8127         "elif",
8128         "else",
8129         "esac",
8130         "fi",
8131         "for",
8132 #if BASH_FUNCTION
8133         "function",
8134 #endif
8135         "if",
8136         "in",
8137         "then",
8138         "until",
8139         "while",
8140         "{",
8141         "}",
8142 };
8143
8144 /* Wrapper around strcmp for qsort/bsearch/... */
8145 static int
8146 pstrcmp(const void *a, const void *b)
8147 {
8148         return strcmp((char*)a, *(char**)b);
8149 }
8150
8151 static const char *const *
8152 findkwd(const char *s)
8153 {
8154         return bsearch(s, tokname_array + KWDOFFSET,
8155                         ARRAY_SIZE(tokname_array) - KWDOFFSET,
8156                         sizeof(tokname_array[0]), pstrcmp);
8157 }
8158
8159 /*
8160  * Locate and print what a word is...
8161  */
8162 static int
8163 describe_command(char *command, const char *path, int describe_command_verbose)
8164 {
8165         struct cmdentry entry;
8166 #if ENABLE_ASH_ALIAS
8167         const struct alias *ap;
8168 #endif
8169
8170         path = path ? path : pathval();
8171
8172         if (describe_command_verbose) {
8173                 out1str(command);
8174         }
8175
8176         /* First look at the keywords */
8177         if (findkwd(command)) {
8178                 out1str(describe_command_verbose ? " is a shell keyword" : command);
8179                 goto out;
8180         }
8181
8182 #if ENABLE_ASH_ALIAS
8183         /* Then look at the aliases */
8184         ap = lookupalias(command, 0);
8185         if (ap != NULL) {
8186                 if (!describe_command_verbose) {
8187                         out1str("alias ");
8188                         printalias(ap);
8189                         return 0;
8190                 }
8191                 out1fmt(" is an alias for %s", ap->val);
8192                 goto out;
8193         }
8194 #endif
8195         /* Brute force */
8196         find_command(command, &entry, DO_ABS, path);
8197
8198         switch (entry.cmdtype) {
8199         case CMDNORMAL: {
8200                 int j = entry.u.index;
8201                 char *p;
8202                 if (j < 0) {
8203                         p = command;
8204                 } else {
8205                         do {
8206                                 p = path_advance(&path, command);
8207                                 stunalloc(p);
8208                         } while (--j >= 0);
8209                 }
8210                 if (describe_command_verbose) {
8211                         out1fmt(" is %s", p);
8212                 } else {
8213                         out1str(p);
8214                 }
8215                 break;
8216         }
8217
8218         case CMDFUNCTION:
8219                 if (describe_command_verbose) {
8220                         out1str(" is a shell function");
8221                 } else {
8222                         out1str(command);
8223                 }
8224                 break;
8225
8226         case CMDBUILTIN:
8227                 if (describe_command_verbose) {
8228                         out1fmt(" is a %sshell builtin",
8229                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
8230                                         "special " : nullstr
8231                         );
8232                 } else {
8233                         out1str(command);
8234                 }
8235                 break;
8236
8237         default:
8238                 if (describe_command_verbose) {
8239                         out1str(": not found\n");
8240                 }
8241                 return 127;
8242         }
8243  out:
8244         out1str("\n");
8245         return 0;
8246 }
8247
8248 static int FAST_FUNC
8249 typecmd(int argc UNUSED_PARAM, char **argv)
8250 {
8251         int i = 1;
8252         int err = 0;
8253         int verbose = 1;
8254
8255         /* type -p ... ? (we don't bother checking for 'p') */
8256         if (argv[1] && argv[1][0] == '-') {
8257                 i++;
8258                 verbose = 0;
8259         }
8260         while (argv[i]) {
8261                 err |= describe_command(argv[i++], NULL, verbose);
8262         }
8263         return err;
8264 }
8265
8266 #if ENABLE_ASH_CMDCMD
8267 /* Is it "command [-p] PROG ARGS" bltin, no other opts? Return ptr to "PROG" if yes */
8268 static char **
8269 parse_command_args(char **argv, const char **path)
8270 {
8271         char *cp, c;
8272
8273         for (;;) {
8274                 cp = *++argv;
8275                 if (!cp)
8276                         return NULL;
8277                 if (*cp++ != '-')
8278                         break;
8279                 c = *cp++;
8280                 if (!c)
8281                         break;
8282                 if (c == '-' && !*cp) {
8283                         if (!*++argv)
8284                                 return NULL;
8285                         break;
8286                 }
8287                 do {
8288                         switch (c) {
8289                         case 'p':
8290                                 *path = bb_default_path;
8291                                 break;
8292                         default:
8293                                 /* run 'typecmd' for other options */
8294                                 return NULL;
8295                         }
8296                         c = *cp++;
8297                 } while (c);
8298         }
8299         return argv;
8300 }
8301
8302 static int FAST_FUNC
8303 commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
8304 {
8305         char *cmd;
8306         int c;
8307         enum {
8308                 VERIFY_BRIEF = 1,
8309                 VERIFY_VERBOSE = 2,
8310         } verify = 0;
8311         const char *path = NULL;
8312
8313         /* "command [-p] PROG ARGS" (that is, without -V or -v)
8314          * never reaches this function.
8315          */
8316
8317         while ((c = nextopt("pvV")) != '\0')
8318                 if (c == 'V')
8319                         verify |= VERIFY_VERBOSE;
8320                 else if (c == 'v')
8321                         /*verify |= VERIFY_BRIEF*/;
8322 #if DEBUG
8323                 else if (c != 'p')
8324                         abort();
8325 #endif
8326                 else
8327                         path = bb_default_path;
8328
8329         /* Mimic bash: just "command -v" doesn't complain, it's a nop */
8330         cmd = *argptr;
8331         if (/*verify && */ cmd)
8332                 return describe_command(cmd, path, verify /* - VERIFY_BRIEF*/);
8333
8334         return 0;
8335 }
8336 #endif
8337
8338
8339 /*static int funcblocksize;     // size of structures in function */
8340 /*static int funcstringsize;    // size of strings in node */
8341 static void *funcblock;         /* block to allocate function from */
8342 static char *funcstring_end;    /* end of block to allocate strings from */
8343
8344 static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8345         [NCMD     ] = SHELL_ALIGN(sizeof(struct ncmd)),
8346         [NPIPE    ] = SHELL_ALIGN(sizeof(struct npipe)),
8347         [NREDIR   ] = SHELL_ALIGN(sizeof(struct nredir)),
8348         [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
8349         [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
8350         [NAND     ] = SHELL_ALIGN(sizeof(struct nbinary)),
8351         [NOR      ] = SHELL_ALIGN(sizeof(struct nbinary)),
8352         [NSEMI    ] = SHELL_ALIGN(sizeof(struct nbinary)),
8353         [NIF      ] = SHELL_ALIGN(sizeof(struct nif)),
8354         [NWHILE   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8355         [NUNTIL   ] = SHELL_ALIGN(sizeof(struct nbinary)),
8356         [NFOR     ] = SHELL_ALIGN(sizeof(struct nfor)),
8357         [NCASE    ] = SHELL_ALIGN(sizeof(struct ncase)),
8358         [NCLIST   ] = SHELL_ALIGN(sizeof(struct nclist)),
8359         [NDEFUN   ] = SHELL_ALIGN(sizeof(struct narg)),
8360         [NARG     ] = SHELL_ALIGN(sizeof(struct narg)),
8361         [NTO      ] = SHELL_ALIGN(sizeof(struct nfile)),
8362 #if BASH_REDIR_OUTPUT
8363         [NTO2     ] = SHELL_ALIGN(sizeof(struct nfile)),
8364 #endif
8365         [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
8366         [NFROM    ] = SHELL_ALIGN(sizeof(struct nfile)),
8367         [NFROMTO  ] = SHELL_ALIGN(sizeof(struct nfile)),
8368         [NAPPEND  ] = SHELL_ALIGN(sizeof(struct nfile)),
8369         [NTOFD    ] = SHELL_ALIGN(sizeof(struct ndup)),
8370         [NFROMFD  ] = SHELL_ALIGN(sizeof(struct ndup)),
8371         [NHERE    ] = SHELL_ALIGN(sizeof(struct nhere)),
8372         [NXHERE   ] = SHELL_ALIGN(sizeof(struct nhere)),
8373         [NNOT     ] = SHELL_ALIGN(sizeof(struct nnot)),
8374 };
8375
8376 static int calcsize(int funcblocksize, union node *n);
8377
8378 static int
8379 sizenodelist(int funcblocksize, struct nodelist *lp)
8380 {
8381         while (lp) {
8382                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8383                 funcblocksize = calcsize(funcblocksize, lp->n);
8384                 lp = lp->next;
8385         }
8386         return funcblocksize;
8387 }
8388
8389 static int
8390 calcsize(int funcblocksize, union node *n)
8391 {
8392         if (n == NULL)
8393                 return funcblocksize;
8394         funcblocksize += nodesize[n->type];
8395         switch (n->type) {
8396         case NCMD:
8397                 funcblocksize = calcsize(funcblocksize, n->ncmd.redirect);
8398                 funcblocksize = calcsize(funcblocksize, n->ncmd.args);
8399                 funcblocksize = calcsize(funcblocksize, n->ncmd.assign);
8400                 break;
8401         case NPIPE:
8402                 funcblocksize = sizenodelist(funcblocksize, n->npipe.cmdlist);
8403                 break;
8404         case NREDIR:
8405         case NBACKGND:
8406         case NSUBSHELL:
8407                 funcblocksize = calcsize(funcblocksize, n->nredir.redirect);
8408                 funcblocksize = calcsize(funcblocksize, n->nredir.n);
8409                 break;
8410         case NAND:
8411         case NOR:
8412         case NSEMI:
8413         case NWHILE:
8414         case NUNTIL:
8415                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch2);
8416                 funcblocksize = calcsize(funcblocksize, n->nbinary.ch1);
8417                 break;
8418         case NIF:
8419                 funcblocksize = calcsize(funcblocksize, n->nif.elsepart);
8420                 funcblocksize = calcsize(funcblocksize, n->nif.ifpart);
8421                 funcblocksize = calcsize(funcblocksize, n->nif.test);
8422                 break;
8423         case NFOR:
8424                 funcblocksize += SHELL_ALIGN(strlen(n->nfor.var) + 1); /* was funcstringsize += ... */
8425                 funcblocksize = calcsize(funcblocksize, n->nfor.body);
8426                 funcblocksize = calcsize(funcblocksize, n->nfor.args);
8427                 break;
8428         case NCASE:
8429                 funcblocksize = calcsize(funcblocksize, n->ncase.cases);
8430                 funcblocksize = calcsize(funcblocksize, n->ncase.expr);
8431                 break;
8432         case NCLIST:
8433                 funcblocksize = calcsize(funcblocksize, n->nclist.body);
8434                 funcblocksize = calcsize(funcblocksize, n->nclist.pattern);
8435                 funcblocksize = calcsize(funcblocksize, n->nclist.next);
8436                 break;
8437         case NDEFUN:
8438         case NARG:
8439                 funcblocksize = sizenodelist(funcblocksize, n->narg.backquote);
8440                 funcblocksize += SHELL_ALIGN(strlen(n->narg.text) + 1); /* was funcstringsize += ... */
8441                 funcblocksize = calcsize(funcblocksize, n->narg.next);
8442                 break;
8443         case NTO:
8444 #if BASH_REDIR_OUTPUT
8445         case NTO2:
8446 #endif
8447         case NCLOBBER:
8448         case NFROM:
8449         case NFROMTO:
8450         case NAPPEND:
8451                 funcblocksize = calcsize(funcblocksize, n->nfile.fname);
8452                 funcblocksize = calcsize(funcblocksize, n->nfile.next);
8453                 break;
8454         case NTOFD:
8455         case NFROMFD:
8456                 funcblocksize = calcsize(funcblocksize, n->ndup.vname);
8457                 funcblocksize = calcsize(funcblocksize, n->ndup.next);
8458         break;
8459         case NHERE:
8460         case NXHERE:
8461                 funcblocksize = calcsize(funcblocksize, n->nhere.doc);
8462                 funcblocksize = calcsize(funcblocksize, n->nhere.next);
8463                 break;
8464         case NNOT:
8465                 funcblocksize = calcsize(funcblocksize, n->nnot.com);
8466                 break;
8467         };
8468         return funcblocksize;
8469 }
8470
8471 static char *
8472 nodeckstrdup(char *s)
8473 {
8474         funcstring_end -= SHELL_ALIGN(strlen(s) + 1);
8475         return strcpy(funcstring_end, s);
8476 }
8477
8478 static union node *copynode(union node *);
8479
8480 static struct nodelist *
8481 copynodelist(struct nodelist *lp)
8482 {
8483         struct nodelist *start;
8484         struct nodelist **lpp;
8485
8486         lpp = &start;
8487         while (lp) {
8488                 *lpp = funcblock;
8489                 funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
8490                 (*lpp)->n = copynode(lp->n);
8491                 lp = lp->next;
8492                 lpp = &(*lpp)->next;
8493         }
8494         *lpp = NULL;
8495         return start;
8496 }
8497
8498 static union node *
8499 copynode(union node *n)
8500 {
8501         union node *new;
8502
8503         if (n == NULL)
8504                 return NULL;
8505         new = funcblock;
8506         funcblock = (char *) funcblock + nodesize[n->type];
8507
8508         switch (n->type) {
8509         case NCMD:
8510                 new->ncmd.redirect = copynode(n->ncmd.redirect);
8511                 new->ncmd.args = copynode(n->ncmd.args);
8512                 new->ncmd.assign = copynode(n->ncmd.assign);
8513                 break;
8514         case NPIPE:
8515                 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8516                 new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
8517                 break;
8518         case NREDIR:
8519         case NBACKGND:
8520         case NSUBSHELL:
8521                 new->nredir.redirect = copynode(n->nredir.redirect);
8522                 new->nredir.n = copynode(n->nredir.n);
8523                 break;
8524         case NAND:
8525         case NOR:
8526         case NSEMI:
8527         case NWHILE:
8528         case NUNTIL:
8529                 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8530                 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8531                 break;
8532         case NIF:
8533                 new->nif.elsepart = copynode(n->nif.elsepart);
8534                 new->nif.ifpart = copynode(n->nif.ifpart);
8535                 new->nif.test = copynode(n->nif.test);
8536                 break;
8537         case NFOR:
8538                 new->nfor.var = nodeckstrdup(n->nfor.var);
8539                 new->nfor.body = copynode(n->nfor.body);
8540                 new->nfor.args = copynode(n->nfor.args);
8541                 break;
8542         case NCASE:
8543                 new->ncase.cases = copynode(n->ncase.cases);
8544                 new->ncase.expr = copynode(n->ncase.expr);
8545                 break;
8546         case NCLIST:
8547                 new->nclist.body = copynode(n->nclist.body);
8548                 new->nclist.pattern = copynode(n->nclist.pattern);
8549                 new->nclist.next = copynode(n->nclist.next);
8550                 break;
8551         case NDEFUN:
8552         case NARG:
8553                 new->narg.backquote = copynodelist(n->narg.backquote);
8554                 new->narg.text = nodeckstrdup(n->narg.text);
8555                 new->narg.next = copynode(n->narg.next);
8556                 break;
8557         case NTO:
8558 #if BASH_REDIR_OUTPUT
8559         case NTO2:
8560 #endif
8561         case NCLOBBER:
8562         case NFROM:
8563         case NFROMTO:
8564         case NAPPEND:
8565                 new->nfile.fname = copynode(n->nfile.fname);
8566                 new->nfile.fd = n->nfile.fd;
8567                 new->nfile.next = copynode(n->nfile.next);
8568                 break;
8569         case NTOFD:
8570         case NFROMFD:
8571                 new->ndup.vname = copynode(n->ndup.vname);
8572                 new->ndup.dupfd = n->ndup.dupfd;
8573                 new->ndup.fd = n->ndup.fd;
8574                 new->ndup.next = copynode(n->ndup.next);
8575                 break;
8576         case NHERE:
8577         case NXHERE:
8578                 new->nhere.doc = copynode(n->nhere.doc);
8579                 new->nhere.fd = n->nhere.fd;
8580                 new->nhere.next = copynode(n->nhere.next);
8581                 break;
8582         case NNOT:
8583                 new->nnot.com = copynode(n->nnot.com);
8584                 break;
8585         };
8586         new->type = n->type;
8587         return new;
8588 }
8589
8590 /*
8591  * Make a copy of a parse tree.
8592  */
8593 static struct funcnode *
8594 copyfunc(union node *n)
8595 {
8596         struct funcnode *f;
8597         size_t blocksize;
8598
8599         /*funcstringsize = 0;*/
8600         blocksize = offsetof(struct funcnode, n) + calcsize(0, n);
8601         f = ckzalloc(blocksize /* + funcstringsize */);
8602         funcblock = (char *) f + offsetof(struct funcnode, n);
8603         funcstring_end = (char *) f + blocksize;
8604         copynode(n);
8605         /* f->count = 0; - ckzalloc did it */
8606         return f;
8607 }
8608
8609 /*
8610  * Define a shell function.
8611  */
8612 static void
8613 defun(union node *func)
8614 {
8615         struct cmdentry entry;
8616
8617         INT_OFF;
8618         entry.cmdtype = CMDFUNCTION;
8619         entry.u.func = copyfunc(func);
8620         addcmdentry(func->narg.text, &entry);
8621         INT_ON;
8622 }
8623
8624 /* Reasons for skipping commands (see comment on breakcmd routine) */
8625 #define SKIPBREAK      (1 << 0)
8626 #define SKIPCONT       (1 << 1)
8627 #define SKIPFUNC       (1 << 2)
8628 static smallint evalskip;       /* set to SKIPxxx if we are skipping commands */
8629 static int skipcount;           /* number of levels to skip */
8630 static int funcnest;            /* depth of function calls */
8631 static int loopnest;            /* current loop nesting level */
8632
8633 /* Forward decl way out to parsing code - dotrap needs it */
8634 static int evalstring(char *s, int flags);
8635
8636 /* Called to execute a trap.
8637  * Single callsite - at the end of evaltree().
8638  * If we return non-zero, evaltree raises EXEXIT exception.
8639  *
8640  * Perhaps we should avoid entering new trap handlers
8641  * while we are executing a trap handler. [is it a TODO?]
8642  */
8643 static void
8644 dotrap(void)
8645 {
8646         uint8_t *g;
8647         int sig;
8648         uint8_t last_status;
8649
8650         if (!pending_sig)
8651                 return;
8652
8653         last_status = exitstatus;
8654         pending_sig = 0;
8655         barrier();
8656
8657         TRACE(("dotrap entered\n"));
8658         for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
8659                 char *p;
8660
8661                 if (!*g)
8662                         continue;
8663
8664                 if (evalskip) {
8665                         pending_sig = sig;
8666                         break;
8667                 }
8668
8669                 p = trap[sig];
8670                 /* non-trapped SIGINT is handled separately by raise_interrupt,
8671                  * don't upset it by resetting gotsig[SIGINT-1] */
8672                 if (sig == SIGINT && !p)
8673                         continue;
8674
8675                 TRACE(("sig %d is active, will run handler '%s'\n", sig, p));
8676                 *g = 0;
8677                 if (!p)
8678                         continue;
8679                 evalstring(p, 0);
8680         }
8681         exitstatus = last_status;
8682         TRACE(("dotrap returns\n"));
8683 }
8684
8685 /* forward declarations - evaluation is fairly recursive business... */
8686 static int evalloop(union node *, int);
8687 static int evalfor(union node *, int);
8688 static int evalcase(union node *, int);
8689 static int evalsubshell(union node *, int);
8690 static void expredir(union node *);
8691 static int evalpipe(union node *, int);
8692 static int evalcommand(union node *, int);
8693 static int evalbltin(const struct builtincmd *, int, char **, int);
8694 static void prehash(union node *);
8695
8696 /*
8697  * Evaluate a parse tree.  The value is left in the global variable
8698  * exitstatus.
8699  */
8700 static int
8701 evaltree(union node *n, int flags)
8702 {
8703         int checkexit = 0;
8704         int (*evalfn)(union node *, int);
8705         int status = 0;
8706
8707         if (n == NULL) {
8708                 TRACE(("evaltree(NULL) called\n"));
8709                 goto out;
8710         }
8711         TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
8712
8713         dotrap();
8714
8715         switch (n->type) {
8716         default:
8717 #if DEBUG
8718                 out1fmt("Node type = %d\n", n->type);
8719                 fflush_all();
8720                 break;
8721 #endif
8722         case NNOT:
8723                 status = !evaltree(n->nnot.com, EV_TESTED);
8724                 goto setstatus;
8725         case NREDIR:
8726                 expredir(n->nredir.redirect);
8727                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
8728                 if (!status) {
8729                         status = evaltree(n->nredir.n, flags & EV_TESTED);
8730                 }
8731                 if (n->nredir.redirect)
8732                         popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
8733                 goto setstatus;
8734         case NCMD:
8735                 evalfn = evalcommand;
8736  checkexit:
8737                 if (eflag && !(flags & EV_TESTED))
8738                         checkexit = ~0;
8739                 goto calleval;
8740         case NFOR:
8741                 evalfn = evalfor;
8742                 goto calleval;
8743         case NWHILE:
8744         case NUNTIL:
8745                 evalfn = evalloop;
8746                 goto calleval;
8747         case NSUBSHELL:
8748         case NBACKGND:
8749                 evalfn = evalsubshell;
8750                 goto checkexit;
8751         case NPIPE:
8752                 evalfn = evalpipe;
8753                 goto checkexit;
8754         case NCASE:
8755                 evalfn = evalcase;
8756                 goto calleval;
8757         case NAND:
8758         case NOR:
8759         case NSEMI: {
8760
8761 #if NAND + 1 != NOR
8762 #error NAND + 1 != NOR
8763 #endif
8764 #if NOR + 1 != NSEMI
8765 #error NOR + 1 != NSEMI
8766 #endif
8767                 unsigned is_or = n->type - NAND;
8768                 status = evaltree(
8769                         n->nbinary.ch1,
8770                         (flags | ((is_or >> 1) - 1)) & EV_TESTED
8771                 );
8772                 if ((!status) == is_or || evalskip)
8773                         break;
8774                 n = n->nbinary.ch2;
8775  evaln:
8776                 evalfn = evaltree;
8777  calleval:
8778                 status = evalfn(n, flags);
8779                 goto setstatus;
8780         }
8781         case NIF:
8782                 status = evaltree(n->nif.test, EV_TESTED);
8783                 if (evalskip)
8784                         break;
8785                 if (!status) {
8786                         n = n->nif.ifpart;
8787                         goto evaln;
8788                 }
8789                 if (n->nif.elsepart) {
8790                         n = n->nif.elsepart;
8791                         goto evaln;
8792                 }
8793                 status = 0;
8794                 goto setstatus;
8795         case NDEFUN:
8796                 defun(n);
8797                 /* Not necessary. To test it:
8798                  * "false; f() { qwerty; }; echo $?" should print 0.
8799                  */
8800                 /* status = 0; */
8801  setstatus:
8802                 exitstatus = status;
8803                 break;
8804         }
8805  out:
8806         /* Order of checks below is important:
8807          * signal handlers trigger before exit caused by "set -e".
8808          */
8809         dotrap();
8810
8811         if (checkexit & status)
8812                 raise_exception(EXEXIT);
8813         if (flags & EV_EXIT)
8814                 raise_exception(EXEXIT);
8815
8816         TRACE(("leaving evaltree (no interrupts)\n"));
8817         return exitstatus;
8818 }
8819
8820 static int
8821 skiploop(void)
8822 {
8823         int skip = evalskip;
8824
8825         switch (skip) {
8826         case 0:
8827                 break;
8828         case SKIPBREAK:
8829         case SKIPCONT:
8830                 if (--skipcount <= 0) {
8831                         evalskip = 0;
8832                         break;
8833                 }
8834                 skip = SKIPBREAK;
8835                 break;
8836         }
8837         return skip;
8838 }
8839
8840 static int
8841 evalloop(union node *n, int flags)
8842 {
8843         int skip;
8844         int status;
8845
8846         loopnest++;
8847         status = 0;
8848         flags &= EV_TESTED;
8849         do {
8850                 int i;
8851
8852                 i = evaltree(n->nbinary.ch1, EV_TESTED);
8853                 skip = skiploop();
8854                 if (skip == SKIPFUNC)
8855                         status = i;
8856                 if (skip)
8857                         continue;
8858                 if (n->type != NWHILE)
8859                         i = !i;
8860                 if (i != 0)
8861                         break;
8862                 status = evaltree(n->nbinary.ch2, flags);
8863                 skip = skiploop();
8864         } while (!(skip & ~SKIPCONT));
8865         loopnest--;
8866
8867         return status;
8868 }
8869
8870 static int
8871 evalfor(union node *n, int flags)
8872 {
8873         struct arglist arglist;
8874         union node *argp;
8875         struct strlist *sp;
8876         struct stackmark smark;
8877         int status = 0;
8878
8879         setstackmark(&smark);
8880         arglist.list = NULL;
8881         arglist.lastp = &arglist.list;
8882         for (argp = n->nfor.args; argp; argp = argp->narg.next) {
8883                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
8884         }
8885         *arglist.lastp = NULL;
8886
8887         loopnest++;
8888         flags &= EV_TESTED;
8889         for (sp = arglist.list; sp; sp = sp->next) {
8890                 setvar0(n->nfor.var, sp->text);
8891                 status = evaltree(n->nfor.body, flags);
8892                 if (skiploop() & ~SKIPCONT)
8893                         break;
8894         }
8895         loopnest--;
8896         popstackmark(&smark);
8897
8898         return status;
8899 }
8900
8901 static int
8902 evalcase(union node *n, int flags)
8903 {
8904         union node *cp;
8905         union node *patp;
8906         struct arglist arglist;
8907         struct stackmark smark;
8908         int status = 0;
8909
8910         setstackmark(&smark);
8911         arglist.list = NULL;
8912         arglist.lastp = &arglist.list;
8913         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
8914         for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
8915                 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
8916                         if (casematch(patp, arglist.list->text)) {
8917                                 /* Ensure body is non-empty as otherwise
8918                                  * EV_EXIT may prevent us from setting the
8919                                  * exit status.
8920                                  */
8921                                 if (evalskip == 0 && cp->nclist.body) {
8922                                         status = evaltree(cp->nclist.body, flags);
8923                                 }
8924                                 goto out;
8925                         }
8926                 }
8927         }
8928  out:
8929         popstackmark(&smark);
8930
8931         return status;
8932 }
8933
8934 /*
8935  * Kick off a subshell to evaluate a tree.
8936  */
8937 static int
8938 evalsubshell(union node *n, int flags)
8939 {
8940         struct job *jp;
8941         int backgnd = (n->type == NBACKGND); /* FORK_BG(1) if yes, else FORK_FG(0) */
8942         int status;
8943
8944         expredir(n->nredir.redirect);
8945         if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
8946                 goto nofork;
8947         INT_OFF;
8948         if (backgnd == FORK_FG)
8949                 get_tty_state();
8950         jp = makejob(/*n,*/ 1);
8951         if (forkshell(jp, n, backgnd) == 0) {
8952                 /* child */
8953                 INT_ON;
8954                 flags |= EV_EXIT;
8955                 if (backgnd)
8956                         flags &= ~EV_TESTED;
8957  nofork:
8958                 redirect(n->nredir.redirect, 0);
8959                 evaltreenr(n->nredir.n, flags);
8960                 /* never returns */
8961         }
8962         /* parent */
8963         status = 0;
8964         if (backgnd == FORK_FG)
8965                 status = waitforjob(jp);
8966         INT_ON;
8967         return status;
8968 }
8969
8970 /*
8971  * Compute the names of the files in a redirection list.
8972  */
8973 static void fixredir(union node *, const char *, int);
8974 static void
8975 expredir(union node *n)
8976 {
8977         union node *redir;
8978
8979         for (redir = n; redir; redir = redir->nfile.next) {
8980                 struct arglist fn;
8981
8982                 fn.list = NULL;
8983                 fn.lastp = &fn.list;
8984                 switch (redir->type) {
8985                 case NFROMTO:
8986                 case NFROM:
8987                 case NTO:
8988 #if BASH_REDIR_OUTPUT
8989                 case NTO2:
8990 #endif
8991                 case NCLOBBER:
8992                 case NAPPEND:
8993                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
8994                         TRACE(("expredir expanded to '%s'\n", fn.list->text));
8995 #if BASH_REDIR_OUTPUT
8996  store_expfname:
8997 #endif
8998 #if 0
8999 // By the design of stack allocator, the loop of this kind:
9000 //      while true; do while true; do break; done </dev/null; done
9001 // will look like a memory leak: ash plans to free expfname's
9002 // of "/dev/null" as soon as it finishes running the loop
9003 // (in this case, never).
9004 // This "fix" is wrong:
9005                         if (redir->nfile.expfname)
9006                                 stunalloc(redir->nfile.expfname);
9007 // It results in corrupted state of stacked allocations.
9008 #endif
9009                         redir->nfile.expfname = fn.list->text;
9010                         break;
9011                 case NFROMFD:
9012                 case NTOFD: /* >& */
9013                         if (redir->ndup.vname) {
9014                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
9015                                 if (fn.list == NULL)
9016                                         ash_msg_and_raise_error("redir error");
9017 #if BASH_REDIR_OUTPUT
9018 //FIXME: we used expandarg with different args!
9019                                 if (!isdigit_str9(fn.list->text)) {
9020                                         /* >&file, not >&fd */
9021                                         if (redir->nfile.fd != 1) /* 123>&file - BAD */
9022                                                 ash_msg_and_raise_error("redir error");
9023                                         redir->type = NTO2;
9024                                         goto store_expfname;
9025                                 }
9026 #endif
9027                                 fixredir(redir, fn.list->text, 1);
9028                         }
9029                         break;
9030                 }
9031         }
9032 }
9033
9034 /*
9035  * Evaluate a pipeline.  All the processes in the pipeline are children
9036  * of the process creating the pipeline.  (This differs from some versions
9037  * of the shell, which make the last process in a pipeline the parent
9038  * of all the rest.)
9039  */
9040 static int
9041 evalpipe(union node *n, int flags)
9042 {
9043         struct job *jp;
9044         struct nodelist *lp;
9045         int pipelen;
9046         int prevfd;
9047         int pip[2];
9048         int status = 0;
9049
9050         TRACE(("evalpipe(0x%lx) called\n", (long)n));
9051         pipelen = 0;
9052         for (lp = n->npipe.cmdlist; lp; lp = lp->next)
9053                 pipelen++;
9054         flags |= EV_EXIT;
9055         INT_OFF;
9056         if (n->npipe.pipe_backgnd == 0)
9057                 get_tty_state();
9058         jp = makejob(/*n,*/ pipelen);
9059         prevfd = -1;
9060         for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
9061                 prehash(lp->n);
9062                 pip[1] = -1;
9063                 if (lp->next) {
9064                         if (pipe(pip) < 0) {
9065                                 close(prevfd);
9066                                 ash_msg_and_raise_error("pipe call failed");
9067                         }
9068                 }
9069                 if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
9070                         /* child */
9071                         INT_ON;
9072                         if (pip[1] >= 0) {
9073                                 close(pip[0]);
9074                         }
9075                         if (prevfd > 0) {
9076                                 dup2(prevfd, 0);
9077                                 close(prevfd);
9078                         }
9079                         if (pip[1] > 1) {
9080                                 dup2(pip[1], 1);
9081                                 close(pip[1]);
9082                         }
9083                         evaltreenr(lp->n, flags);
9084                         /* never returns */
9085                 }
9086                 /* parent */
9087                 if (prevfd >= 0)
9088                         close(prevfd);
9089                 prevfd = pip[0];
9090                 /* Don't want to trigger debugging */
9091                 if (pip[1] != -1)
9092                         close(pip[1]);
9093         }
9094         if (n->npipe.pipe_backgnd == 0) {
9095                 status = waitforjob(jp);
9096                 TRACE(("evalpipe:  job done exit status %d\n", status));
9097         }
9098         INT_ON;
9099
9100         return status;
9101 }
9102
9103 /*
9104  * Controls whether the shell is interactive or not.
9105  */
9106 static void
9107 setinteractive(int on)
9108 {
9109         static smallint is_interactive;
9110
9111         if (++on == is_interactive)
9112                 return;
9113         is_interactive = on;
9114         setsignal(SIGINT);
9115         setsignal(SIGQUIT);
9116         setsignal(SIGTERM);
9117 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
9118         if (is_interactive > 1) {
9119                 /* Looks like they want an interactive shell */
9120                 static smallint did_banner;
9121
9122                 if (!did_banner) {
9123                         /* note: ash and hush share this string */
9124                         out1fmt("\n\n%s %s\n"
9125                                 IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
9126                                 "\n",
9127                                 bb_banner,
9128                                 "built-in shell (ash)"
9129                         );
9130                         did_banner = 1;
9131                 }
9132         }
9133 #endif
9134 }
9135
9136 static void
9137 optschanged(void)
9138 {
9139 #if DEBUG
9140         opentrace();
9141 #endif
9142         setinteractive(iflag);
9143         setjobctl(mflag);
9144 #if ENABLE_FEATURE_EDITING_VI
9145         if (viflag)
9146                 line_input_state->flags |= VI_MODE;
9147         else
9148                 line_input_state->flags &= ~VI_MODE;
9149 #else
9150         viflag = 0; /* forcibly keep the option off */
9151 #endif
9152 }
9153
9154 struct localvar_list {
9155         struct localvar_list *next;
9156         struct localvar *lv;
9157 };
9158
9159 static struct localvar_list *localvar_stack;
9160
9161 /*
9162  * Called after a function returns.
9163  * Interrupts must be off.
9164  */
9165 static void
9166 poplocalvars(int keep)
9167 {
9168         struct localvar_list *ll;
9169         struct localvar *lvp, *next;
9170         struct var *vp;
9171
9172         INT_OFF;
9173         ll = localvar_stack;
9174         localvar_stack = ll->next;
9175
9176         next = ll->lv;
9177         free(ll);
9178
9179         while ((lvp = next) != NULL) {
9180                 next = lvp->next;
9181                 vp = lvp->vp;
9182                 TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
9183                 if (keep) {
9184                         int bits = VSTRFIXED;
9185
9186                         if (lvp->flags != VUNSET) {
9187                                 if (vp->var_text == lvp->text)
9188                                         bits |= VTEXTFIXED;
9189                                 else if (!(lvp->flags & (VTEXTFIXED|VSTACK)))
9190                                         free((char*)lvp->text);
9191                         }
9192
9193                         vp->flags &= ~bits;
9194                         vp->flags |= (lvp->flags & bits);
9195
9196                         if ((vp->flags &
9197                              (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
9198                                 unsetvar(vp->var_text);
9199                 } else 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 struct localvar_list *
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         return ll->next;
9235 }
9236
9237 static void
9238 unwindlocalvars(struct localvar_list *stop)
9239 {
9240         while (localvar_stack != stop)
9241                 poplocalvars(0);
9242 }
9243
9244 static int
9245 evalfun(struct funcnode *func, int argc, char **argv, int flags)
9246 {
9247         volatile struct shparam saveparam;
9248         struct jmploc *volatile savehandler;
9249         struct jmploc jmploc;
9250         int e;
9251
9252         saveparam = shellparam;
9253         savehandler = exception_handler;
9254         e = setjmp(jmploc.loc);
9255         if (e) {
9256                 goto funcdone;
9257         }
9258         INT_OFF;
9259         exception_handler = &jmploc;
9260         shellparam.malloced = 0;
9261         func->count++;
9262         funcnest++;
9263         INT_ON;
9264         shellparam.nparam = argc - 1;
9265         shellparam.p = argv + 1;
9266 #if ENABLE_ASH_GETOPTS
9267         shellparam.optind = 1;
9268         shellparam.optoff = -1;
9269 #endif
9270         pushlocalvars();
9271         evaltree(func->n.narg.next, flags & EV_TESTED);
9272         poplocalvars(0);
9273  funcdone:
9274         INT_OFF;
9275         funcnest--;
9276         freefunc(func);
9277         freeparam(&shellparam);
9278         shellparam = saveparam;
9279         exception_handler = savehandler;
9280         INT_ON;
9281         evalskip &= ~SKIPFUNC;
9282         return e;
9283 }
9284
9285 /*
9286  * Make a variable a local variable.  When a variable is made local, it's
9287  * value and flags are saved in a localvar structure.  The saved values
9288  * will be restored when the shell function returns.  We handle the name
9289  * "-" as a special case: it makes changes to "set +-options" local
9290  * (options will be restored on return from the function).
9291  */
9292 static void
9293 mklocal(char *name)
9294 {
9295         struct localvar *lvp;
9296         struct var **vpp;
9297         struct var *vp;
9298         char *eq = strchr(name, '=');
9299
9300         INT_OFF;
9301         /* Cater for duplicate "local". Examples:
9302          * x=0; f() { local x=1; echo $x; local x; echo $x; }; f; echo $x
9303          * x=0; f() { local x=1; echo $x; local x=2; echo $x; }; f; echo $x
9304          */
9305         lvp = localvar_stack->lv;
9306         while (lvp) {
9307                 if (lvp->vp && varcmp(lvp->vp->var_text, name) == 0) {
9308                         if (eq)
9309                                 setvareq(name, 0);
9310                         /* else:
9311                          * it's a duplicate "local VAR" declaration, do nothing
9312                          */
9313                         goto ret;
9314                 }
9315                 lvp = lvp->next;
9316         }
9317
9318         lvp = ckzalloc(sizeof(*lvp));
9319         if (LONE_DASH(name)) {
9320                 char *p;
9321                 p = ckmalloc(sizeof(optlist));
9322                 lvp->text = memcpy(p, optlist, sizeof(optlist));
9323                 vp = NULL;
9324         } else {
9325                 vpp = hashvar(name);
9326                 vp = *findvar(vpp, name);
9327                 if (vp == NULL) {
9328                         /* variable did not exist yet */
9329                         if (eq)
9330                                 vp = setvareq(name, VSTRFIXED);
9331                         else
9332                                 vp = setvar(name, NULL, VSTRFIXED);
9333                         lvp->flags = VUNSET;
9334                 } else {
9335                         lvp->text = vp->var_text;
9336                         lvp->flags = vp->flags;
9337                         /* make sure neither "struct var" nor string gets freed
9338                          * during (un)setting:
9339                          */
9340                         vp->flags |= VSTRFIXED|VTEXTFIXED;
9341                         if (eq)
9342                                 setvareq(name, 0);
9343                         else
9344                                 /* "local VAR" unsets VAR: */
9345                                 setvar0(name, NULL);
9346                 }
9347         }
9348         lvp->vp = vp;
9349         lvp->next = localvar_stack->lv;
9350         localvar_stack->lv = lvp;
9351  ret:
9352         INT_ON;
9353 }
9354
9355 /*
9356  * The "local" command.
9357  */
9358 static int FAST_FUNC
9359 localcmd(int argc UNUSED_PARAM, char **argv)
9360 {
9361         char *name;
9362
9363         if (!localvar_stack)
9364                 ash_msg_and_raise_error("not in a function");
9365
9366         argv = argptr;
9367         while ((name = *argv++) != NULL) {
9368                 mklocal(name);
9369         }
9370         return 0;
9371 }
9372
9373 static int FAST_FUNC
9374 falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9375 {
9376         return 1;
9377 }
9378
9379 static int FAST_FUNC
9380 truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9381 {
9382         return 0;
9383 }
9384
9385 static int FAST_FUNC
9386 execcmd(int argc UNUSED_PARAM, char **argv)
9387 {
9388         optionarg = NULL;
9389         while (nextopt("a:") != '\0')
9390                 /* nextopt() sets optionarg to "-a ARGV0" */;
9391
9392         argv = argptr;
9393         if (argv[0]) {
9394                 char *prog;
9395
9396                 iflag = 0;              /* exit on error */
9397                 mflag = 0;
9398                 optschanged();
9399                 /* We should set up signals for "exec CMD"
9400                  * the same way as for "CMD" without "exec".
9401                  * But optschanged->setinteractive->setsignal
9402                  * still thought we are a root shell. Therefore, for example,
9403                  * SIGQUIT is still set to IGN. Fix it:
9404                  */
9405                 shlvl++;
9406                 setsignal(SIGQUIT);
9407                 /*setsignal(SIGTERM); - unnecessary because of iflag=0 */
9408                 /*setsignal(SIGTSTP); - unnecessary because of mflag=0 */
9409                 /*setsignal(SIGTTOU); - unnecessary because of mflag=0 */
9410
9411                 prog = argv[0];
9412                 if (optionarg)
9413                         argv[0] = optionarg;
9414                 shellexec(prog, argv, pathval(), 0);
9415                 /* NOTREACHED */
9416         }
9417         return 0;
9418 }
9419
9420 /*
9421  * The return command.
9422  */
9423 static int FAST_FUNC
9424 returncmd(int argc UNUSED_PARAM, char **argv)
9425 {
9426         /*
9427          * If called outside a function, do what ksh does;
9428          * skip the rest of the file.
9429          */
9430         evalskip = SKIPFUNC;
9431         return argv[1] ? number(argv[1]) : exitstatus;
9432 }
9433
9434 /* Forward declarations for builtintab[] */
9435 static int breakcmd(int, char **) FAST_FUNC;
9436 static int dotcmd(int, char **) FAST_FUNC;
9437 static int evalcmd(int, char **, int) FAST_FUNC;
9438 static int exitcmd(int, char **) FAST_FUNC;
9439 static int exportcmd(int, char **) FAST_FUNC;
9440 #if ENABLE_ASH_GETOPTS
9441 static int getoptscmd(int, char **) FAST_FUNC;
9442 #endif
9443 #if ENABLE_ASH_HELP
9444 static int helpcmd(int, char **) FAST_FUNC;
9445 #endif
9446 #if MAX_HISTORY
9447 static int historycmd(int, char **) FAST_FUNC;
9448 #endif
9449 #if ENABLE_FEATURE_SH_MATH
9450 static int letcmd(int, char **) FAST_FUNC;
9451 #endif
9452 static int readcmd(int, char **) FAST_FUNC;
9453 static int setcmd(int, char **) FAST_FUNC;
9454 static int shiftcmd(int, char **) FAST_FUNC;
9455 static int timescmd(int, char **) FAST_FUNC;
9456 static int trapcmd(int, char **) FAST_FUNC;
9457 static int umaskcmd(int, char **) FAST_FUNC;
9458 static int unsetcmd(int, char **) FAST_FUNC;
9459 static int ulimitcmd(int, char **) FAST_FUNC;
9460
9461 #define BUILTIN_NOSPEC          "0"
9462 #define BUILTIN_SPECIAL         "1"
9463 #define BUILTIN_REGULAR         "2"
9464 #define BUILTIN_SPEC_REG        "3"
9465 #define BUILTIN_ASSIGN          "4"
9466 #define BUILTIN_SPEC_ASSG       "5"
9467 #define BUILTIN_REG_ASSG        "6"
9468 #define BUILTIN_SPEC_REG_ASSG   "7"
9469
9470 /* Stubs for calling non-FAST_FUNC's */
9471 #if ENABLE_ASH_ECHO
9472 static int FAST_FUNC echocmd(int argc, char **argv)   { return echo_main(argc, argv); }
9473 #endif
9474 #if ENABLE_ASH_PRINTF
9475 static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9476 #endif
9477 #if ENABLE_ASH_TEST || BASH_TEST2
9478 static int FAST_FUNC testcmd(int argc, char **argv)   { return test_main(argc, argv); }
9479 #endif
9480
9481 /* Keep these in proper order since it is searched via bsearch() */
9482 static const struct builtincmd builtintab[] = {
9483         { BUILTIN_SPEC_REG      "."       , dotcmd     },
9484         { BUILTIN_SPEC_REG      ":"       , truecmd    },
9485 #if ENABLE_ASH_TEST
9486         { BUILTIN_REGULAR       "["       , testcmd    },
9487 #endif
9488 #if BASH_TEST2
9489         { BUILTIN_REGULAR       "[["      , testcmd    },
9490 #endif
9491 #if ENABLE_ASH_ALIAS
9492         { BUILTIN_REG_ASSG      "alias"   , aliascmd   },
9493 #endif
9494 #if JOBS
9495         { BUILTIN_REGULAR       "bg"      , fg_bgcmd   },
9496 #endif
9497         { BUILTIN_SPEC_REG      "break"   , breakcmd   },
9498         { BUILTIN_REGULAR       "cd"      , cdcmd      },
9499         { BUILTIN_NOSPEC        "chdir"   , cdcmd      },
9500 #if ENABLE_ASH_CMDCMD
9501         { BUILTIN_REGULAR       "command" , commandcmd },
9502 #endif
9503         { BUILTIN_SPEC_REG      "continue", breakcmd   },
9504 #if ENABLE_ASH_ECHO
9505         { BUILTIN_REGULAR       "echo"    , echocmd    },
9506 #endif
9507         { BUILTIN_SPEC_REG      "eval"    , NULL       }, /*evalcmd() has a differing prototype*/
9508         { BUILTIN_SPEC_REG      "exec"    , execcmd    },
9509         { BUILTIN_SPEC_REG      "exit"    , exitcmd    },
9510         { BUILTIN_SPEC_REG_ASSG "export"  , exportcmd  },
9511         { BUILTIN_REGULAR       "false"   , falsecmd   },
9512 #if JOBS
9513         { BUILTIN_REGULAR       "fg"      , fg_bgcmd   },
9514 #endif
9515 #if ENABLE_ASH_GETOPTS
9516         { BUILTIN_REGULAR       "getopts" , getoptscmd },
9517 #endif
9518         { BUILTIN_NOSPEC        "hash"    , hashcmd    },
9519 #if ENABLE_ASH_HELP
9520         { BUILTIN_NOSPEC        "help"    , helpcmd    },
9521 #endif
9522 #if MAX_HISTORY
9523         { BUILTIN_NOSPEC        "history" , historycmd },
9524 #endif
9525 #if JOBS
9526         { BUILTIN_REGULAR       "jobs"    , jobscmd    },
9527         { BUILTIN_REGULAR       "kill"    , killcmd    },
9528 #endif
9529 #if ENABLE_FEATURE_SH_MATH
9530         { BUILTIN_NOSPEC        "let"     , letcmd     },
9531 #endif
9532         { BUILTIN_SPEC_REG_ASSG "local"   , localcmd   },
9533 #if ENABLE_ASH_PRINTF
9534         { BUILTIN_REGULAR       "printf"  , printfcmd  },
9535 #endif
9536         { BUILTIN_NOSPEC        "pwd"     , pwdcmd     },
9537         { BUILTIN_REGULAR       "read"    , readcmd    },
9538         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd  },
9539         { BUILTIN_SPEC_REG      "return"  , returncmd  },
9540         { BUILTIN_SPEC_REG      "set"     , setcmd     },
9541         { BUILTIN_SPEC_REG      "shift"   , shiftcmd   },
9542 #if BASH_SOURCE
9543         { BUILTIN_SPEC_REG      "source"  , dotcmd     },
9544 #endif
9545 #if ENABLE_ASH_TEST
9546         { BUILTIN_REGULAR       "test"    , testcmd    },
9547 #endif
9548         { BUILTIN_SPEC_REG      "times"   , timescmd   },
9549         { BUILTIN_SPEC_REG      "trap"    , trapcmd    },
9550         { BUILTIN_REGULAR       "true"    , truecmd    },
9551         { BUILTIN_NOSPEC        "type"    , typecmd    },
9552         { BUILTIN_NOSPEC        "ulimit"  , ulimitcmd  },
9553         { BUILTIN_REGULAR       "umask"   , umaskcmd   },
9554 #if ENABLE_ASH_ALIAS
9555         { BUILTIN_REGULAR       "unalias" , unaliascmd },
9556 #endif
9557         { BUILTIN_SPEC_REG      "unset"   , unsetcmd   },
9558         { BUILTIN_REGULAR       "wait"    , waitcmd    },
9559 };
9560
9561 /* Should match the above table! */
9562 #define COMMANDCMD (builtintab + \
9563         /* . : */       2 + \
9564         /* [ */         1 * ENABLE_ASH_TEST + \
9565         /* [[ */        1 * BASH_TEST2 + \
9566         /* alias */     1 * ENABLE_ASH_ALIAS + \
9567         /* bg */        1 * ENABLE_ASH_JOB_CONTROL + \
9568         /* break cd cddir  */   3)
9569 #define EVALCMD (COMMANDCMD + \
9570         /* command */   1 * ENABLE_ASH_CMDCMD + \
9571         /* continue */  1 + \
9572         /* echo */      1 * ENABLE_ASH_ECHO + \
9573         0)
9574 #define EXECCMD (EVALCMD + \
9575         /* eval */      1)
9576
9577 /*
9578  * Search the table of builtin commands.
9579  */
9580 static int
9581 pstrcmp1(const void *a, const void *b)
9582 {
9583         return strcmp((char*)a, *(char**)b + 1);
9584 }
9585 static struct builtincmd *
9586 find_builtin(const char *name)
9587 {
9588         struct builtincmd *bp;
9589
9590         bp = bsearch(
9591                 name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
9592                 pstrcmp1
9593         );
9594         return bp;
9595 }
9596
9597 /*
9598  * Execute a simple command.
9599  */
9600 static int
9601 isassignment(const char *p)
9602 {
9603         const char *q = endofname(p);
9604         if (p == q)
9605                 return 0;
9606         return *q == '=';
9607 }
9608 static int FAST_FUNC
9609 bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
9610 {
9611         /* Preserve exitstatus of a previous possible redirection
9612          * as POSIX mandates */
9613         return back_exitstatus;
9614 }
9615 static int
9616 evalcommand(union node *cmd, int flags)
9617 {
9618         static const struct builtincmd null_bltin = {
9619                 "\0\0", bltincmd /* why three NULs? */
9620         };
9621         struct localvar_list *localvar_stop;
9622         struct stackmark smark;
9623         union node *argp;
9624         struct arglist arglist;
9625         struct arglist varlist;
9626         char **argv;
9627         int argc;
9628         const struct strlist *sp;
9629         struct cmdentry cmdentry;
9630         struct job *jp;
9631         char *lastarg;
9632         const char *path;
9633         int spclbltin;
9634         int status;
9635         char **nargv;
9636         struct builtincmd *bcmd;
9637         smallint cmd_is_exec;
9638         smallint pseudovarflag = 0;
9639
9640         /* First expand the arguments. */
9641         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
9642         setstackmark(&smark);
9643         localvar_stop = pushlocalvars();
9644         back_exitstatus = 0;
9645
9646         cmdentry.cmdtype = CMDBUILTIN;
9647         cmdentry.u.cmd = &null_bltin;
9648         varlist.lastp = &varlist.list;
9649         *varlist.lastp = NULL;
9650         arglist.lastp = &arglist.list;
9651         *arglist.lastp = NULL;
9652
9653         argc = 0;
9654         if (cmd->ncmd.args) {
9655                 bcmd = find_builtin(cmd->ncmd.args->narg.text);
9656                 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
9657         }
9658
9659         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
9660                 struct strlist **spp;
9661
9662                 spp = arglist.lastp;
9663                 if (pseudovarflag && isassignment(argp->narg.text))
9664                         expandarg(argp, &arglist, EXP_VARTILDE);
9665                 else
9666                         expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
9667
9668                 for (sp = *spp; sp; sp = sp->next)
9669                         argc++;
9670         }
9671
9672         /* Reserve one extra spot at the front for shellexec. */
9673         nargv = stalloc(sizeof(char *) * (argc + 2));
9674         argv = ++nargv;
9675         for (sp = arglist.list; sp; sp = sp->next) {
9676                 TRACE(("evalcommand arg: %s\n", sp->text));
9677                 *nargv++ = sp->text;
9678         }
9679         *nargv = NULL;
9680
9681         lastarg = NULL;
9682         if (iflag && funcnest == 0 && argc > 0)
9683                 lastarg = nargv[-1];
9684
9685         preverrout_fd = 2;
9686         expredir(cmd->ncmd.redirect);
9687         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
9688
9689         path = vpath.var_text;
9690         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
9691                 struct strlist **spp;
9692                 char *p;
9693
9694                 spp = varlist.lastp;
9695                 expandarg(argp, &varlist, EXP_VARTILDE);
9696
9697                 mklocal((*spp)->text);
9698
9699                 /*
9700                  * Modify the command lookup path, if a PATH= assignment
9701                  * is present
9702                  */
9703                 p = (*spp)->text;
9704                 if (varcmp(p, path) == 0)
9705                         path = p;
9706         }
9707
9708         /* Print the command if xflag is set. */
9709         if (xflag) {
9710                 const char *pfx = "";
9711
9712                 fdprintf(preverrout_fd, "%s", expandstr(ps4val()));
9713
9714                 sp = varlist.list;
9715                 while (sp) {
9716                         char *varval = sp->text;
9717                         char *eq = strchrnul(varval, '=');
9718                         if (*eq)
9719                                 eq++;
9720                         fdprintf(preverrout_fd, "%s%.*s%s",
9721                                 pfx,
9722                                 (int)(eq - varval), varval,
9723                                 maybe_single_quote(eq)
9724                         );
9725                         sp = sp->next;
9726                         pfx = " ";
9727                 }
9728
9729                 sp = arglist.list;
9730                 while (sp) {
9731                         fdprintf(preverrout_fd, "%s%s",
9732                                 pfx,
9733                                 /* always quote if matches reserved word: */
9734                                 findkwd(sp->text)
9735                                 ? single_quote(sp->text)
9736                                 : maybe_single_quote(sp->text)
9737                         );
9738                         sp = sp->next;
9739                         pfx = " ";
9740                 }
9741                 safe_write(preverrout_fd, "\n", 1);
9742         }
9743
9744         cmd_is_exec = 0;
9745         spclbltin = -1;
9746
9747         /* Now locate the command. */
9748         if (argc) {
9749                 int cmd_flag = DO_ERR;
9750 #if ENABLE_ASH_CMDCMD
9751                 const char *oldpath = path + 5;
9752 #endif
9753                 path += 5;
9754                 for (;;) {
9755                         find_command(argv[0], &cmdentry, cmd_flag, path);
9756                         if (cmdentry.cmdtype == CMDUNKNOWN) {
9757                                 flush_stdout_stderr();
9758                                 status = 127;
9759                                 goto bail;
9760                         }
9761
9762                         /* implement bltin and command here */
9763                         if (cmdentry.cmdtype != CMDBUILTIN)
9764                                 break;
9765                         if (spclbltin < 0)
9766                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
9767                         if (cmdentry.u.cmd == EXECCMD)
9768                                 cmd_is_exec = 1;
9769 #if ENABLE_ASH_CMDCMD
9770                         if (cmdentry.u.cmd == COMMANDCMD) {
9771                                 path = oldpath;
9772                                 nargv = parse_command_args(argv, &path);
9773                                 if (!nargv)
9774                                         break;
9775                                 /* It's "command [-p] PROG ARGS" (that is, no -Vv).
9776                                  * nargv => "PROG". path is updated if -p.
9777                                  */
9778                                 argc -= nargv - argv;
9779                                 argv = nargv;
9780                                 cmd_flag |= DO_NOFUNC;
9781                         } else
9782 #endif
9783                                 break;
9784                 }
9785         }
9786
9787         if (status) {
9788  bail:
9789                 exitstatus = status;
9790
9791                 /* We have a redirection error. */
9792                 if (spclbltin > 0)
9793                         raise_exception(EXERROR);
9794
9795                 goto out;
9796         }
9797
9798         /* Execute the command. */
9799         switch (cmdentry.cmdtype) {
9800         default: {
9801
9802 #if ENABLE_FEATURE_SH_NOFORK
9803 /* (1) BUG: if variables are set, we need to fork, or save/restore them
9804  *     around run_nofork_applet() call.
9805  * (2) Should this check also be done in forkshell()?
9806  *     (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
9807  */
9808                 /* find_command() encodes applet_no as (-2 - applet_no) */
9809                 int applet_no = (- cmdentry.u.index - 2);
9810                 if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
9811                         listsetvar(varlist.list, VEXPORT|VSTACK);
9812                         /* run <applet>_main() */
9813                         status = run_nofork_applet(applet_no, argv);
9814                         break;
9815                 }
9816 #endif
9817                 /* Can we avoid forking off? For example, very last command
9818                  * in a script or a subshell does not need forking,
9819                  * we can just exec it.
9820                  */
9821                 if (!(flags & EV_EXIT) || may_have_traps) {
9822                         /* No, forking off a child is necessary */
9823                         INT_OFF;
9824                         get_tty_state();
9825                         jp = makejob(/*cmd,*/ 1);
9826                         if (forkshell(jp, cmd, FORK_FG) != 0) {
9827                                 /* parent */
9828                                 status = waitforjob(jp);
9829                                 INT_ON;
9830                                 TRACE(("forked child exited with %d\n", status));
9831                                 break;
9832                         }
9833                         /* child */
9834                         FORCE_INT_ON;
9835                         /* fall through to exec'ing external program */
9836                 }
9837                 listsetvar(varlist.list, VEXPORT|VSTACK);
9838                 shellexec(argv[0], argv, path, cmdentry.u.index);
9839                 /* NOTREACHED */
9840         } /* default */
9841         case CMDBUILTIN:
9842                 if (spclbltin > 0 || argc == 0) {
9843                         poplocalvars(1);
9844                         if (cmd_is_exec && argc > 1)
9845                                 listsetvar(varlist.list, VEXPORT);
9846                 }
9847
9848                 /* Tight loop with builtins only:
9849                  * "while kill -0 $child; do true; done"
9850                  * will never exit even if $child died, unless we do this
9851                  * to reap the zombie and make kill detect that it's gone: */
9852                 dowait(DOWAIT_NONBLOCK, NULL);
9853
9854                 if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {
9855                         if (exception_type == EXERROR && spclbltin <= 0) {
9856                                 FORCE_INT_ON;
9857                                 goto readstatus;
9858                         }
9859  raise:
9860                         longjmp(exception_handler->loc, 1);
9861                 }
9862                 goto readstatus;
9863
9864         case CMDFUNCTION:
9865                 poplocalvars(1);
9866                 /* See above for the rationale */
9867                 dowait(DOWAIT_NONBLOCK, NULL);
9868                 if (evalfun(cmdentry.u.func, argc, argv, flags))
9869                         goto raise;
9870  readstatus:
9871                 status = exitstatus;
9872                 break;
9873         } /* switch */
9874
9875  out:
9876         if (cmd->ncmd.redirect)
9877                 popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
9878         unwindlocalvars(localvar_stop);
9879         if (lastarg) {
9880                 /* dsl: I think this is intended to be used to support
9881                  * '_' in 'vi' command mode during line editing...
9882                  * However I implemented that within libedit itself.
9883                  */
9884                 setvar0("_", lastarg);
9885         }
9886         popstackmark(&smark);
9887
9888         return status;
9889 }
9890
9891 static int
9892 evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
9893 {
9894         char *volatile savecmdname;
9895         struct jmploc *volatile savehandler;
9896         struct jmploc jmploc;
9897         int status;
9898         int i;
9899
9900         savecmdname = commandname;
9901         savehandler = exception_handler;
9902         i = setjmp(jmploc.loc);
9903         if (i)
9904                 goto cmddone;
9905         exception_handler = &jmploc;
9906         commandname = argv[0];
9907         argptr = argv + 1;
9908         optptr = NULL;                  /* initialize nextopt */
9909         if (cmd == EVALCMD)
9910                 status = evalcmd(argc, argv, flags);
9911         else
9912                 status = (*cmd->builtin)(argc, argv);
9913         flush_stdout_stderr();
9914         status |= ferror(stdout);
9915         exitstatus = status;
9916  cmddone:
9917         clearerr(stdout);
9918         commandname = savecmdname;
9919         exception_handler = savehandler;
9920
9921         return i;
9922 }
9923
9924 static int
9925 goodname(const char *p)
9926 {
9927         return endofname(p)[0] == '\0';
9928 }
9929
9930
9931 /*
9932  * Search for a command.  This is called before we fork so that the
9933  * location of the command will be available in the parent as well as
9934  * the child.  The check for "goodname" is an overly conservative
9935  * check that the name will not be subject to expansion.
9936  */
9937 static void
9938 prehash(union node *n)
9939 {
9940         struct cmdentry entry;
9941
9942         if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
9943                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
9944 }
9945
9946
9947 /* ============ Builtin commands
9948  *
9949  * Builtin commands whose functions are closely tied to evaluation
9950  * are implemented here.
9951  */
9952
9953 /*
9954  * Handle break and continue commands.  Break, continue, and return are
9955  * all handled by setting the evalskip flag.  The evaluation routines
9956  * above all check this flag, and if it is set they start skipping
9957  * commands rather than executing them.  The variable skipcount is
9958  * the number of loops to break/continue, or the number of function
9959  * levels to return.  (The latter is always 1.)  It should probably
9960  * be an error to break out of more loops than exist, but it isn't
9961  * in the standard shell so we don't make it one here.
9962  */
9963 static int FAST_FUNC
9964 breakcmd(int argc UNUSED_PARAM, char **argv)
9965 {
9966         int n = argv[1] ? number(argv[1]) : 1;
9967
9968         if (n <= 0)
9969                 ash_msg_and_raise_error(msg_illnum, argv[1]);
9970         if (n > loopnest)
9971                 n = loopnest;
9972         if (n > 0) {
9973                 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
9974                 skipcount = n;
9975         }
9976         return 0;
9977 }
9978
9979
9980 /*
9981  * This implements the input routines used by the parser.
9982  */
9983
9984 enum {
9985         INPUT_PUSH_FILE = 1,
9986         INPUT_NOFILE_OK = 2,
9987 };
9988
9989 static smallint checkkwd;
9990 /* values of checkkwd variable */
9991 #define CHKALIAS        0x1
9992 #define CHKKWD          0x2
9993 #define CHKNL           0x4
9994
9995 /*
9996  * Push a string back onto the input at this current parsefile level.
9997  * We handle aliases this way.
9998  */
9999 #if !ENABLE_ASH_ALIAS
10000 #define pushstring(s, ap) pushstring(s)
10001 #endif
10002 static void
10003 pushstring(char *s, struct alias *ap)
10004 {
10005         struct strpush *sp;
10006         int len;
10007
10008         len = strlen(s);
10009         INT_OFF;
10010         if (g_parsefile->strpush) {
10011                 sp = ckzalloc(sizeof(*sp));
10012                 sp->prev = g_parsefile->strpush;
10013         } else {
10014                 sp = &(g_parsefile->basestrpush);
10015         }
10016         g_parsefile->strpush = sp;
10017         sp->prev_string = g_parsefile->next_to_pgetc;
10018         sp->prev_left_in_line = g_parsefile->left_in_line;
10019         sp->unget = g_parsefile->unget;
10020         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10021 #if ENABLE_ASH_ALIAS
10022         sp->ap = ap;
10023         if (ap) {
10024                 ap->flag |= ALIASINUSE;
10025                 sp->string = s;
10026         }
10027 #endif
10028         g_parsefile->next_to_pgetc = s;
10029         g_parsefile->left_in_line = len;
10030         g_parsefile->unget = 0;
10031         INT_ON;
10032 }
10033
10034 static void
10035 popstring(void)
10036 {
10037         struct strpush *sp = g_parsefile->strpush;
10038
10039         INT_OFF;
10040 #if ENABLE_ASH_ALIAS
10041         if (sp->ap) {
10042                 if (g_parsefile->next_to_pgetc[-1] == ' '
10043                  || g_parsefile->next_to_pgetc[-1] == '\t'
10044                 ) {
10045                         checkkwd |= CHKALIAS;
10046                 }
10047                 if (sp->string != sp->ap->val) {
10048                         free(sp->string);
10049                 }
10050                 sp->ap->flag &= ~ALIASINUSE;
10051                 if (sp->ap->flag & ALIASDEAD) {
10052                         unalias(sp->ap->name);
10053                 }
10054         }
10055 #endif
10056         g_parsefile->next_to_pgetc = sp->prev_string;
10057         g_parsefile->left_in_line = sp->prev_left_in_line;
10058         g_parsefile->unget = sp->unget;
10059         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10060         g_parsefile->strpush = sp->prev;
10061         if (sp != &(g_parsefile->basestrpush))
10062                 free(sp);
10063         INT_ON;
10064 }
10065
10066 static int
10067 preadfd(void)
10068 {
10069         int nr;
10070         char *buf = g_parsefile->buf;
10071
10072         g_parsefile->next_to_pgetc = buf;
10073 #if ENABLE_FEATURE_EDITING
10074  retry:
10075         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10076                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10077         else {
10078                 int timeout = -1;
10079 # if ENABLE_ASH_IDLE_TIMEOUT
10080                 if (iflag) {
10081                         const char *tmout_var = lookupvar("TMOUT");
10082                         if (tmout_var) {
10083                                 timeout = atoi(tmout_var) * 1000;
10084                                 if (timeout <= 0)
10085                                         timeout = -1;
10086                         }
10087                 }
10088 # endif
10089 # if ENABLE_FEATURE_TAB_COMPLETION
10090                 line_input_state->path_lookup = pathval();
10091 # endif
10092                 reinit_unicode_for_ash();
10093                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
10094                 if (nr == 0) {
10095                         /* ^C pressed, "convert" to SIGINT */
10096                         write(STDOUT_FILENO, "^C", 2);
10097                         if (trap[SIGINT]) {
10098                                 buf[0] = '\n';
10099                                 buf[1] = '\0';
10100                                 raise(SIGINT);
10101                                 return 1;
10102                         }
10103                         exitstatus = 128 + SIGINT;
10104                         bb_putchar('\n');
10105                         goto retry;
10106                 }
10107                 if (nr < 0) {
10108                         if (errno == 0) {
10109                                 /* Ctrl+D pressed */
10110                                 nr = 0;
10111                         }
10112 # if ENABLE_ASH_IDLE_TIMEOUT
10113                         else if (errno == EAGAIN && timeout > 0) {
10114                                 puts("\007timed out waiting for input: auto-logout");
10115                                 exitshell();
10116                         }
10117 # endif
10118                 }
10119         }
10120 #else
10121         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10122 #endif
10123
10124 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10125         if (nr < 0) {
10126                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10127                         int flags = fcntl(0, F_GETFL);
10128                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10129                                 flags &= ~O_NONBLOCK;
10130                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10131                                         out2str("sh: turning off NDELAY mode\n");
10132                                         goto retry;
10133                                 }
10134                         }
10135                 }
10136         }
10137 #endif
10138         return nr;
10139 }
10140
10141 /*
10142  * Refill the input buffer and return the next input character:
10143  *
10144  * 1) If a string was pushed back on the input, pop it;
10145  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10146  *    or we are reading from a string so we can't refill the buffer,
10147  *    return EOF.
10148  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10149  * 4) Process input up to the next newline, deleting nul characters.
10150  */
10151 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10152 #define pgetc_debug(...) ((void)0)
10153 static int pgetc(void);
10154 static int
10155 preadbuffer(void)
10156 {
10157         char *q;
10158         int more;
10159
10160         if (g_parsefile->strpush) {
10161 #if ENABLE_ASH_ALIAS
10162                 if (g_parsefile->left_in_line == -1
10163                  && g_parsefile->strpush->ap
10164                  && g_parsefile->next_to_pgetc[-1] != ' '
10165                  && g_parsefile->next_to_pgetc[-1] != '\t'
10166                 ) {
10167                         pgetc_debug("preadbuffer PEOA");
10168                         return PEOA;
10169                 }
10170 #endif
10171                 popstring();
10172                 return pgetc();
10173         }
10174         /* on both branches above g_parsefile->left_in_line < 0.
10175          * "pgetc" needs refilling.
10176          */
10177
10178         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10179          * pungetc() may increment it a few times.
10180          * Assuming it won't increment it to less than -90.
10181          */
10182         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10183                 pgetc_debug("preadbuffer PEOF1");
10184                 /* even in failure keep left_in_line and next_to_pgetc
10185                  * in lock step, for correct multi-layer pungetc.
10186                  * left_in_line was decremented before preadbuffer(),
10187                  * must inc next_to_pgetc: */
10188                 g_parsefile->next_to_pgetc++;
10189                 return PEOF;
10190         }
10191
10192         more = g_parsefile->left_in_buffer;
10193         if (more <= 0) {
10194                 flush_stdout_stderr();
10195  again:
10196                 more = preadfd();
10197                 if (more <= 0) {
10198                         /* don't try reading again */
10199                         g_parsefile->left_in_line = -99;
10200                         pgetc_debug("preadbuffer PEOF2");
10201                         g_parsefile->next_to_pgetc++;
10202                         return PEOF;
10203                 }
10204         }
10205
10206         /* Find out where's the end of line.
10207          * Set g_parsefile->left_in_line
10208          * and g_parsefile->left_in_buffer acordingly.
10209          * NUL chars are deleted.
10210          */
10211         q = g_parsefile->next_to_pgetc;
10212         for (;;) {
10213                 char c;
10214
10215                 more--;
10216
10217                 c = *q;
10218                 if (c == '\0') {
10219                         memmove(q, q + 1, more);
10220                 } else {
10221                         q++;
10222                         if (c == '\n') {
10223                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10224                                 break;
10225                         }
10226                 }
10227
10228                 if (more <= 0) {
10229                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10230                         if (g_parsefile->left_in_line < 0)
10231                                 goto again;
10232                         break;
10233                 }
10234         }
10235         g_parsefile->left_in_buffer = more;
10236
10237         if (vflag) {
10238                 char save = *q;
10239                 *q = '\0';
10240                 out2str(g_parsefile->next_to_pgetc);
10241                 *q = save;
10242         }
10243
10244         pgetc_debug("preadbuffer at %d:%p'%s'",
10245                         g_parsefile->left_in_line,
10246                         g_parsefile->next_to_pgetc,
10247                         g_parsefile->next_to_pgetc);
10248         return (unsigned char)*g_parsefile->next_to_pgetc++;
10249 }
10250
10251 static void
10252 nlprompt(void)
10253 {
10254         g_parsefile->linno++;
10255         setprompt_if(doprompt, 2);
10256 }
10257 static void
10258 nlnoprompt(void)
10259 {
10260         g_parsefile->linno++;
10261         needprompt = doprompt;
10262 }
10263
10264 static int
10265 pgetc(void)
10266 {
10267         int c;
10268
10269         pgetc_debug("pgetc at %d:%p'%s'",
10270                         g_parsefile->left_in_line,
10271                         g_parsefile->next_to_pgetc,
10272                         g_parsefile->next_to_pgetc);
10273         if (g_parsefile->unget)
10274                 return g_parsefile->lastc[--g_parsefile->unget];
10275
10276         if (--g_parsefile->left_in_line >= 0)
10277                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10278         else
10279                 c = preadbuffer();
10280
10281         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10282         g_parsefile->lastc[0] = c;
10283
10284         return c;
10285 }
10286
10287 #if ENABLE_ASH_ALIAS
10288 static int
10289 pgetc_without_PEOA(void)
10290 {
10291         int c;
10292         do {
10293                 pgetc_debug("pgetc at %d:%p'%s'",
10294                                 g_parsefile->left_in_line,
10295                                 g_parsefile->next_to_pgetc,
10296                                 g_parsefile->next_to_pgetc);
10297                 c = pgetc();
10298         } while (c == PEOA);
10299         return c;
10300 }
10301 #else
10302 # define pgetc_without_PEOA() pgetc()
10303 #endif
10304
10305 /*
10306  * Read a line from the script.
10307  */
10308 static char *
10309 pfgets(char *line, int len)
10310 {
10311         char *p = line;
10312         int nleft = len;
10313         int c;
10314
10315         while (--nleft > 0) {
10316                 c = pgetc_without_PEOA();
10317                 if (c == PEOF) {
10318                         if (p == line)
10319                                 return NULL;
10320                         break;
10321                 }
10322                 *p++ = c;
10323                 if (c == '\n')
10324                         break;
10325         }
10326         *p = '\0';
10327         return line;
10328 }
10329
10330 /*
10331  * Undo a call to pgetc.  Only two characters may be pushed back.
10332  * PEOF may be pushed back.
10333  */
10334 static void
10335 pungetc(void)
10336 {
10337         g_parsefile->unget++;
10338 }
10339
10340 /* This one eats backslash+newline */
10341 static int
10342 pgetc_eatbnl(void)
10343 {
10344         int c;
10345
10346         while ((c = pgetc()) == '\\') {
10347                 if (pgetc() != '\n') {
10348                         pungetc();
10349                         break;
10350                 }
10351
10352                 nlprompt();
10353         }
10354
10355         return c;
10356 }
10357
10358 /*
10359  * To handle the "." command, a stack of input files is used.  Pushfile
10360  * adds a new entry to the stack and popfile restores the previous level.
10361  */
10362 static void
10363 pushfile(void)
10364 {
10365         struct parsefile *pf;
10366
10367         pf = ckzalloc(sizeof(*pf));
10368         pf->prev = g_parsefile;
10369         pf->pf_fd = -1;
10370         /*pf->strpush = NULL; - ckzalloc did it */
10371         /*pf->basestrpush.prev = NULL;*/
10372         /*pf->unget = 0;*/
10373         g_parsefile = pf;
10374 }
10375
10376 static void
10377 popfile(void)
10378 {
10379         struct parsefile *pf = g_parsefile;
10380
10381         if (pf == &basepf)
10382                 return;
10383
10384         INT_OFF;
10385         if (pf->pf_fd >= 0)
10386                 close(pf->pf_fd);
10387         free(pf->buf);
10388         while (pf->strpush)
10389                 popstring();
10390         g_parsefile = pf->prev;
10391         free(pf);
10392         INT_ON;
10393 }
10394
10395 /*
10396  * Return to top level.
10397  */
10398 static void
10399 popallfiles(void)
10400 {
10401         while (g_parsefile != &basepf)
10402                 popfile();
10403 }
10404
10405 /*
10406  * Close the file(s) that the shell is reading commands from.  Called
10407  * after a fork is done.
10408  */
10409 static void
10410 closescript(void)
10411 {
10412         popallfiles();
10413         if (g_parsefile->pf_fd > 0) {
10414                 close(g_parsefile->pf_fd);
10415                 g_parsefile->pf_fd = 0;
10416         }
10417 }
10418
10419 /*
10420  * Like setinputfile, but takes an open file descriptor.  Call this with
10421  * interrupts off.
10422  */
10423 static void
10424 setinputfd(int fd, int push)
10425 {
10426         if (push) {
10427                 pushfile();
10428                 g_parsefile->buf = NULL;
10429         }
10430         g_parsefile->pf_fd = fd;
10431         if (g_parsefile->buf == NULL)
10432                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10433         g_parsefile->left_in_buffer = 0;
10434         g_parsefile->left_in_line = 0;
10435         g_parsefile->linno = 1;
10436 }
10437
10438 /*
10439  * Set the input to take input from a file.  If push is set, push the
10440  * old input onto the stack first.
10441  */
10442 static int
10443 setinputfile(const char *fname, int flags)
10444 {
10445         int fd;
10446
10447         INT_OFF;
10448         fd = open(fname, O_RDONLY);
10449         if (fd < 0) {
10450                 if (flags & INPUT_NOFILE_OK)
10451                         goto out;
10452                 exitstatus = 127;
10453                 ash_msg_and_raise_error("can't open '%s'", fname);
10454         }
10455         if (fd < 10)
10456                 fd = savefd(fd);
10457         else
10458                 close_on_exec_on(fd);
10459         setinputfd(fd, flags & INPUT_PUSH_FILE);
10460  out:
10461         INT_ON;
10462         return fd;
10463 }
10464
10465 /*
10466  * Like setinputfile, but takes input from a string.
10467  */
10468 static void
10469 setinputstring(char *string)
10470 {
10471         INT_OFF;
10472         pushfile();
10473         g_parsefile->next_to_pgetc = string;
10474         g_parsefile->left_in_line = strlen(string);
10475         g_parsefile->buf = NULL;
10476         g_parsefile->linno = 1;
10477         INT_ON;
10478 }
10479
10480
10481 /*
10482  * Routines to check for mail.
10483  */
10484
10485 #if ENABLE_ASH_MAIL
10486
10487 /* Hash of mtimes of mailboxes */
10488 static unsigned mailtime_hash;
10489 /* Set if MAIL or MAILPATH is changed. */
10490 static smallint mail_var_path_changed;
10491
10492 /*
10493  * Print appropriate message(s) if mail has arrived.
10494  * If mail_var_path_changed is set,
10495  * then the value of MAIL has mail_var_path_changed,
10496  * so we just update the values.
10497  */
10498 static void
10499 chkmail(void)
10500 {
10501         const char *mpath;
10502         char *p;
10503         char *q;
10504         unsigned new_hash;
10505         struct stackmark smark;
10506         struct stat statb;
10507
10508         setstackmark(&smark);
10509         mpath = mpathset() ? mpathval() : mailval();
10510         new_hash = 0;
10511         for (;;) {
10512                 p = path_advance(&mpath, nullstr);
10513                 if (p == NULL)
10514                         break;
10515                 if (*p == '\0')
10516                         continue;
10517                 for (q = p; *q; q++)
10518                         continue;
10519 #if DEBUG
10520                 if (q[-1] != '/')
10521                         abort();
10522 #endif
10523                 q[-1] = '\0';                   /* delete trailing '/' */
10524                 if (stat(p, &statb) < 0) {
10525                         continue;
10526                 }
10527                 /* Very simplistic "hash": just a sum of all mtimes */
10528                 new_hash += (unsigned)statb.st_mtime;
10529         }
10530         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10531                 if (mailtime_hash != 0)
10532                         out2str("you have mail\n");
10533                 mailtime_hash = new_hash;
10534         }
10535         mail_var_path_changed = 0;
10536         popstackmark(&smark);
10537 }
10538
10539 static void FAST_FUNC
10540 changemail(const char *val UNUSED_PARAM)
10541 {
10542         mail_var_path_changed = 1;
10543 }
10544
10545 #endif /* ASH_MAIL */
10546
10547
10548 /* ============ ??? */
10549
10550 /*
10551  * Set the shell parameters.
10552  */
10553 static void
10554 setparam(char **argv)
10555 {
10556         char **newparam;
10557         char **ap;
10558         int nparam;
10559
10560         for (nparam = 0; argv[nparam]; nparam++)
10561                 continue;
10562         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10563         while (*argv) {
10564                 *ap++ = ckstrdup(*argv++);
10565         }
10566         *ap = NULL;
10567         freeparam(&shellparam);
10568         shellparam.malloced = 1;
10569         shellparam.nparam = nparam;
10570         shellparam.p = newparam;
10571 #if ENABLE_ASH_GETOPTS
10572         shellparam.optind = 1;
10573         shellparam.optoff = -1;
10574 #endif
10575 }
10576
10577 /*
10578  * Process shell options.  The global variable argptr contains a pointer
10579  * to the argument list; we advance it past the options.
10580  *
10581  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10582  * For a non-interactive shell, an error condition encountered
10583  * by a special built-in ... shall cause the shell to write a diagnostic message
10584  * to standard error and exit as shown in the following table:
10585  * Error                                           Special Built-In
10586  * ...
10587  * Utility syntax error (option or operand error)  Shall exit
10588  * ...
10589  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10590  * we see that bash does not do that (set "finishes" with error code 1 instead,
10591  * and shell continues), and people rely on this behavior!
10592  * Testcase:
10593  * set -o barfoo 2>/dev/null
10594  * echo $?
10595  *
10596  * Oh well. Let's mimic that.
10597  */
10598 static int
10599 plus_minus_o(char *name, int val)
10600 {
10601         int i;
10602
10603         if (name) {
10604                 for (i = 0; i < NOPTS; i++) {
10605                         if (strcmp(name, optnames(i)) == 0) {
10606                                 optlist[i] = val;
10607                                 return 0;
10608                         }
10609                 }
10610                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10611                 return 1;
10612         }
10613         for (i = 0; i < NOPTS; i++) {
10614                 if (val) {
10615                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10616                 } else {
10617                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10618                 }
10619         }
10620         return 0;
10621 }
10622 static void
10623 setoption(int flag, int val)
10624 {
10625         int i;
10626
10627         for (i = 0; i < NOPTS; i++) {
10628                 if (optletters(i) == flag) {
10629                         optlist[i] = val;
10630                         return;
10631                 }
10632         }
10633         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10634         /* NOTREACHED */
10635 }
10636 static int
10637 options(int cmdline)
10638 {
10639         char *p;
10640         int val;
10641         int c;
10642
10643         if (cmdline)
10644                 minusc = NULL;
10645         while ((p = *argptr) != NULL) {
10646                 c = *p++;
10647                 if (c != '-' && c != '+')
10648                         break;
10649                 argptr++;
10650                 val = 0; /* val = 0 if c == '+' */
10651                 if (c == '-') {
10652                         val = 1;
10653                         if (p[0] == '\0' || LONE_DASH(p)) {
10654                                 if (!cmdline) {
10655                                         /* "-" means turn off -x and -v */
10656                                         if (p[0] == '\0')
10657                                                 xflag = vflag = 0;
10658                                         /* "--" means reset params */
10659                                         else if (*argptr == NULL)
10660                                                 setparam(argptr);
10661                                 }
10662                                 break;    /* "-" or "--" terminates options */
10663                         }
10664                 }
10665                 /* first char was + or - */
10666                 while ((c = *p++) != '\0') {
10667                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10668                         if (c == 'c' && cmdline) {
10669                                 minusc = p;     /* command is after shell args */
10670                         } else if (c == 'o') {
10671                                 if (plus_minus_o(*argptr, val)) {
10672                                         /* it already printed err message */
10673                                         return 1; /* error */
10674                                 }
10675                                 if (*argptr)
10676                                         argptr++;
10677                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10678                                 isloginsh = 1;
10679                         /* bash does not accept +-login, we also won't */
10680                         } else if (cmdline && val && (c == '-')) { /* long options */
10681                                 if (strcmp(p, "login") == 0)
10682                                         isloginsh = 1;
10683                                 break;
10684                         } else {
10685                                 setoption(c, val);
10686                         }
10687                 }
10688         }
10689         return 0;
10690 }
10691
10692 /*
10693  * The shift builtin command.
10694  */
10695 static int FAST_FUNC
10696 shiftcmd(int argc UNUSED_PARAM, char **argv)
10697 {
10698         int n;
10699         char **ap1, **ap2;
10700
10701         n = 1;
10702         if (argv[1])
10703                 n = number(argv[1]);
10704         if (n > shellparam.nparam)
10705                 n = 0; /* bash compat, was = shellparam.nparam; */
10706         INT_OFF;
10707         shellparam.nparam -= n;
10708         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10709                 if (shellparam.malloced)
10710                         free(*ap1);
10711         }
10712         ap2 = shellparam.p;
10713         while ((*ap2++ = *ap1++) != NULL)
10714                 continue;
10715 #if ENABLE_ASH_GETOPTS
10716         shellparam.optind = 1;
10717         shellparam.optoff = -1;
10718 #endif
10719         INT_ON;
10720         return 0;
10721 }
10722
10723 /*
10724  * POSIX requires that 'set' (but not export or readonly) output the
10725  * variables in lexicographic order - by the locale's collating order (sigh).
10726  * Maybe we could keep them in an ordered balanced binary tree
10727  * instead of hashed lists.
10728  * For now just roll 'em through qsort for printing...
10729  */
10730 static int
10731 showvars(const char *sep_prefix, int on, int off)
10732 {
10733         const char *sep;
10734         char **ep, **epend;
10735
10736         ep = listvars(on, off, &epend);
10737         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10738
10739         sep = *sep_prefix ? " " : sep_prefix;
10740
10741         for (; ep < epend; ep++) {
10742                 const char *p;
10743                 const char *q;
10744
10745                 p = strchrnul(*ep, '=');
10746                 q = nullstr;
10747                 if (*p)
10748                         q = single_quote(++p);
10749                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10750         }
10751         return 0;
10752 }
10753
10754 /*
10755  * The set command builtin.
10756  */
10757 static int FAST_FUNC
10758 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10759 {
10760         int retval;
10761
10762         if (!argv[1])
10763                 return showvars(nullstr, 0, VUNSET);
10764
10765         INT_OFF;
10766         retval = options(/*cmdline:*/ 0);
10767         if (retval == 0) { /* if no parse error... */
10768                 optschanged();
10769                 if (*argptr != NULL) {
10770                         setparam(argptr);
10771                 }
10772         }
10773         INT_ON;
10774         return retval;
10775 }
10776
10777 #if ENABLE_ASH_RANDOM_SUPPORT
10778 static void FAST_FUNC
10779 change_random(const char *value)
10780 {
10781         uint32_t t;
10782
10783         if (value == NULL) {
10784                 /* "get", generate */
10785                 t = next_random(&random_gen);
10786                 /* set without recursion */
10787                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10788                 vrandom.flags &= ~VNOFUNC;
10789         } else {
10790                 /* set/reset */
10791                 t = strtoul(value, NULL, 10);
10792                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10793         }
10794 }
10795 #endif
10796
10797 #if ENABLE_ASH_GETOPTS
10798 static int
10799 getopts(char *optstr, char *optvar, char **optfirst)
10800 {
10801         char *p, *q;
10802         char c = '?';
10803         int done = 0;
10804         char sbuf[2];
10805         char **optnext;
10806         int ind = shellparam.optind;
10807         int off = shellparam.optoff;
10808
10809         sbuf[1] = '\0';
10810
10811         shellparam.optind = -1;
10812         optnext = optfirst + ind - 1;
10813
10814         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10815                 p = NULL;
10816         else
10817                 p = optnext[-1] + off;
10818         if (p == NULL || *p == '\0') {
10819                 /* Current word is done, advance */
10820                 p = *optnext;
10821                 if (p == NULL || *p != '-' || *++p == '\0') {
10822  atend:
10823                         p = NULL;
10824                         done = 1;
10825                         goto out;
10826                 }
10827                 optnext++;
10828                 if (LONE_DASH(p))        /* check for "--" */
10829                         goto atend;
10830         }
10831
10832         c = *p++;
10833         for (q = optstr; *q != c;) {
10834                 if (*q == '\0') {
10835                         if (optstr[0] == ':') {
10836                                 sbuf[0] = c;
10837                                 /*sbuf[1] = '\0'; - already is */
10838                                 setvar0("OPTARG", sbuf);
10839                         } else {
10840                                 fprintf(stderr, "Illegal option -%c\n", c);
10841                                 unsetvar("OPTARG");
10842                         }
10843                         c = '?';
10844                         goto out;
10845                 }
10846                 if (*++q == ':')
10847                         q++;
10848         }
10849
10850         if (*++q == ':') {
10851                 if (*p == '\0' && (p = *optnext) == NULL) {
10852                         if (optstr[0] == ':') {
10853                                 sbuf[0] = c;
10854                                 /*sbuf[1] = '\0'; - already is */
10855                                 setvar0("OPTARG", sbuf);
10856                                 c = ':';
10857                         } else {
10858                                 fprintf(stderr, "No arg for -%c option\n", c);
10859                                 unsetvar("OPTARG");
10860                                 c = '?';
10861                         }
10862                         goto out;
10863                 }
10864
10865                 if (p == *optnext)
10866                         optnext++;
10867                 setvar0("OPTARG", p);
10868                 p = NULL;
10869         } else
10870                 setvar0("OPTARG", nullstr);
10871  out:
10872         ind = optnext - optfirst + 1;
10873         setvar("OPTIND", itoa(ind), VNOFUNC);
10874         sbuf[0] = c;
10875         /*sbuf[1] = '\0'; - already is */
10876         setvar0(optvar, sbuf);
10877
10878         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10879         shellparam.optind = ind;
10880
10881         return done;
10882 }
10883
10884 /*
10885  * The getopts builtin.  Shellparam.optnext points to the next argument
10886  * to be processed.  Shellparam.optptr points to the next character to
10887  * be processed in the current argument.  If shellparam.optnext is NULL,
10888  * then it's the first time getopts has been called.
10889  */
10890 static int FAST_FUNC
10891 getoptscmd(int argc, char **argv)
10892 {
10893         char **optbase;
10894
10895         if (argc < 3)
10896                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10897         if (argc == 3) {
10898                 optbase = shellparam.p;
10899                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10900                         shellparam.optind = 1;
10901                         shellparam.optoff = -1;
10902                 }
10903         } else {
10904                 optbase = &argv[3];
10905                 if ((unsigned)shellparam.optind > argc - 2) {
10906                         shellparam.optind = 1;
10907                         shellparam.optoff = -1;
10908                 }
10909         }
10910
10911         return getopts(argv[1], argv[2], optbase);
10912 }
10913 #endif /* ASH_GETOPTS */
10914
10915
10916 /* ============ Shell parser */
10917
10918 struct heredoc {
10919         struct heredoc *next;   /* next here document in list */
10920         union node *here;       /* redirection node */
10921         char *eofmark;          /* string indicating end of input */
10922         smallint striptabs;     /* if set, strip leading tabs */
10923 };
10924
10925 static smallint tokpushback;           /* last token pushed back */
10926 static smallint quoteflag;             /* set if (part of) last token was quoted */
10927 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10928 static struct heredoc *heredoclist;    /* list of here documents to read */
10929 static char *wordtext;                 /* text of last word returned by readtoken */
10930 static struct nodelist *backquotelist;
10931 static union node *redirnode;
10932 static struct heredoc *heredoc;
10933
10934 static const char *
10935 tokname(char *buf, int tok)
10936 {
10937         if (tok < TSEMI)
10938                 return tokname_array[tok];
10939         sprintf(buf, "\"%s\"", tokname_array[tok]);
10940         return buf;
10941 }
10942
10943 /* raise_error_unexpected_syntax:
10944  * Called when an unexpected token is read during the parse.  The argument
10945  * is the token that is expected, or -1 if more than one type of token can
10946  * occur at this point.
10947  */
10948 static void raise_error_unexpected_syntax(int) NORETURN;
10949 static void
10950 raise_error_unexpected_syntax(int token)
10951 {
10952         char msg[64];
10953         char buf[16];
10954         int l;
10955
10956         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10957         if (token >= 0)
10958                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10959         raise_error_syntax(msg);
10960         /* NOTREACHED */
10961 }
10962
10963 #define EOFMARKLEN 79
10964
10965 /* parsing is heavily cross-recursive, need these forward decls */
10966 static union node *andor(void);
10967 static union node *pipeline(void);
10968 static union node *parse_command(void);
10969 static void parseheredoc(void);
10970 static int peektoken(void);
10971 static int readtoken(void);
10972
10973 static union node *
10974 list(int nlflag)
10975 {
10976         union node *n1, *n2, *n3;
10977         int tok;
10978
10979         n1 = NULL;
10980         for (;;) {
10981                 switch (peektoken()) {
10982                 case TNL:
10983                         if (!(nlflag & 1))
10984                                 break;
10985                         parseheredoc();
10986                         return n1;
10987
10988                 case TEOF:
10989                         if (!n1 && (nlflag & 1))
10990                                 n1 = NODE_EOF;
10991                         parseheredoc();
10992                         return n1;
10993                 }
10994
10995                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10996                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
10997                         return n1;
10998                 nlflag |= 2;
10999
11000                 n2 = andor();
11001                 tok = readtoken();
11002                 if (tok == TBACKGND) {
11003                         if (n2->type == NPIPE) {
11004                                 n2->npipe.pipe_backgnd = 1;
11005                         } else {
11006                                 if (n2->type != NREDIR) {
11007                                         n3 = stzalloc(sizeof(struct nredir));
11008                                         n3->nredir.n = n2;
11009                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
11010                                         n2 = n3;
11011                                 }
11012                                 n2->type = NBACKGND;
11013                         }
11014                 }
11015                 if (n1 == NULL) {
11016                         n1 = n2;
11017                 } else {
11018                         n3 = stzalloc(sizeof(struct nbinary));
11019                         n3->type = NSEMI;
11020                         n3->nbinary.ch1 = n1;
11021                         n3->nbinary.ch2 = n2;
11022                         n1 = n3;
11023                 }
11024                 switch (tok) {
11025                 case TNL:
11026                 case TEOF:
11027                         tokpushback = 1;
11028                         /* fall through */
11029                 case TBACKGND:
11030                 case TSEMI:
11031                         break;
11032                 default:
11033                         if ((nlflag & 1))
11034                                 raise_error_unexpected_syntax(-1);
11035                         tokpushback = 1;
11036                         return n1;
11037                 }
11038         }
11039 }
11040
11041 static union node *
11042 andor(void)
11043 {
11044         union node *n1, *n2, *n3;
11045         int t;
11046
11047         n1 = pipeline();
11048         for (;;) {
11049                 t = readtoken();
11050                 if (t == TAND) {
11051                         t = NAND;
11052                 } else if (t == TOR) {
11053                         t = NOR;
11054                 } else {
11055                         tokpushback = 1;
11056                         return n1;
11057                 }
11058                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11059                 n2 = pipeline();
11060                 n3 = stzalloc(sizeof(struct nbinary));
11061                 n3->type = t;
11062                 n3->nbinary.ch1 = n1;
11063                 n3->nbinary.ch2 = n2;
11064                 n1 = n3;
11065         }
11066 }
11067
11068 static union node *
11069 pipeline(void)
11070 {
11071         union node *n1, *n2, *pipenode;
11072         struct nodelist *lp, *prev;
11073         int negate;
11074
11075         negate = 0;
11076         TRACE(("pipeline: entered\n"));
11077         if (readtoken() == TNOT) {
11078                 negate = !negate;
11079                 checkkwd = CHKKWD | CHKALIAS;
11080         } else
11081                 tokpushback = 1;
11082         n1 = parse_command();
11083         if (readtoken() == TPIPE) {
11084                 pipenode = stzalloc(sizeof(struct npipe));
11085                 pipenode->type = NPIPE;
11086                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11087                 lp = stzalloc(sizeof(struct nodelist));
11088                 pipenode->npipe.cmdlist = lp;
11089                 lp->n = n1;
11090                 do {
11091                         prev = lp;
11092                         lp = stzalloc(sizeof(struct nodelist));
11093                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11094                         lp->n = parse_command();
11095                         prev->next = lp;
11096                 } while (readtoken() == TPIPE);
11097                 lp->next = NULL;
11098                 n1 = pipenode;
11099         }
11100         tokpushback = 1;
11101         if (negate) {
11102                 n2 = stzalloc(sizeof(struct nnot));
11103                 n2->type = NNOT;
11104                 n2->nnot.com = n1;
11105                 return n2;
11106         }
11107         return n1;
11108 }
11109
11110 static union node *
11111 makename(void)
11112 {
11113         union node *n;
11114
11115         n = stzalloc(sizeof(struct narg));
11116         n->type = NARG;
11117         /*n->narg.next = NULL; - stzalloc did it */
11118         n->narg.text = wordtext;
11119         n->narg.backquote = backquotelist;
11120         return n;
11121 }
11122
11123 static void
11124 fixredir(union node *n, const char *text, int err)
11125 {
11126         int fd;
11127
11128         TRACE(("Fix redir %s %d\n", text, err));
11129         if (!err)
11130                 n->ndup.vname = NULL;
11131
11132         fd = bb_strtou(text, NULL, 10);
11133         if (!errno && fd >= 0)
11134                 n->ndup.dupfd = fd;
11135         else if (LONE_DASH(text))
11136                 n->ndup.dupfd = -1;
11137         else {
11138                 if (err)
11139                         raise_error_syntax("bad fd number");
11140                 n->ndup.vname = makename();
11141         }
11142 }
11143
11144 /*
11145  * Returns true if the text contains nothing to expand (no dollar signs
11146  * or backquotes).
11147  */
11148 static int
11149 noexpand(const char *text)
11150 {
11151         unsigned char c;
11152
11153         while ((c = *text++) != '\0') {
11154                 if (c == CTLQUOTEMARK)
11155                         continue;
11156                 if (c == CTLESC)
11157                         text++;
11158                 else if (SIT(c, BASESYNTAX) == CCTL)
11159                         return 0;
11160         }
11161         return 1;
11162 }
11163
11164 static void
11165 parsefname(void)
11166 {
11167         union node *n = redirnode;
11168
11169         if (readtoken() != TWORD)
11170                 raise_error_unexpected_syntax(-1);
11171         if (n->type == NHERE) {
11172                 struct heredoc *here = heredoc;
11173                 struct heredoc *p;
11174                 int i;
11175
11176                 if (quoteflag == 0)
11177                         n->type = NXHERE;
11178                 TRACE(("Here document %d\n", n->type));
11179                 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
11180                         raise_error_syntax("illegal eof marker for << redirection");
11181                 rmescapes(wordtext, 0);
11182                 here->eofmark = wordtext;
11183                 here->next = NULL;
11184                 if (heredoclist == NULL)
11185                         heredoclist = here;
11186                 else {
11187                         for (p = heredoclist; p->next; p = p->next)
11188                                 continue;
11189                         p->next = here;
11190                 }
11191         } else if (n->type == NTOFD || n->type == NFROMFD) {
11192                 fixredir(n, wordtext, 0);
11193         } else {
11194                 n->nfile.fname = makename();
11195         }
11196 }
11197
11198 static union node *
11199 simplecmd(void)
11200 {
11201         union node *args, **app;
11202         union node *n = NULL;
11203         union node *vars, **vpp;
11204         union node **rpp, *redir;
11205         int savecheckkwd;
11206 #if BASH_TEST2
11207         smallint double_brackets_flag = 0;
11208 #endif
11209         IF_BASH_FUNCTION(smallint function_flag = 0;)
11210
11211         args = NULL;
11212         app = &args;
11213         vars = NULL;
11214         vpp = &vars;
11215         redir = NULL;
11216         rpp = &redir;
11217
11218         savecheckkwd = CHKALIAS;
11219         for (;;) {
11220                 int t;
11221                 checkkwd = savecheckkwd;
11222                 t = readtoken();
11223                 switch (t) {
11224 #if BASH_FUNCTION
11225                 case TFUNCTION:
11226                         if (peektoken() != TWORD)
11227                                 raise_error_unexpected_syntax(TWORD);
11228                         function_flag = 1;
11229                         break;
11230 #endif
11231 #if BASH_TEST2
11232                 case TAND: /* "&&" */
11233                 case TOR: /* "||" */
11234                         if (!double_brackets_flag) {
11235                                 tokpushback = 1;
11236                                 goto out;
11237                         }
11238                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11239 #endif
11240                 case TWORD:
11241                         n = stzalloc(sizeof(struct narg));
11242                         n->type = NARG;
11243                         /*n->narg.next = NULL; - stzalloc did it */
11244                         n->narg.text = wordtext;
11245 #if BASH_TEST2
11246                         if (strcmp("[[", wordtext) == 0)
11247                                 double_brackets_flag = 1;
11248                         else if (strcmp("]]", wordtext) == 0)
11249                                 double_brackets_flag = 0;
11250 #endif
11251                         n->narg.backquote = backquotelist;
11252                         if (savecheckkwd && isassignment(wordtext)) {
11253                                 *vpp = n;
11254                                 vpp = &n->narg.next;
11255                         } else {
11256                                 *app = n;
11257                                 app = &n->narg.next;
11258                                 savecheckkwd = 0;
11259                         }
11260 #if BASH_FUNCTION
11261                         if (function_flag) {
11262                                 checkkwd = CHKNL | CHKKWD;
11263                                 switch (peektoken()) {
11264                                 case TBEGIN:
11265                                 case TIF:
11266                                 case TCASE:
11267                                 case TUNTIL:
11268                                 case TWHILE:
11269                                 case TFOR:
11270                                         goto do_func;
11271                                 case TLP:
11272                                         function_flag = 0;
11273                                         break;
11274                                 case TWORD:
11275                                         if (strcmp("[[", wordtext) == 0)
11276                                                 goto do_func;
11277                                         /* fall through */
11278                                 default:
11279                                         raise_error_unexpected_syntax(-1);
11280                                 }
11281                         }
11282 #endif
11283                         break;
11284                 case TREDIR:
11285                         *rpp = n = redirnode;
11286                         rpp = &n->nfile.next;
11287                         parsefname();   /* read name of redirection file */
11288                         break;
11289                 case TLP:
11290  IF_BASH_FUNCTION(do_func:)
11291                         if (args && app == &args->narg.next
11292                          && !vars && !redir
11293                         ) {
11294                                 struct builtincmd *bcmd;
11295                                 const char *name;
11296
11297                                 /* We have a function */
11298                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11299                                         raise_error_unexpected_syntax(TRP);
11300                                 name = n->narg.text;
11301                                 if (!goodname(name)
11302                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11303                                 ) {
11304                                         raise_error_syntax("bad function name");
11305                                 }
11306                                 n->type = NDEFUN;
11307                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11308                                 n->narg.next = parse_command();
11309                                 return n;
11310                         }
11311                         IF_BASH_FUNCTION(function_flag = 0;)
11312                         /* fall through */
11313                 default:
11314                         tokpushback = 1;
11315                         goto out;
11316                 }
11317         }
11318  out:
11319         *app = NULL;
11320         *vpp = NULL;
11321         *rpp = NULL;
11322         n = stzalloc(sizeof(struct ncmd));
11323         n->type = NCMD;
11324         n->ncmd.args = args;
11325         n->ncmd.assign = vars;
11326         n->ncmd.redirect = redir;
11327         return n;
11328 }
11329
11330 static union node *
11331 parse_command(void)
11332 {
11333         union node *n1, *n2;
11334         union node *ap, **app;
11335         union node *cp, **cpp;
11336         union node *redir, **rpp;
11337         union node **rpp2;
11338         int t;
11339
11340         redir = NULL;
11341         rpp2 = &redir;
11342
11343         switch (readtoken()) {
11344         default:
11345                 raise_error_unexpected_syntax(-1);
11346                 /* NOTREACHED */
11347         case TIF:
11348                 n1 = stzalloc(sizeof(struct nif));
11349                 n1->type = NIF;
11350                 n1->nif.test = list(0);
11351                 if (readtoken() != TTHEN)
11352                         raise_error_unexpected_syntax(TTHEN);
11353                 n1->nif.ifpart = list(0);
11354                 n2 = n1;
11355                 while (readtoken() == TELIF) {
11356                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11357                         n2 = n2->nif.elsepart;
11358                         n2->type = NIF;
11359                         n2->nif.test = list(0);
11360                         if (readtoken() != TTHEN)
11361                                 raise_error_unexpected_syntax(TTHEN);
11362                         n2->nif.ifpart = list(0);
11363                 }
11364                 if (lasttoken == TELSE)
11365                         n2->nif.elsepart = list(0);
11366                 else {
11367                         n2->nif.elsepart = NULL;
11368                         tokpushback = 1;
11369                 }
11370                 t = TFI;
11371                 break;
11372         case TWHILE:
11373         case TUNTIL: {
11374                 int got;
11375                 n1 = stzalloc(sizeof(struct nbinary));
11376                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11377                 n1->nbinary.ch1 = list(0);
11378                 got = readtoken();
11379                 if (got != TDO) {
11380                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11381                                         got == TWORD ? wordtext : ""));
11382                         raise_error_unexpected_syntax(TDO);
11383                 }
11384                 n1->nbinary.ch2 = list(0);
11385                 t = TDONE;
11386                 break;
11387         }
11388         case TFOR:
11389                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11390                         raise_error_syntax("bad for loop variable");
11391                 n1 = stzalloc(sizeof(struct nfor));
11392                 n1->type = NFOR;
11393                 n1->nfor.var = wordtext;
11394                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11395                 if (readtoken() == TIN) {
11396                         app = &ap;
11397                         while (readtoken() == TWORD) {
11398                                 n2 = stzalloc(sizeof(struct narg));
11399                                 n2->type = NARG;
11400                                 /*n2->narg.next = NULL; - stzalloc did it */
11401                                 n2->narg.text = wordtext;
11402                                 n2->narg.backquote = backquotelist;
11403                                 *app = n2;
11404                                 app = &n2->narg.next;
11405                         }
11406                         *app = NULL;
11407                         n1->nfor.args = ap;
11408                         if (lasttoken != TNL && lasttoken != TSEMI)
11409                                 raise_error_unexpected_syntax(-1);
11410                 } else {
11411                         n2 = stzalloc(sizeof(struct narg));
11412                         n2->type = NARG;
11413                         /*n2->narg.next = NULL; - stzalloc did it */
11414                         n2->narg.text = (char *)dolatstr;
11415                         /*n2->narg.backquote = NULL;*/
11416                         n1->nfor.args = n2;
11417                         /*
11418                          * Newline or semicolon here is optional (but note
11419                          * that the original Bourne shell only allowed NL).
11420                          */
11421                         if (lasttoken != TSEMI)
11422                                 tokpushback = 1;
11423                 }
11424                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11425                 if (readtoken() != TDO)
11426                         raise_error_unexpected_syntax(TDO);
11427                 n1->nfor.body = list(0);
11428                 t = TDONE;
11429                 break;
11430         case TCASE:
11431                 n1 = stzalloc(sizeof(struct ncase));
11432                 n1->type = NCASE;
11433                 if (readtoken() != TWORD)
11434                         raise_error_unexpected_syntax(TWORD);
11435                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11436                 n2->type = NARG;
11437                 /*n2->narg.next = NULL; - stzalloc did it */
11438                 n2->narg.text = wordtext;
11439                 n2->narg.backquote = backquotelist;
11440                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11441                 if (readtoken() != TIN)
11442                         raise_error_unexpected_syntax(TIN);
11443                 cpp = &n1->ncase.cases;
11444  next_case:
11445                 checkkwd = CHKNL | CHKKWD;
11446                 t = readtoken();
11447                 while (t != TESAC) {
11448                         if (lasttoken == TLP)
11449                                 readtoken();
11450                         *cpp = cp = stzalloc(sizeof(struct nclist));
11451                         cp->type = NCLIST;
11452                         app = &cp->nclist.pattern;
11453                         for (;;) {
11454                                 *app = ap = stzalloc(sizeof(struct narg));
11455                                 ap->type = NARG;
11456                                 /*ap->narg.next = NULL; - stzalloc did it */
11457                                 ap->narg.text = wordtext;
11458                                 ap->narg.backquote = backquotelist;
11459                                 if (readtoken() != TPIPE)
11460                                         break;
11461                                 app = &ap->narg.next;
11462                                 readtoken();
11463                         }
11464                         //ap->narg.next = NULL;
11465                         if (lasttoken != TRP)
11466                                 raise_error_unexpected_syntax(TRP);
11467                         cp->nclist.body = list(2);
11468
11469                         cpp = &cp->nclist.next;
11470
11471                         checkkwd = CHKNL | CHKKWD;
11472                         t = readtoken();
11473                         if (t != TESAC) {
11474                                 if (t != TENDCASE)
11475                                         raise_error_unexpected_syntax(TENDCASE);
11476                                 goto next_case;
11477                         }
11478                 }
11479                 *cpp = NULL;
11480                 goto redir;
11481         case TLP:
11482                 n1 = stzalloc(sizeof(struct nredir));
11483                 n1->type = NSUBSHELL;
11484                 n1->nredir.n = list(0);
11485                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11486                 t = TRP;
11487                 break;
11488         case TBEGIN:
11489                 n1 = list(0);
11490                 t = TEND;
11491                 break;
11492         IF_BASH_FUNCTION(case TFUNCTION:)
11493         case TWORD:
11494         case TREDIR:
11495                 tokpushback = 1;
11496                 return simplecmd();
11497         }
11498
11499         if (readtoken() != t)
11500                 raise_error_unexpected_syntax(t);
11501
11502  redir:
11503         /* Now check for redirection which may follow command */
11504         checkkwd = CHKKWD | CHKALIAS;
11505         rpp = rpp2;
11506         while (readtoken() == TREDIR) {
11507                 *rpp = n2 = redirnode;
11508                 rpp = &n2->nfile.next;
11509                 parsefname();
11510         }
11511         tokpushback = 1;
11512         *rpp = NULL;
11513         if (redir) {
11514                 if (n1->type != NSUBSHELL) {
11515                         n2 = stzalloc(sizeof(struct nredir));
11516                         n2->type = NREDIR;
11517                         n2->nredir.n = n1;
11518                         n1 = n2;
11519                 }
11520                 n1->nredir.redirect = redir;
11521         }
11522         return n1;
11523 }
11524
11525 #if BASH_DOLLAR_SQUOTE
11526 static int
11527 decode_dollar_squote(void)
11528 {
11529         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11530         int c, cnt;
11531         char *p;
11532         char buf[4];
11533
11534         c = pgetc();
11535         p = strchr(C_escapes, c);
11536         if (p) {
11537                 buf[0] = c;
11538                 p = buf;
11539                 cnt = 3;
11540                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11541                         do {
11542                                 c = pgetc();
11543                                 *++p = c;
11544                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11545                         pungetc();
11546                 } else if (c == 'x') { /* \xHH */
11547                         do {
11548                                 c = pgetc();
11549                                 *++p = c;
11550                         } while (isxdigit(c) && --cnt);
11551                         pungetc();
11552                         if (cnt == 3) { /* \x but next char is "bad" */
11553                                 c = 'x';
11554                                 goto unrecognized;
11555                         }
11556                 } else { /* simple seq like \\ or \t */
11557                         p++;
11558                 }
11559                 *p = '\0';
11560                 p = buf;
11561                 c = bb_process_escape_sequence((void*)&p);
11562         } else { /* unrecognized "\z": print both chars unless ' or " */
11563                 if (c != '\'' && c != '"') {
11564  unrecognized:
11565                         c |= 0x100; /* "please encode \, then me" */
11566                 }
11567         }
11568         return c;
11569 }
11570 #endif
11571
11572 /*
11573  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11574  * is not NULL, read a here document.  In the latter case, eofmark is the
11575  * word which marks the end of the document and striptabs is true if
11576  * leading tabs should be stripped from the document.  The argument c
11577  * is the first character of the input token or document.
11578  *
11579  * Because C does not have internal subroutines, I have simulated them
11580  * using goto's to implement the subroutine linkage.  The following macros
11581  * will run code that appears at the end of readtoken1.
11582  */
11583 #define CHECKEND()      {goto checkend; checkend_return:;}
11584 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11585 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11586 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11587 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11588 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11589 static int
11590 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11591 {
11592         /* NB: syntax parameter fits into smallint */
11593         /* c parameter is an unsigned char or PEOF or PEOA */
11594         char *out;
11595         size_t len;
11596         char line[EOFMARKLEN + 1];
11597         struct nodelist *bqlist;
11598         smallint quotef;
11599         smallint dblquote;
11600         smallint oldstyle;
11601         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11602         smallint pssyntax;   /* we are expanding a prompt string */
11603         int varnest;         /* levels of variables expansion */
11604         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11605         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11606         int dqvarnest;       /* levels of variables expansion within double quotes */
11607
11608         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11609
11610         startlinno = g_parsefile->linno;
11611         bqlist = NULL;
11612         quotef = 0;
11613         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11614         pssyntax = (syntax == PSSYNTAX);
11615         if (pssyntax)
11616                 syntax = DQSYNTAX;
11617         dblquote = (syntax == DQSYNTAX);
11618         varnest = 0;
11619         IF_FEATURE_SH_MATH(arinest = 0;)
11620         IF_FEATURE_SH_MATH(parenlevel = 0;)
11621         dqvarnest = 0;
11622
11623         STARTSTACKSTR(out);
11624  loop:
11625         /* For each line, until end of word */
11626         CHECKEND();     /* set c to PEOF if at end of here document */
11627         for (;;) {      /* until end of line or end of word */
11628                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11629                 switch (SIT(c, syntax)) {
11630                 case CNL:       /* '\n' */
11631                         if (syntax == BASESYNTAX)
11632                                 goto endword;   /* exit outer loop */
11633                         USTPUTC(c, out);
11634                         nlprompt();
11635                         c = pgetc();
11636                         goto loop;              /* continue outer loop */
11637                 case CWORD:
11638                         USTPUTC(c, out);
11639                         break;
11640                 case CCTL:
11641 #if BASH_DOLLAR_SQUOTE
11642                         if (c == '\\' && bash_dollar_squote) {
11643                                 c = decode_dollar_squote();
11644                                 if (c == '\0') {
11645                                         /* skip $'\000', $'\x00' (like bash) */
11646                                         break;
11647                                 }
11648                                 if (c & 0x100) {
11649                                         /* Unknown escape. Encode as '\z' */
11650                                         c = (unsigned char)c;
11651                                         if (eofmark == NULL || dblquote)
11652                                                 USTPUTC(CTLESC, out);
11653                                         USTPUTC('\\', out);
11654                                 }
11655                         }
11656 #endif
11657                         if (eofmark == NULL || dblquote)
11658                                 USTPUTC(CTLESC, out);
11659                         USTPUTC(c, out);
11660                         break;
11661                 case CBACK:     /* backslash */
11662                         c = pgetc_without_PEOA();
11663                         if (c == PEOF) {
11664                                 USTPUTC(CTLESC, out);
11665                                 USTPUTC('\\', out);
11666                                 pungetc();
11667                         } else if (c == '\n') {
11668                                 nlprompt();
11669                         } else {
11670                                 if (c == '$' && pssyntax) {
11671                                         USTPUTC(CTLESC, out);
11672                                         USTPUTC('\\', out);
11673                                 }
11674                                 /* Backslash is retained if we are in "str" and next char isn't special */
11675                                 if (dblquote
11676                                  && c != '\\'
11677                                  && c != '`'
11678                                  && c != '$'
11679                                  && (c != '"' || eofmark != NULL)
11680                                 ) {
11681                                         USTPUTC('\\', out);
11682                                 }
11683                                 USTPUTC(CTLESC, out);
11684                                 USTPUTC(c, out);
11685                                 quotef = 1;
11686                         }
11687                         break;
11688                 case CSQUOTE:
11689                         syntax = SQSYNTAX;
11690  quotemark:
11691                         if (eofmark == NULL) {
11692                                 USTPUTC(CTLQUOTEMARK, out);
11693                         }
11694                         break;
11695                 case CDQUOTE:
11696                         syntax = DQSYNTAX;
11697                         dblquote = 1;
11698                         goto quotemark;
11699                 case CENDQUOTE:
11700                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11701                         if (eofmark != NULL && varnest == 0) {
11702                                 USTPUTC(c, out);
11703                         } else {
11704                                 if (dqvarnest == 0) {
11705                                         syntax = BASESYNTAX;
11706                                         dblquote = 0;
11707                                 }
11708                                 quotef = 1;
11709                                 goto quotemark;
11710                         }
11711                         break;
11712                 case CVAR:      /* '$' */
11713                         PARSESUB();             /* parse substitution */
11714                         break;
11715                 case CENDVAR:   /* '}' */
11716                         if (varnest > 0) {
11717                                 varnest--;
11718                                 if (dqvarnest > 0) {
11719                                         dqvarnest--;
11720                                 }
11721                                 c = CTLENDVAR;
11722                         }
11723                         USTPUTC(c, out);
11724                         break;
11725 #if ENABLE_FEATURE_SH_MATH
11726                 case CLP:       /* '(' in arithmetic */
11727                         parenlevel++;
11728                         USTPUTC(c, out);
11729                         break;
11730                 case CRP:       /* ')' in arithmetic */
11731                         if (parenlevel > 0) {
11732                                 parenlevel--;
11733                         } else {
11734                                 if (pgetc_eatbnl() == ')') {
11735                                         c = CTLENDARI;
11736                                         if (--arinest == 0) {
11737                                                 syntax = prevsyntax;
11738                                         }
11739                                 } else {
11740                                         /*
11741                                          * unbalanced parens
11742                                          * (don't 2nd guess - no error)
11743                                          */
11744                                         pungetc();
11745                                 }
11746                         }
11747                         USTPUTC(c, out);
11748                         break;
11749 #endif
11750                 case CBQUOTE:   /* '`' */
11751                         PARSEBACKQOLD();
11752                         break;
11753                 case CENDFILE:
11754                         goto endword;           /* exit outer loop */
11755                 case CIGN:
11756                         break;
11757                 default:
11758                         if (varnest == 0) {
11759 #if BASH_REDIR_OUTPUT
11760                                 if (c == '&') {
11761 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11762                                         if (pgetc() == '>')
11763                                                 c = 0x100 + '>'; /* flag &> */
11764                                         pungetc();
11765                                 }
11766 #endif
11767                                 goto endword;   /* exit outer loop */
11768                         }
11769                         IF_ASH_ALIAS(if (c != PEOA))
11770                                 USTPUTC(c, out);
11771                 }
11772                 c = pgetc();
11773         } /* for (;;) */
11774  endword:
11775
11776 #if ENABLE_FEATURE_SH_MATH
11777         if (syntax == ARISYNTAX)
11778                 raise_error_syntax("missing '))'");
11779 #endif
11780         if (syntax != BASESYNTAX && eofmark == NULL)
11781                 raise_error_syntax("unterminated quoted string");
11782         if (varnest != 0) {
11783                 startlinno = g_parsefile->linno;
11784                 /* { */
11785                 raise_error_syntax("missing '}'");
11786         }
11787         USTPUTC('\0', out);
11788         len = out - (char *)stackblock();
11789         out = stackblock();
11790         if (eofmark == NULL) {
11791                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11792                  && quotef == 0
11793                 ) {
11794                         if (isdigit_str9(out)) {
11795                                 PARSEREDIR(); /* passed as params: out, c */
11796                                 lasttoken = TREDIR;
11797                                 return lasttoken;
11798                         }
11799                         /* else: non-number X seen, interpret it
11800                          * as "NNNX>file" = "NNNX >file" */
11801                 }
11802                 pungetc();
11803         }
11804         quoteflag = quotef;
11805         backquotelist = bqlist;
11806         grabstackblock(len);
11807         wordtext = out;
11808         lasttoken = TWORD;
11809         return lasttoken;
11810 /* end of readtoken routine */
11811
11812 /*
11813  * Check to see whether we are at the end of the here document.  When this
11814  * is called, c is set to the first character of the next input line.  If
11815  * we are at the end of the here document, this routine sets the c to PEOF.
11816  */
11817 checkend: {
11818         if (eofmark) {
11819 #if ENABLE_ASH_ALIAS
11820                 if (c == PEOA)
11821                         c = pgetc_without_PEOA();
11822 #endif
11823                 if (striptabs) {
11824                         while (c == '\t') {
11825                                 c = pgetc_without_PEOA();
11826                         }
11827                 }
11828                 if (c == *eofmark) {
11829                         if (pfgets(line, sizeof(line)) != NULL) {
11830                                 char *p, *q;
11831                                 int cc;
11832
11833                                 p = line;
11834                                 for (q = eofmark + 1;; p++, q++) {
11835                                         cc = *p;
11836                                         if (cc == '\n')
11837                                                 cc = 0;
11838                                         if (!*q || cc != *q)
11839                                                 break;
11840                                 }
11841                                 if (cc == *q) {
11842                                         c = PEOF;
11843                                         nlnoprompt();
11844                                 } else {
11845                                         pushstring(line, NULL);
11846                                 }
11847                         }
11848                 }
11849         }
11850         goto checkend_return;
11851 }
11852
11853 /*
11854  * Parse a redirection operator.  The variable "out" points to a string
11855  * specifying the fd to be redirected.  The variable "c" contains the
11856  * first character of the redirection operator.
11857  */
11858 parseredir: {
11859         /* out is already checked to be a valid number or "" */
11860         int fd = (*out == '\0' ? -1 : atoi(out));
11861         union node *np;
11862
11863         np = stzalloc(sizeof(struct nfile));
11864         if (c == '>') {
11865                 np->nfile.fd = 1;
11866                 c = pgetc();
11867                 if (c == '>')
11868                         np->type = NAPPEND;
11869                 else if (c == '|')
11870                         np->type = NCLOBBER;
11871                 else if (c == '&')
11872                         np->type = NTOFD;
11873                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11874                 else {
11875                         np->type = NTO;
11876                         pungetc();
11877                 }
11878         }
11879 #if BASH_REDIR_OUTPUT
11880         else if (c == 0x100 + '>') { /* this flags &> redirection */
11881                 np->nfile.fd = 1;
11882                 pgetc(); /* this is '>', no need to check */
11883                 np->type = NTO2;
11884         }
11885 #endif
11886         else { /* c == '<' */
11887                 /*np->nfile.fd = 0; - stzalloc did it */
11888                 c = pgetc();
11889                 switch (c) {
11890                 case '<':
11891                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11892                                 np = stzalloc(sizeof(struct nhere));
11893                                 /*np->nfile.fd = 0; - stzalloc did it */
11894                         }
11895                         np->type = NHERE;
11896                         heredoc = stzalloc(sizeof(struct heredoc));
11897                         heredoc->here = np;
11898                         c = pgetc();
11899                         if (c == '-') {
11900                                 heredoc->striptabs = 1;
11901                         } else {
11902                                 /*heredoc->striptabs = 0; - stzalloc did it */
11903                                 pungetc();
11904                         }
11905                         break;
11906
11907                 case '&':
11908                         np->type = NFROMFD;
11909                         break;
11910
11911                 case '>':
11912                         np->type = NFROMTO;
11913                         break;
11914
11915                 default:
11916                         np->type = NFROM;
11917                         pungetc();
11918                         break;
11919                 }
11920         }
11921         if (fd >= 0)
11922                 np->nfile.fd = fd;
11923         redirnode = np;
11924         goto parseredir_return;
11925 }
11926
11927 /*
11928  * Parse a substitution.  At this point, we have read the dollar sign
11929  * and nothing else.
11930  */
11931
11932 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11933  * (assuming ascii char codes, as the original implementation did) */
11934 #define is_special(c) \
11935         (((unsigned)(c) - 33 < 32) \
11936                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11937 parsesub: {
11938         unsigned char subtype;
11939         int typeloc;
11940
11941         c = pgetc_eatbnl();
11942         if (c > 255 /* PEOA or PEOF */
11943          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11944         ) {
11945 #if BASH_DOLLAR_SQUOTE
11946                 if (syntax != DQSYNTAX && c == '\'')
11947                         bash_dollar_squote = 1;
11948                 else
11949 #endif
11950                         USTPUTC('$', out);
11951                 pungetc();
11952         } else if (c == '(') {
11953                 /* $(command) or $((arith)) */
11954                 if (pgetc_eatbnl() == '(') {
11955 #if ENABLE_FEATURE_SH_MATH
11956                         PARSEARITH();
11957 #else
11958                         raise_error_syntax("support for $((arith)) is disabled");
11959 #endif
11960                 } else {
11961                         pungetc();
11962                         PARSEBACKQNEW();
11963                 }
11964         } else {
11965                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11966                 USTPUTC(CTLVAR, out);
11967                 typeloc = out - (char *)stackblock();
11968                 STADJUST(1, out);
11969                 subtype = VSNORMAL;
11970                 if (c == '{') {
11971                         c = pgetc_eatbnl();
11972                         subtype = 0;
11973                 }
11974  varname:
11975                 if (is_name(c)) {
11976                         /* $[{[#]]NAME[}] */
11977                         do {
11978                                 STPUTC(c, out);
11979                                 c = pgetc_eatbnl();
11980                         } while (is_in_name(c));
11981                 } else if (isdigit(c)) {
11982                         /* $[{[#]]NUM[}] */
11983                         do {
11984                                 STPUTC(c, out);
11985                                 c = pgetc_eatbnl();
11986                         } while (isdigit(c));
11987                 } else if (is_special(c)) {
11988                         /* $[{[#]]<specialchar>[}] */
11989                         int cc = c;
11990
11991                         c = pgetc_eatbnl();
11992                         if (!subtype && cc == '#') {
11993                                 subtype = VSLENGTH;
11994                                 if (c == '_' || isalnum(c))
11995                                         goto varname;
11996                                 cc = c;
11997                                 c = pgetc_eatbnl();
11998                                 if (cc == '}' || c != '}') {
11999                                         pungetc();
12000                                         subtype = 0;
12001                                         c = cc;
12002                                         cc = '#';
12003                                 }
12004                         }
12005                         USTPUTC(cc, out);
12006                 } else {
12007                         goto badsub;
12008                 }
12009                 if (c != '}' && subtype == VSLENGTH) {
12010                         /* ${#VAR didn't end with } */
12011                         goto badsub;
12012                 }
12013
12014                 if (subtype == 0) {
12015                         static const char types[] ALIGN1 = "}-+?=";
12016                         /* ${VAR...} but not $VAR or ${#VAR} */
12017                         /* c == first char after VAR */
12018                         switch (c) {
12019                         case ':':
12020                                 c = pgetc_eatbnl();
12021 #if BASH_SUBSTR
12022                                 /* This check is only needed to not misinterpret
12023                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
12024                                  * constructs.
12025                                  */
12026                                 if (!strchr(types, c)) {
12027                                         subtype = VSSUBSTR;
12028                                         pungetc();
12029                                         break; /* "goto badsub" is bigger (!) */
12030                                 }
12031 #endif
12032                                 subtype = VSNUL;
12033                                 /*FALLTHROUGH*/
12034                         default: {
12035                                 const char *p = strchr(types, c);
12036                                 if (p == NULL)
12037                                         break;
12038                                 subtype |= p - types + VSNORMAL;
12039                                 break;
12040                         }
12041                         case '%':
12042                         case '#': {
12043                                 int cc = c;
12044                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12045                                 c = pgetc_eatbnl();
12046                                 if (c != cc)
12047                                         goto badsub;
12048                                 subtype++;
12049                                 break;
12050                         }
12051 #if BASH_PATTERN_SUBST
12052                         case '/':
12053                                 /* ${v/[/]pattern/repl} */
12054 //TODO: encode pattern and repl separately.
12055 // Currently ${v/$var_with_slash/repl} is horribly broken
12056                                 subtype = VSREPLACE;
12057                                 c = pgetc_eatbnl();
12058                                 if (c != '/')
12059                                         goto badsub;
12060                                 subtype++; /* VSREPLACEALL */
12061                                 break;
12062 #endif
12063                         }
12064                 } else {
12065  badsub:
12066                         pungetc();
12067                 }
12068                 ((unsigned char *)stackblock())[typeloc] = subtype;
12069                 if (subtype != VSNORMAL) {
12070                         varnest++;
12071                         if (dblquote)
12072                                 dqvarnest++;
12073                 }
12074                 STPUTC('=', out);
12075         }
12076         goto parsesub_return;
12077 }
12078
12079 /*
12080  * Called to parse command substitutions.  Newstyle is set if the command
12081  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12082  * list of commands (passed by reference), and savelen is the number of
12083  * characters on the top of the stack which must be preserved.
12084  */
12085 parsebackq: {
12086         struct nodelist **nlpp;
12087         union node *n;
12088         char *str;
12089         size_t savelen;
12090         smallint saveprompt = 0;
12091
12092         str = NULL;
12093         savelen = out - (char *)stackblock();
12094         if (savelen > 0) {
12095                 /*
12096                  * FIXME: this can allocate very large block on stack and SEGV.
12097                  * Example:
12098                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12099                  * allocates 100kb for every command subst. With about
12100                  * a hundred command substitutions stack overflows.
12101                  * With larger prepended string, SEGV happens sooner.
12102                  */
12103                 str = alloca(savelen);
12104                 memcpy(str, stackblock(), savelen);
12105         }
12106
12107         if (oldstyle) {
12108                 /* We must read until the closing backquote, giving special
12109                  * treatment to some slashes, and then push the string and
12110                  * reread it as input, interpreting it normally.
12111                  */
12112                 char *pout;
12113                 size_t psavelen;
12114                 char *pstr;
12115
12116                 STARTSTACKSTR(pout);
12117                 for (;;) {
12118                         int pc;
12119
12120                         setprompt_if(needprompt, 2);
12121                         pc = pgetc();
12122                         switch (pc) {
12123                         case '`':
12124                                 goto done;
12125
12126                         case '\\':
12127                                 pc = pgetc();
12128                                 if (pc == '\n') {
12129                                         nlprompt();
12130                                         /*
12131                                          * If eating a newline, avoid putting
12132                                          * the newline into the new character
12133                                          * stream (via the STPUTC after the
12134                                          * switch).
12135                                          */
12136                                         continue;
12137                                 }
12138                                 if (pc != '\\' && pc != '`' && pc != '$'
12139                                  && (!dblquote || pc != '"')
12140                                 ) {
12141                                         STPUTC('\\', pout);
12142                                 }
12143                                 if (pc <= 255 /* not PEOA or PEOF */) {
12144                                         break;
12145                                 }
12146                                 /* fall through */
12147
12148                         case PEOF:
12149                         IF_ASH_ALIAS(case PEOA:)
12150                                 startlinno = g_parsefile->linno;
12151                                 raise_error_syntax("EOF in backquote substitution");
12152
12153                         case '\n':
12154                                 nlnoprompt();
12155                                 break;
12156
12157                         default:
12158                                 break;
12159                         }
12160                         STPUTC(pc, pout);
12161                 }
12162  done:
12163                 STPUTC('\0', pout);
12164                 psavelen = pout - (char *)stackblock();
12165                 if (psavelen > 0) {
12166                         pstr = grabstackstr(pout);
12167                         setinputstring(pstr);
12168                 }
12169         }
12170         nlpp = &bqlist;
12171         while (*nlpp)
12172                 nlpp = &(*nlpp)->next;
12173         *nlpp = stzalloc(sizeof(**nlpp));
12174         /* (*nlpp)->next = NULL; - stzalloc did it */
12175
12176         if (oldstyle) {
12177                 saveprompt = doprompt;
12178                 doprompt = 0;
12179         }
12180
12181         n = list(2);
12182
12183         if (oldstyle)
12184                 doprompt = saveprompt;
12185         else if (readtoken() != TRP)
12186                 raise_error_unexpected_syntax(TRP);
12187
12188         (*nlpp)->n = n;
12189         if (oldstyle) {
12190                 /*
12191                  * Start reading from old file again, ignoring any pushed back
12192                  * tokens left from the backquote parsing
12193                  */
12194                 popfile();
12195                 tokpushback = 0;
12196         }
12197         while (stackblocksize() <= savelen)
12198                 growstackblock();
12199         STARTSTACKSTR(out);
12200         if (str) {
12201                 memcpy(out, str, savelen);
12202                 STADJUST(savelen, out);
12203         }
12204         USTPUTC(CTLBACKQ, out);
12205         if (oldstyle)
12206                 goto parsebackq_oldreturn;
12207         goto parsebackq_newreturn;
12208 }
12209
12210 #if ENABLE_FEATURE_SH_MATH
12211 /*
12212  * Parse an arithmetic expansion (indicate start of one and set state)
12213  */
12214 parsearith: {
12215         if (++arinest == 1) {
12216                 prevsyntax = syntax;
12217                 syntax = ARISYNTAX;
12218         }
12219         USTPUTC(CTLARI, out);
12220         goto parsearith_return;
12221 }
12222 #endif
12223 } /* end of readtoken */
12224
12225 /*
12226  * Read the next input token.
12227  * If the token is a word, we set backquotelist to the list of cmds in
12228  *      backquotes.  We set quoteflag to true if any part of the word was
12229  *      quoted.
12230  * If the token is TREDIR, then we set redirnode to a structure containing
12231  *      the redirection.
12232  * In all cases, the variable startlinno is set to the number of the line
12233  *      on which the token starts.
12234  *
12235  * [Change comment:  here documents and internal procedures]
12236  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12237  *  word parsing code into a separate routine.  In this case, readtoken
12238  *  doesn't need to have any internal procedures, but parseword does.
12239  *  We could also make parseoperator in essence the main routine, and
12240  *  have parseword (readtoken1?) handle both words and redirection.]
12241  */
12242 #define NEW_xxreadtoken
12243 #ifdef NEW_xxreadtoken
12244 /* singles must be first! */
12245 static const char xxreadtoken_chars[7] ALIGN1 = {
12246         '\n', '(', ')', /* singles */
12247         '&', '|', ';',  /* doubles */
12248         0
12249 };
12250
12251 #define xxreadtoken_singles 3
12252 #define xxreadtoken_doubles 3
12253
12254 static const char xxreadtoken_tokens[] ALIGN1 = {
12255         TNL, TLP, TRP,          /* only single occurrence allowed */
12256         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12257         TEOF,                   /* corresponds to trailing nul */
12258         TAND, TOR, TENDCASE     /* if double occurrence */
12259 };
12260
12261 static int
12262 xxreadtoken(void)
12263 {
12264         int c;
12265
12266         if (tokpushback) {
12267                 tokpushback = 0;
12268                 return lasttoken;
12269         }
12270         setprompt_if(needprompt, 2);
12271         startlinno = g_parsefile->linno;
12272         for (;;) {                      /* until token or start of word found */
12273                 c = pgetc();
12274                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12275                         continue;
12276
12277                 if (c == '#') {
12278                         while ((c = pgetc()) != '\n' && c != PEOF)
12279                                 continue;
12280                         pungetc();
12281                 } else if (c == '\\') {
12282                         if (pgetc() != '\n') {
12283                                 pungetc();
12284                                 break; /* return readtoken1(...) */
12285                         }
12286                         nlprompt();
12287                 } else {
12288                         const char *p;
12289
12290                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12291                         if (c != PEOF) {
12292                                 if (c == '\n') {
12293                                         nlnoprompt();
12294                                 }
12295
12296                                 p = strchr(xxreadtoken_chars, c);
12297                                 if (p == NULL)
12298                                         break; /* return readtoken1(...) */
12299
12300                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12301                                         int cc = pgetc();
12302                                         if (cc == c) {    /* double occurrence? */
12303                                                 p += xxreadtoken_doubles + 1;
12304                                         } else {
12305                                                 pungetc();
12306 #if BASH_REDIR_OUTPUT
12307                                                 if (c == '&' && cc == '>') /* &> */
12308                                                         break; /* return readtoken1(...) */
12309 #endif
12310                                         }
12311                                 }
12312                         }
12313                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12314                         return lasttoken;
12315                 }
12316         } /* for (;;) */
12317
12318         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12319 }
12320 #else /* old xxreadtoken */
12321 #define RETURN(token)   return lasttoken = token
12322 static int
12323 xxreadtoken(void)
12324 {
12325         int c;
12326
12327         if (tokpushback) {
12328                 tokpushback = 0;
12329                 return lasttoken;
12330         }
12331         setprompt_if(needprompt, 2);
12332         startlinno = g_parsefile->linno;
12333         for (;;) {      /* until token or start of word found */
12334                 c = pgetc();
12335                 switch (c) {
12336                 case ' ': case '\t':
12337                 IF_ASH_ALIAS(case PEOA:)
12338                         continue;
12339                 case '#':
12340                         while ((c = pgetc()) != '\n' && c != PEOF)
12341                                 continue;
12342                         pungetc();
12343                         continue;
12344                 case '\\':
12345                         if (pgetc() == '\n') {
12346                                 nlprompt();
12347                                 continue;
12348                         }
12349                         pungetc();
12350                         goto breakloop;
12351                 case '\n':
12352                         nlnoprompt();
12353                         RETURN(TNL);
12354                 case PEOF:
12355                         RETURN(TEOF);
12356                 case '&':
12357                         if (pgetc() == '&')
12358                                 RETURN(TAND);
12359                         pungetc();
12360                         RETURN(TBACKGND);
12361                 case '|':
12362                         if (pgetc() == '|')
12363                                 RETURN(TOR);
12364                         pungetc();
12365                         RETURN(TPIPE);
12366                 case ';':
12367                         if (pgetc() == ';')
12368                                 RETURN(TENDCASE);
12369                         pungetc();
12370                         RETURN(TSEMI);
12371                 case '(':
12372                         RETURN(TLP);
12373                 case ')':
12374                         RETURN(TRP);
12375                 default:
12376                         goto breakloop;
12377                 }
12378         }
12379  breakloop:
12380         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12381 #undef RETURN
12382 }
12383 #endif /* old xxreadtoken */
12384
12385 static int
12386 readtoken(void)
12387 {
12388         int t;
12389         int kwd = checkkwd;
12390 #if DEBUG
12391         smallint alreadyseen = tokpushback;
12392 #endif
12393
12394 #if ENABLE_ASH_ALIAS
12395  top:
12396 #endif
12397
12398         t = xxreadtoken();
12399
12400         /*
12401          * eat newlines
12402          */
12403         if (kwd & CHKNL) {
12404                 while (t == TNL) {
12405                         parseheredoc();
12406                         t = xxreadtoken();
12407                 }
12408         }
12409
12410         if (t != TWORD || quoteflag) {
12411                 goto out;
12412         }
12413
12414         /*
12415          * check for keywords
12416          */
12417         if (kwd & CHKKWD) {
12418                 const char *const *pp;
12419
12420                 pp = findkwd(wordtext);
12421                 if (pp) {
12422                         lasttoken = t = pp - tokname_array;
12423                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12424                         goto out;
12425                 }
12426         }
12427
12428         if (checkkwd & CHKALIAS) {
12429 #if ENABLE_ASH_ALIAS
12430                 struct alias *ap;
12431                 ap = lookupalias(wordtext, 1);
12432                 if (ap != NULL) {
12433                         if (*ap->val) {
12434                                 pushstring(ap->val, ap);
12435                         }
12436                         goto top;
12437                 }
12438 #endif
12439         }
12440  out:
12441         checkkwd = 0;
12442 #if DEBUG
12443         if (!alreadyseen)
12444                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12445         else
12446                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12447 #endif
12448         return t;
12449 }
12450
12451 static int
12452 peektoken(void)
12453 {
12454         int t;
12455
12456         t = readtoken();
12457         tokpushback = 1;
12458         return t;
12459 }
12460
12461 /*
12462  * Read and parse a command.  Returns NODE_EOF on end of file.
12463  * (NULL is a valid parse tree indicating a blank line.)
12464  */
12465 static union node *
12466 parsecmd(int interact)
12467 {
12468         tokpushback = 0;
12469         checkkwd = 0;
12470         heredoclist = 0;
12471         doprompt = interact;
12472         setprompt_if(doprompt, doprompt);
12473         needprompt = 0;
12474         return list(1);
12475 }
12476
12477 /*
12478  * Input any here documents.
12479  */
12480 static void
12481 parseheredoc(void)
12482 {
12483         struct heredoc *here;
12484         union node *n;
12485
12486         here = heredoclist;
12487         heredoclist = NULL;
12488
12489         while (here) {
12490                 setprompt_if(needprompt, 2);
12491                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12492                                 here->eofmark, here->striptabs);
12493                 n = stzalloc(sizeof(struct narg));
12494                 n->narg.type = NARG;
12495                 /*n->narg.next = NULL; - stzalloc did it */
12496                 n->narg.text = wordtext;
12497                 n->narg.backquote = backquotelist;
12498                 here->here->nhere.doc = n;
12499                 here = here->next;
12500         }
12501 }
12502
12503
12504 /*
12505  * called by editline -- any expansions to the prompt should be added here.
12506  */
12507 static const char *
12508 expandstr(const char *ps)
12509 {
12510         union node n;
12511         int saveprompt;
12512
12513         /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
12514          * and token processing _can_ alter it (delete NULs etc). */
12515         setinputstring((char *)ps);
12516
12517         saveprompt = doprompt;
12518         doprompt = 0;
12519         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
12520         doprompt = saveprompt;
12521
12522         popfile();
12523
12524         n.narg.type = NARG;
12525         n.narg.next = NULL;
12526         n.narg.text = wordtext;
12527         n.narg.backquote = backquotelist;
12528
12529         expandarg(&n, NULL, EXP_QUOTED);
12530         return stackblock();
12531 }
12532
12533 static inline int
12534 parser_eof(void)
12535 {
12536         return tokpushback && lasttoken == TEOF;
12537 }
12538
12539 /*
12540  * Execute a command or commands contained in a string.
12541  */
12542 static int
12543 evalstring(char *s, int flags)
12544 {
12545         struct jmploc *volatile savehandler;
12546         struct jmploc jmploc;
12547         int ex;
12548
12549         union node *n;
12550         struct stackmark smark;
12551         int status;
12552
12553         s = sstrdup(s);
12554         setinputstring(s);
12555         setstackmark(&smark);
12556
12557         status = 0;
12558         /* On exception inside execution loop, we must popfile().
12559          * Try interactively:
12560          *      readonly a=a
12561          *      command eval "a=b"  # throws "is read only" error
12562          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12563          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12564          */
12565         savehandler = exception_handler;
12566         ex = setjmp(jmploc.loc);
12567         if (ex)
12568                 goto out;
12569         exception_handler = &jmploc;
12570
12571         while ((n = parsecmd(0)) != NODE_EOF) {
12572                 int i;
12573
12574                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12575                 if (n)
12576                         status = i;
12577                 popstackmark(&smark);
12578                 if (evalskip)
12579                         break;
12580         }
12581  out:
12582         popstackmark(&smark);
12583         popfile();
12584         stunalloc(s);
12585
12586         exception_handler = savehandler;
12587         if (ex)
12588                 longjmp(exception_handler->loc, ex);
12589
12590         return status;
12591 }
12592
12593 /*
12594  * The eval command.
12595  */
12596 static int FAST_FUNC
12597 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12598 {
12599         char *p;
12600         char *concat;
12601
12602         if (argv[1]) {
12603                 p = argv[1];
12604                 argv += 2;
12605                 if (argv[0]) {
12606                         STARTSTACKSTR(concat);
12607                         for (;;) {
12608                                 concat = stack_putstr(p, concat);
12609                                 p = *argv++;
12610                                 if (p == NULL)
12611                                         break;
12612                                 STPUTC(' ', concat);
12613                         }
12614                         STPUTC('\0', concat);
12615                         p = grabstackstr(concat);
12616                 }
12617                 return evalstring(p, flags & EV_TESTED);
12618         }
12619         return 0;
12620 }
12621
12622 /*
12623  * Read and execute commands.
12624  * "Top" is nonzero for the top level command loop;
12625  * it turns on prompting if the shell is interactive.
12626  */
12627 static int
12628 cmdloop(int top)
12629 {
12630         union node *n;
12631         struct stackmark smark;
12632         int inter;
12633         int status = 0;
12634         int numeof = 0;
12635
12636         TRACE(("cmdloop(%d) called\n", top));
12637         for (;;) {
12638                 int skip;
12639
12640                 setstackmark(&smark);
12641 #if JOBS
12642                 if (doing_jobctl)
12643                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12644 #endif
12645                 inter = 0;
12646                 if (iflag && top) {
12647                         inter++;
12648                         chkmail();
12649                 }
12650                 n = parsecmd(inter);
12651 #if DEBUG
12652                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12653                         showtree(n);
12654 #endif
12655                 if (n == NODE_EOF) {
12656                         if (!top || numeof >= 50)
12657                                 break;
12658                         if (!stoppedjobs()) {
12659                                 if (!Iflag)
12660                                         break;
12661                                 out2str("\nUse \"exit\" to leave shell.\n");
12662                         }
12663                         numeof++;
12664                 } else if (nflag == 0) {
12665                         int i;
12666
12667                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12668                         job_warning >>= 1;
12669                         numeof = 0;
12670                         i = evaltree(n, 0);
12671                         if (n)
12672                                 status = i;
12673                 }
12674                 popstackmark(&smark);
12675                 skip = evalskip;
12676
12677                 if (skip) {
12678                         evalskip &= ~SKIPFUNC;
12679                         break;
12680                 }
12681         }
12682         return status;
12683 }
12684
12685 /*
12686  * Take commands from a file.  To be compatible we should do a path
12687  * search for the file, which is necessary to find sub-commands.
12688  */
12689 static char *
12690 find_dot_file(char *name)
12691 {
12692         char *fullname;
12693         const char *path = pathval();
12694         struct stat statb;
12695
12696         /* don't try this for absolute or relative paths */
12697         if (strchr(name, '/'))
12698                 return name;
12699
12700         while ((fullname = path_advance(&path, name)) != NULL) {
12701                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12702                         /*
12703                          * Don't bother freeing here, since it will
12704                          * be freed by the caller.
12705                          */
12706                         return fullname;
12707                 }
12708                 if (fullname != name)
12709                         stunalloc(fullname);
12710         }
12711
12712         /* not found in the PATH */
12713         ash_msg_and_raise_error("%s: not found", name);
12714         /* NOTREACHED */
12715 }
12716
12717 static int FAST_FUNC
12718 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12719 {
12720         /* "false; . empty_file; echo $?" should print 0, not 1: */
12721         int status = 0;
12722         char *fullname;
12723         char **argv;
12724         char *args_need_save;
12725         volatile struct shparam saveparam;
12726
12727 //???
12728 //      struct strlist *sp;
12729 //      for (sp = cmdenviron; sp; sp = sp->next)
12730 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12731
12732         nextopt(nullstr); /* handle possible "--" */
12733         argv = argptr;
12734
12735         if (!argv[0]) {
12736                 /* bash says: "bash: .: filename argument required" */
12737                 return 2; /* bash compat */
12738         }
12739
12740         /* This aborts if file isn't found, which is POSIXly correct.
12741          * bash returns exitcode 1 instead.
12742          */
12743         fullname = find_dot_file(argv[0]);
12744         argv++;
12745         args_need_save = argv[0];
12746         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12747                 int argc;
12748                 saveparam = shellparam;
12749                 shellparam.malloced = 0;
12750                 argc = 1;
12751                 while (argv[argc])
12752                         argc++;
12753                 shellparam.nparam = argc;
12754                 shellparam.p = argv;
12755         };
12756
12757         /* This aborts if file can't be opened, which is POSIXly correct.
12758          * bash returns exitcode 1 instead.
12759          */
12760         setinputfile(fullname, INPUT_PUSH_FILE);
12761         commandname = fullname;
12762         status = cmdloop(0);
12763         popfile();
12764
12765         if (args_need_save) {
12766                 freeparam(&shellparam);
12767                 shellparam = saveparam;
12768         };
12769
12770         return status;
12771 }
12772
12773 static int FAST_FUNC
12774 exitcmd(int argc UNUSED_PARAM, char **argv)
12775 {
12776         if (stoppedjobs())
12777                 return 0;
12778         if (argv[1])
12779                 exitstatus = number(argv[1]);
12780         raise_exception(EXEXIT);
12781         /* NOTREACHED */
12782 }
12783
12784 /*
12785  * Read a file containing shell functions.
12786  */
12787 static void
12788 readcmdfile(char *name)
12789 {
12790         setinputfile(name, INPUT_PUSH_FILE);
12791         cmdloop(0);
12792         popfile();
12793 }
12794
12795
12796 /* ============ find_command inplementation */
12797
12798 /*
12799  * Resolve a command name.  If you change this routine, you may have to
12800  * change the shellexec routine as well.
12801  */
12802 static void
12803 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12804 {
12805         struct tblentry *cmdp;
12806         int idx;
12807         int prev;
12808         char *fullname;
12809         struct stat statb;
12810         int e;
12811         int updatetbl;
12812         struct builtincmd *bcmd;
12813
12814         /* If name contains a slash, don't use PATH or hash table */
12815         if (strchr(name, '/') != NULL) {
12816                 entry->u.index = -1;
12817                 if (act & DO_ABS) {
12818                         while (stat(name, &statb) < 0) {
12819 #ifdef SYSV
12820                                 if (errno == EINTR)
12821                                         continue;
12822 #endif
12823                                 entry->cmdtype = CMDUNKNOWN;
12824                                 return;
12825                         }
12826                 }
12827                 entry->cmdtype = CMDNORMAL;
12828                 return;
12829         }
12830
12831 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12832
12833         updatetbl = (path == pathval());
12834         if (!updatetbl) {
12835                 act |= DO_ALTPATH;
12836                 if (strstr(path, "%builtin") != NULL)
12837                         act |= DO_ALTBLTIN;
12838         }
12839
12840         /* If name is in the table, check answer will be ok */
12841         cmdp = cmdlookup(name, 0);
12842         if (cmdp != NULL) {
12843                 int bit;
12844
12845                 switch (cmdp->cmdtype) {
12846                 default:
12847 #if DEBUG
12848                         abort();
12849 #endif
12850                 case CMDNORMAL:
12851                         bit = DO_ALTPATH;
12852                         break;
12853                 case CMDFUNCTION:
12854                         bit = DO_NOFUNC;
12855                         break;
12856                 case CMDBUILTIN:
12857                         bit = DO_ALTBLTIN;
12858                         break;
12859                 }
12860                 if (act & bit) {
12861                         updatetbl = 0;
12862                         cmdp = NULL;
12863                 } else if (cmdp->rehash == 0)
12864                         /* if not invalidated by cd, we're done */
12865                         goto success;
12866         }
12867
12868         /* If %builtin not in path, check for builtin next */
12869         bcmd = find_builtin(name);
12870         if (bcmd) {
12871                 if (IS_BUILTIN_REGULAR(bcmd))
12872                         goto builtin_success;
12873                 if (act & DO_ALTPATH) {
12874                         if (!(act & DO_ALTBLTIN))
12875                                 goto builtin_success;
12876                 } else if (builtinloc <= 0) {
12877                         goto builtin_success;
12878                 }
12879         }
12880
12881 #if ENABLE_FEATURE_SH_STANDALONE
12882         {
12883                 int applet_no = find_applet_by_name(name);
12884                 if (applet_no >= 0) {
12885                         entry->cmdtype = CMDNORMAL;
12886                         entry->u.index = -2 - applet_no;
12887                         return;
12888                 }
12889         }
12890 #endif
12891
12892         /* We have to search path. */
12893         prev = -1;              /* where to start */
12894         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12895                 if (cmdp->cmdtype == CMDBUILTIN)
12896                         prev = builtinloc;
12897                 else
12898                         prev = cmdp->param.index;
12899         }
12900
12901         e = ENOENT;
12902         idx = -1;
12903  loop:
12904         while ((fullname = path_advance(&path, name)) != NULL) {
12905                 stunalloc(fullname);
12906                 /* NB: code below will still use fullname
12907                  * despite it being "unallocated" */
12908                 idx++;
12909                 if (pathopt) {
12910                         if (prefix(pathopt, "builtin")) {
12911                                 if (bcmd)
12912                                         goto builtin_success;
12913                                 continue;
12914                         }
12915                         if ((act & DO_NOFUNC)
12916                          || !prefix(pathopt, "func")
12917                         ) {     /* ignore unimplemented options */
12918                                 continue;
12919                         }
12920                 }
12921                 /* if rehash, don't redo absolute path names */
12922                 if (fullname[0] == '/' && idx <= prev) {
12923                         if (idx < prev)
12924                                 continue;
12925                         TRACE(("searchexec \"%s\": no change\n", name));
12926                         goto success;
12927                 }
12928                 while (stat(fullname, &statb) < 0) {
12929 #ifdef SYSV
12930                         if (errno == EINTR)
12931                                 continue;
12932 #endif
12933                         if (errno != ENOENT && errno != ENOTDIR)
12934                                 e = errno;
12935                         goto loop;
12936                 }
12937                 e = EACCES;     /* if we fail, this will be the error */
12938                 if (!S_ISREG(statb.st_mode))
12939                         continue;
12940                 if (pathopt) {          /* this is a %func directory */
12941                         stalloc(strlen(fullname) + 1);
12942                         /* NB: stalloc will return space pointed by fullname
12943                          * (because we don't have any intervening allocations
12944                          * between stunalloc above and this stalloc) */
12945                         readcmdfile(fullname);
12946                         cmdp = cmdlookup(name, 0);
12947                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12948                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12949                         stunalloc(fullname);
12950                         goto success;
12951                 }
12952                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12953                 if (!updatetbl) {
12954                         entry->cmdtype = CMDNORMAL;
12955                         entry->u.index = idx;
12956                         return;
12957                 }
12958                 INT_OFF;
12959                 cmdp = cmdlookup(name, 1);
12960                 cmdp->cmdtype = CMDNORMAL;
12961                 cmdp->param.index = idx;
12962                 INT_ON;
12963                 goto success;
12964         }
12965
12966         /* We failed.  If there was an entry for this command, delete it */
12967         if (cmdp && updatetbl)
12968                 delete_cmd_entry();
12969         if (act & DO_ERR)
12970                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12971         entry->cmdtype = CMDUNKNOWN;
12972         return;
12973
12974  builtin_success:
12975         if (!updatetbl) {
12976                 entry->cmdtype = CMDBUILTIN;
12977                 entry->u.cmd = bcmd;
12978                 return;
12979         }
12980         INT_OFF;
12981         cmdp = cmdlookup(name, 1);
12982         cmdp->cmdtype = CMDBUILTIN;
12983         cmdp->param.cmd = bcmd;
12984         INT_ON;
12985  success:
12986         cmdp->rehash = 0;
12987         entry->cmdtype = cmdp->cmdtype;
12988         entry->u = cmdp->param;
12989 }
12990
12991
12992 /*
12993  * The trap builtin.
12994  */
12995 static int FAST_FUNC
12996 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12997 {
12998         char *action;
12999         char **ap;
13000         int signo, exitcode;
13001
13002         nextopt(nullstr);
13003         ap = argptr;
13004         if (!*ap) {
13005                 for (signo = 0; signo < NSIG; signo++) {
13006                         char *tr = trap_ptr[signo];
13007                         if (tr) {
13008                                 /* note: bash adds "SIG", but only if invoked
13009                                  * as "bash". If called as "sh", or if set -o posix,
13010                                  * then it prints short signal names.
13011                                  * We are printing short names: */
13012                                 out1fmt("trap -- %s %s\n",
13013                                                 single_quote(tr),
13014                                                 get_signame(signo));
13015                 /* trap_ptr != trap only if we are in special-cased `trap` code.
13016                  * In this case, we will exit very soon, no need to free(). */
13017                                 /* if (trap_ptr != trap && tp[0]) */
13018                                 /*      free(tr); */
13019                         }
13020                 }
13021                 /*
13022                 if (trap_ptr != trap) {
13023                         free(trap_ptr);
13024                         trap_ptr = trap;
13025                 }
13026                 */
13027                 return 0;
13028         }
13029
13030         /* Why the second check?
13031          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13032          * In this case, NUM is signal no, not an action.
13033          */
13034         action = NULL;
13035         if (ap[1] && !is_number(ap[0]))
13036                 action = *ap++;
13037
13038         exitcode = 0;
13039         while (*ap) {
13040                 signo = get_signum(*ap);
13041                 if (signo < 0) {
13042                         /* Mimic bash message exactly */
13043                         ash_msg("%s: invalid signal specification", *ap);
13044                         exitcode = 1;
13045                         goto next;
13046                 }
13047                 INT_OFF;
13048                 if (action) {
13049                         if (LONE_DASH(action))
13050                                 action = NULL;
13051                         else {
13052                                 if (action[0]) /* not NULL and not "" and not "-" */
13053                                         may_have_traps = 1;
13054                                 action = ckstrdup(action);
13055                         }
13056                 }
13057                 free(trap[signo]);
13058                 trap[signo] = action;
13059                 if (signo != 0)
13060                         setsignal(signo);
13061                 INT_ON;
13062  next:
13063                 ap++;
13064         }
13065         return exitcode;
13066 }
13067
13068
13069 /* ============ Builtins */
13070
13071 #if ENABLE_ASH_HELP
13072 static int FAST_FUNC
13073 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13074 {
13075         unsigned col;
13076         unsigned i;
13077
13078         out1fmt(
13079                 "Built-in commands:\n"
13080                 "------------------\n");
13081         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13082                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13083                                         builtintab[i].name + 1);
13084                 if (col > 60) {
13085                         out1fmt("\n");
13086                         col = 0;
13087                 }
13088         }
13089 # if ENABLE_FEATURE_SH_STANDALONE
13090         {
13091                 const char *a = applet_names;
13092                 while (*a) {
13093                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13094                         if (col > 60) {
13095                                 out1fmt("\n");
13096                                 col = 0;
13097                         }
13098                         while (*a++ != '\0')
13099                                 continue;
13100                 }
13101         }
13102 # endif
13103         newline_and_flush(stdout);
13104         return EXIT_SUCCESS;
13105 }
13106 #endif
13107
13108 #if MAX_HISTORY
13109 static int FAST_FUNC
13110 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13111 {
13112         show_history(line_input_state);
13113         return EXIT_SUCCESS;
13114 }
13115 #endif
13116
13117 /*
13118  * The export and readonly commands.
13119  */
13120 static int FAST_FUNC
13121 exportcmd(int argc UNUSED_PARAM, char **argv)
13122 {
13123         struct var *vp;
13124         char *name;
13125         const char *p;
13126         char **aptr;
13127         char opt;
13128         int flag;
13129         int flag_off;
13130
13131         /* "readonly" in bash accepts, but ignores -n.
13132          * We do the same: it saves a conditional in nextopt's param.
13133          */
13134         flag_off = 0;
13135         while ((opt = nextopt("np")) != '\0') {
13136                 if (opt == 'n')
13137                         flag_off = VEXPORT;
13138         }
13139         flag = VEXPORT;
13140         if (argv[0][0] == 'r') {
13141                 flag = VREADONLY;
13142                 flag_off = 0; /* readonly ignores -n */
13143         }
13144         flag_off = ~flag_off;
13145
13146         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13147         {
13148                 aptr = argptr;
13149                 name = *aptr;
13150                 if (name) {
13151                         do {
13152                                 p = strchr(name, '=');
13153                                 if (p != NULL) {
13154                                         p++;
13155                                 } else {
13156                                         vp = *findvar(hashvar(name), name);
13157                                         if (vp) {
13158                                                 vp->flags = ((vp->flags | flag) & flag_off);
13159                                                 continue;
13160                                         }
13161                                 }
13162                                 setvar(name, p, (flag & flag_off));
13163                         } while ((name = *++aptr) != NULL);
13164                         return 0;
13165                 }
13166         }
13167
13168         /* No arguments. Show the list of exported or readonly vars.
13169          * -n is ignored.
13170          */
13171         showvars(argv[0], flag, 0);
13172         return 0;
13173 }
13174
13175 /*
13176  * Delete a function if it exists.
13177  */
13178 static void
13179 unsetfunc(const char *name)
13180 {
13181         struct tblentry *cmdp;
13182
13183         cmdp = cmdlookup(name, 0);
13184         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13185                 delete_cmd_entry();
13186 }
13187
13188 /*
13189  * The unset builtin command.  We unset the function before we unset the
13190  * variable to allow a function to be unset when there is a readonly variable
13191  * with the same name.
13192  */
13193 static int FAST_FUNC
13194 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13195 {
13196         char **ap;
13197         int i;
13198         int flag = 0;
13199
13200         while ((i = nextopt("vf")) != 0) {
13201                 flag = i;
13202         }
13203
13204         for (ap = argptr; *ap; ap++) {
13205                 if (flag != 'f') {
13206                         unsetvar(*ap);
13207                         continue;
13208                 }
13209                 if (flag != 'v')
13210                         unsetfunc(*ap);
13211         }
13212         return 0;
13213 }
13214
13215 static const unsigned char timescmd_str[] ALIGN1 = {
13216         ' ',  offsetof(struct tms, tms_utime),
13217         '\n', offsetof(struct tms, tms_stime),
13218         ' ',  offsetof(struct tms, tms_cutime),
13219         '\n', offsetof(struct tms, tms_cstime),
13220         0
13221 };
13222 static int FAST_FUNC
13223 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13224 {
13225         unsigned long clk_tck, s, t;
13226         const unsigned char *p;
13227         struct tms buf;
13228
13229         clk_tck = bb_clk_tck();
13230         times(&buf);
13231
13232         p = timescmd_str;
13233         do {
13234                 t = *(clock_t *)(((char *) &buf) + p[1]);
13235                 s = t / clk_tck;
13236                 t = t % clk_tck;
13237                 out1fmt("%lum%lu.%03lus%c",
13238                         s / 60, s % 60,
13239                         (t * 1000) / clk_tck,
13240                         p[0]);
13241                 p += 2;
13242         } while (*p);
13243
13244         return 0;
13245 }
13246
13247 #if ENABLE_FEATURE_SH_MATH
13248 /*
13249  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13250  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13251  *
13252  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13253  */
13254 static int FAST_FUNC
13255 letcmd(int argc UNUSED_PARAM, char **argv)
13256 {
13257         arith_t i;
13258
13259         argv++;
13260         if (!*argv)
13261                 ash_msg_and_raise_error("expression expected");
13262         do {
13263                 i = ash_arith(*argv);
13264         } while (*++argv);
13265
13266         return !i;
13267 }
13268 #endif
13269
13270 /*
13271  * The read builtin. Options:
13272  *      -r              Do not interpret '\' specially
13273  *      -s              Turn off echo (tty only)
13274  *      -n NCHARS       Read NCHARS max
13275  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13276  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13277  *      -u FD           Read from given FD instead of fd 0
13278  * This uses unbuffered input, which may be avoidable in some cases.
13279  * TODO: bash also has:
13280  *      -a ARRAY        Read into array[0],[1],etc
13281  *      -d DELIM        End on DELIM char, not newline
13282  *      -e              Use line editing (tty only)
13283  */
13284 static int FAST_FUNC
13285 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13286 {
13287         char *opt_n = NULL;
13288         char *opt_p = NULL;
13289         char *opt_t = NULL;
13290         char *opt_u = NULL;
13291         int read_flags = 0;
13292         const char *r;
13293         int i;
13294
13295         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13296                 switch (i) {
13297                 case 'p':
13298                         opt_p = optionarg;
13299                         break;
13300                 case 'n':
13301                         opt_n = optionarg;
13302                         break;
13303                 case 's':
13304                         read_flags |= BUILTIN_READ_SILENT;
13305                         break;
13306                 case 't':
13307                         opt_t = optionarg;
13308                         break;
13309                 case 'r':
13310                         read_flags |= BUILTIN_READ_RAW;
13311                         break;
13312                 case 'u':
13313                         opt_u = optionarg;
13314                         break;
13315                 default:
13316                         break;
13317                 }
13318         }
13319
13320         /* "read -s" needs to save/restore termios, can't allow ^C
13321          * to jump out of it.
13322          */
13323  again:
13324         INT_OFF;
13325         r = shell_builtin_read(setvar0,
13326                 argptr,
13327                 bltinlookup("IFS"), /* can be NULL */
13328                 read_flags,
13329                 opt_n,
13330                 opt_p,
13331                 opt_t,
13332                 opt_u
13333         );
13334         INT_ON;
13335
13336         if ((uintptr_t)r == 1 && errno == EINTR) {
13337                 /* to get SIGCHLD: sleep 1 & read x; echo $x */
13338                 if (pending_sig == 0)
13339                         goto again;
13340         }
13341
13342         if ((uintptr_t)r > 1)
13343                 ash_msg_and_raise_error(r);
13344
13345         return (uintptr_t)r;
13346 }
13347
13348 static int FAST_FUNC
13349 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13350 {
13351         static const char permuser[3] ALIGN1 = "ogu";
13352
13353         mode_t mask;
13354         int symbolic_mode = 0;
13355
13356         while (nextopt("S") != '\0') {
13357                 symbolic_mode = 1;
13358         }
13359
13360         INT_OFF;
13361         mask = umask(0);
13362         umask(mask);
13363         INT_ON;
13364
13365         if (*argptr == NULL) {
13366                 if (symbolic_mode) {
13367                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13368                         char *p = buf;
13369                         int i;
13370
13371                         i = 2;
13372                         for (;;) {
13373                                 *p++ = ',';
13374                                 *p++ = permuser[i];
13375                                 *p++ = '=';
13376                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13377                                 if (!(mask & 0400)) *p++ = 'r';
13378                                 if (!(mask & 0200)) *p++ = 'w';
13379                                 if (!(mask & 0100)) *p++ = 'x';
13380                                 mask <<= 3;
13381                                 if (--i < 0)
13382                                         break;
13383                         }
13384                         *p = '\0';
13385                         puts(buf + 1);
13386                 } else {
13387                         out1fmt("%04o\n", mask);
13388                 }
13389         } else {
13390                 char *modestr = *argptr;
13391                 /* numeric umasks are taken as-is */
13392                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13393                 if (!isdigit(modestr[0]))
13394                         mask ^= 0777;
13395                 mask = bb_parse_mode(modestr, mask);
13396                 if ((unsigned)mask > 0777) {
13397                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13398                 }
13399                 if (!isdigit(modestr[0]))
13400                         mask ^= 0777;
13401                 umask(mask);
13402         }
13403         return 0;
13404 }
13405
13406 static int FAST_FUNC
13407 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13408 {
13409         return shell_builtin_ulimit(argv);
13410 }
13411
13412 /* ============ main() and helpers */
13413
13414 /*
13415  * Called to exit the shell.
13416  */
13417 static void
13418 exitshell(void)
13419 {
13420         struct jmploc loc;
13421         char *p;
13422         int status;
13423
13424 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13425         save_history(line_input_state);
13426 #endif
13427         status = exitstatus;
13428         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13429         if (setjmp(loc.loc)) {
13430                 if (exception_type == EXEXIT)
13431                         status = exitstatus;
13432                 goto out;
13433         }
13434         exception_handler = &loc;
13435         p = trap[0];
13436         if (p) {
13437                 trap[0] = NULL;
13438                 evalskip = 0;
13439                 evalstring(p, 0);
13440                 /*free(p); - we'll exit soon */
13441         }
13442  out:
13443         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13444          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13445          */
13446         setjobctl(0);
13447         flush_stdout_stderr();
13448         _exit(status);
13449         /* NOTREACHED */
13450 }
13451
13452 static void
13453 init(void)
13454 {
13455         /* we will never free this */
13456         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13457
13458         sigmode[SIGCHLD - 1] = S_DFL;
13459         setsignal(SIGCHLD);
13460
13461         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13462          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13463          */
13464         signal(SIGHUP, SIG_DFL);
13465
13466         {
13467                 char **envp;
13468                 const char *p;
13469                 struct stat st1, st2;
13470
13471                 initvar();
13472                 for (envp = environ; envp && *envp; envp++) {
13473                         p = endofname(*envp);
13474                         if (p != *envp && *p == '=') {
13475                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13476                         }
13477                 }
13478
13479                 setvareq((char*)defoptindvar, VTEXTFIXED);
13480
13481                 setvar0("PPID", utoa(getppid()));
13482 #if BASH_SHLVL_VAR
13483                 p = lookupvar("SHLVL");
13484                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13485 #endif
13486 #if BASH_HOSTNAME_VAR
13487                 if (!lookupvar("HOSTNAME")) {
13488                         struct utsname uts;
13489                         uname(&uts);
13490                         setvar0("HOSTNAME", uts.nodename);
13491                 }
13492 #endif
13493                 p = lookupvar("PWD");
13494                 if (p) {
13495                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13496                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13497                         ) {
13498                                 p = NULL;
13499                         }
13500                 }
13501                 setpwd(p, 0);
13502         }
13503 }
13504
13505
13506 //usage:#define ash_trivial_usage
13507 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13508 //usage:#define ash_full_usage "\n\n"
13509 //usage:        "Unix shell interpreter"
13510
13511 /*
13512  * Process the shell command line arguments.
13513  */
13514 static void
13515 procargs(char **argv)
13516 {
13517         int i;
13518         const char *xminusc;
13519         char **xargv;
13520
13521         xargv = argv;
13522         arg0 = xargv[0];
13523         /* if (xargv[0]) - mmm, this is always true! */
13524                 xargv++;
13525         for (i = 0; i < NOPTS; i++)
13526                 optlist[i] = 2;
13527         argptr = xargv;
13528         if (options(/*cmdline:*/ 1)) {
13529                 /* it already printed err message */
13530                 raise_exception(EXERROR);
13531         }
13532         xargv = argptr;
13533         xminusc = minusc;
13534         if (*xargv == NULL) {
13535                 if (xminusc)
13536                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13537                 sflag = 1;
13538         }
13539         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13540                 iflag = 1;
13541         if (mflag == 2)
13542                 mflag = iflag;
13543         for (i = 0; i < NOPTS; i++)
13544                 if (optlist[i] == 2)
13545                         optlist[i] = 0;
13546 #if DEBUG == 2
13547         debug = 1;
13548 #endif
13549         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13550         if (xminusc) {
13551                 minusc = *xargv++;
13552                 if (*xargv)
13553                         goto setarg0;
13554         } else if (!sflag) {
13555                 setinputfile(*xargv, 0);
13556  setarg0:
13557                 arg0 = *xargv++;
13558                 commandname = arg0;
13559         }
13560
13561         shellparam.p = xargv;
13562 #if ENABLE_ASH_GETOPTS
13563         shellparam.optind = 1;
13564         shellparam.optoff = -1;
13565 #endif
13566         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13567         while (*xargv) {
13568                 shellparam.nparam++;
13569                 xargv++;
13570         }
13571         optschanged();
13572 }
13573
13574 /*
13575  * Read /etc/profile, ~/.profile, $ENV.
13576  */
13577 static void
13578 read_profile(const char *name)
13579 {
13580         name = expandstr(name);
13581         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13582                 return;
13583         cmdloop(0);
13584         popfile();
13585 }
13586
13587 /*
13588  * This routine is called when an error or an interrupt occurs in an
13589  * interactive shell and control is returned to the main command loop.
13590  * (In dash, this function is auto-generated by build machinery).
13591  */
13592 static void
13593 reset(void)
13594 {
13595         /* from eval.c: */
13596         evalskip = 0;
13597         loopnest = 0;
13598
13599         /* from expand.c: */
13600         ifsfree();
13601
13602         /* from input.c: */
13603         g_parsefile->left_in_buffer = 0;
13604         g_parsefile->left_in_line = 0;      /* clear input buffer */
13605         popallfiles();
13606
13607         /* from redir.c: */
13608         while (redirlist)
13609                 popredir(/*drop:*/ 0, /*restore:*/ 0);
13610
13611         /* from var.c: */
13612         unwindlocalvars(NULL);
13613 }
13614
13615 #if PROFILE
13616 static short profile_buf[16384];
13617 extern int etext();
13618 #endif
13619
13620 /*
13621  * Main routine.  We initialize things, parse the arguments, execute
13622  * profiles if we're a login shell, and then call cmdloop to execute
13623  * commands.  The setjmp call sets up the location to jump to when an
13624  * exception occurs.  When an exception occurs the variable "state"
13625  * is used to figure out how far we had gotten.
13626  */
13627 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13628 int ash_main(int argc UNUSED_PARAM, char **argv)
13629 {
13630         volatile smallint state;
13631         struct jmploc jmploc;
13632         struct stackmark smark;
13633
13634         /* Initialize global data */
13635         INIT_G_misc();
13636         INIT_G_memstack();
13637         INIT_G_var();
13638 #if ENABLE_ASH_ALIAS
13639         INIT_G_alias();
13640 #endif
13641         INIT_G_cmdtable();
13642
13643 #if PROFILE
13644         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13645 #endif
13646
13647 #if ENABLE_FEATURE_EDITING
13648         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13649 #endif
13650         state = 0;
13651         if (setjmp(jmploc.loc)) {
13652                 smallint e;
13653                 smallint s;
13654
13655                 reset();
13656
13657                 e = exception_type;
13658                 s = state;
13659                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13660                         exitshell();
13661                 }
13662                 if (e == EXINT) {
13663                         newline_and_flush(stderr);
13664                 }
13665
13666                 popstackmark(&smark);
13667                 FORCE_INT_ON; /* enable interrupts */
13668                 if (s == 1)
13669                         goto state1;
13670                 if (s == 2)
13671                         goto state2;
13672                 if (s == 3)
13673                         goto state3;
13674                 goto state4;
13675         }
13676         exception_handler = &jmploc;
13677         rootpid = getpid();
13678
13679         init();
13680         setstackmark(&smark);
13681         procargs(argv);
13682 #if DEBUG
13683         TRACE(("Shell args: "));
13684         trace_puts_args(argv);
13685 #endif
13686
13687         if (argv[0] && argv[0][0] == '-')
13688                 isloginsh = 1;
13689         if (isloginsh) {
13690                 const char *hp;
13691
13692                 state = 1;
13693                 read_profile("/etc/profile");
13694  state1:
13695                 state = 2;
13696                 hp = lookupvar("HOME");
13697                 if (hp)
13698                         read_profile("$HOME/.profile");
13699         }
13700  state2:
13701         state = 3;
13702         if (
13703 #ifndef linux
13704          getuid() == geteuid() && getgid() == getegid() &&
13705 #endif
13706          iflag
13707         ) {
13708                 const char *shinit = lookupvar("ENV");
13709                 if (shinit != NULL && *shinit != '\0')
13710                         read_profile(shinit);
13711         }
13712         popstackmark(&smark);
13713  state3:
13714         state = 4;
13715         if (minusc) {
13716                 /* evalstring pushes parsefile stack.
13717                  * Ensure we don't falsely claim that 0 (stdin)
13718                  * is one of stacked source fds.
13719                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13720                 // if (!sflag) g_parsefile->pf_fd = -1;
13721                 // ^^ not necessary since now we special-case fd 0
13722                 // in is_hidden_fd() to not be considered "hidden fd"
13723                 evalstring(minusc, sflag ? 0 : EV_EXIT);
13724         }
13725
13726         if (sflag || minusc == NULL) {
13727 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13728                 if (iflag) {
13729                         const char *hp = lookupvar("HISTFILE");
13730                         if (!hp) {
13731                                 hp = lookupvar("HOME");
13732                                 if (hp) {
13733                                         INT_OFF;
13734                                         hp = concat_path_file(hp, ".ash_history");
13735                                         setvar0("HISTFILE", hp);
13736                                         free((char*)hp);
13737                                         INT_ON;
13738                                         hp = lookupvar("HISTFILE");
13739                                 }
13740                         }
13741                         if (hp)
13742                                 line_input_state->hist_file = hp;
13743 # if ENABLE_FEATURE_SH_HISTFILESIZE
13744                         hp = lookupvar("HISTFILESIZE");
13745                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13746 # endif
13747                 }
13748 #endif
13749  state4: /* XXX ??? - why isn't this before the "if" statement */
13750                 cmdloop(1);
13751         }
13752 #if PROFILE
13753         monitor(0);
13754 #endif
13755 #ifdef GPROF
13756         {
13757                 extern void _mcleanup(void);
13758                 _mcleanup();
13759         }
13760 #endif
13761         TRACE(("End of main reached\n"));
13762         exitshell();
13763         /* NOTREACHED */
13764 }
13765
13766
13767 /*-
13768  * Copyright (c) 1989, 1991, 1993, 1994
13769  *      The Regents of the University of California.  All rights reserved.
13770  *
13771  * This code is derived from software contributed to Berkeley by
13772  * Kenneth Almquist.
13773  *
13774  * Redistribution and use in source and binary forms, with or without
13775  * modification, are permitted provided that the following conditions
13776  * are met:
13777  * 1. Redistributions of source code must retain the above copyright
13778  *    notice, this list of conditions and the following disclaimer.
13779  * 2. Redistributions in binary form must reproduce the above copyright
13780  *    notice, this list of conditions and the following disclaimer in the
13781  *    documentation and/or other materials provided with the distribution.
13782  * 3. Neither the name of the University nor the names of its contributors
13783  *    may be used to endorse or promote products derived from this software
13784  *    without specific prior written permission.
13785  *
13786  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13787  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13788  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13789  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13790  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13791  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13792  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13793  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13794  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13795  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13796  * SUCH DAMAGE.
13797  */