ash: [PARSER] Removed noexpand/length check on eofmark
[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 #define CHKEOFMARK      0x8
9995
9996 /*
9997  * Push a string back onto the input at this current parsefile level.
9998  * We handle aliases this way.
9999  */
10000 #if !ENABLE_ASH_ALIAS
10001 #define pushstring(s, ap) pushstring(s)
10002 #endif
10003 static void
10004 pushstring(char *s, struct alias *ap)
10005 {
10006         struct strpush *sp;
10007         int len;
10008
10009         len = strlen(s);
10010         INT_OFF;
10011         if (g_parsefile->strpush) {
10012                 sp = ckzalloc(sizeof(*sp));
10013                 sp->prev = g_parsefile->strpush;
10014         } else {
10015                 sp = &(g_parsefile->basestrpush);
10016         }
10017         g_parsefile->strpush = sp;
10018         sp->prev_string = g_parsefile->next_to_pgetc;
10019         sp->prev_left_in_line = g_parsefile->left_in_line;
10020         sp->unget = g_parsefile->unget;
10021         memcpy(sp->lastc, g_parsefile->lastc, sizeof(sp->lastc));
10022 #if ENABLE_ASH_ALIAS
10023         sp->ap = ap;
10024         if (ap) {
10025                 ap->flag |= ALIASINUSE;
10026                 sp->string = s;
10027         }
10028 #endif
10029         g_parsefile->next_to_pgetc = s;
10030         g_parsefile->left_in_line = len;
10031         g_parsefile->unget = 0;
10032         INT_ON;
10033 }
10034
10035 static void
10036 popstring(void)
10037 {
10038         struct strpush *sp = g_parsefile->strpush;
10039
10040         INT_OFF;
10041 #if ENABLE_ASH_ALIAS
10042         if (sp->ap) {
10043                 if (g_parsefile->next_to_pgetc[-1] == ' '
10044                  || g_parsefile->next_to_pgetc[-1] == '\t'
10045                 ) {
10046                         checkkwd |= CHKALIAS;
10047                 }
10048                 if (sp->string != sp->ap->val) {
10049                         free(sp->string);
10050                 }
10051                 sp->ap->flag &= ~ALIASINUSE;
10052                 if (sp->ap->flag & ALIASDEAD) {
10053                         unalias(sp->ap->name);
10054                 }
10055         }
10056 #endif
10057         g_parsefile->next_to_pgetc = sp->prev_string;
10058         g_parsefile->left_in_line = sp->prev_left_in_line;
10059         g_parsefile->unget = sp->unget;
10060         memcpy(g_parsefile->lastc, sp->lastc, sizeof(sp->lastc));
10061         g_parsefile->strpush = sp->prev;
10062         if (sp != &(g_parsefile->basestrpush))
10063                 free(sp);
10064         INT_ON;
10065 }
10066
10067 static int
10068 preadfd(void)
10069 {
10070         int nr;
10071         char *buf = g_parsefile->buf;
10072
10073         g_parsefile->next_to_pgetc = buf;
10074 #if ENABLE_FEATURE_EDITING
10075  retry:
10076         if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
10077                 nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10078         else {
10079                 int timeout = -1;
10080 # if ENABLE_ASH_IDLE_TIMEOUT
10081                 if (iflag) {
10082                         const char *tmout_var = lookupvar("TMOUT");
10083                         if (tmout_var) {
10084                                 timeout = atoi(tmout_var) * 1000;
10085                                 if (timeout <= 0)
10086                                         timeout = -1;
10087                         }
10088                 }
10089 # endif
10090 # if ENABLE_FEATURE_TAB_COMPLETION
10091                 line_input_state->path_lookup = pathval();
10092 # endif
10093                 reinit_unicode_for_ash();
10094                 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
10095                 if (nr == 0) {
10096                         /* ^C pressed, "convert" to SIGINT */
10097                         write(STDOUT_FILENO, "^C", 2);
10098                         if (trap[SIGINT]) {
10099                                 buf[0] = '\n';
10100                                 buf[1] = '\0';
10101                                 raise(SIGINT);
10102                                 return 1;
10103                         }
10104                         exitstatus = 128 + SIGINT;
10105                         bb_putchar('\n');
10106                         goto retry;
10107                 }
10108                 if (nr < 0) {
10109                         if (errno == 0) {
10110                                 /* Ctrl+D pressed */
10111                                 nr = 0;
10112                         }
10113 # if ENABLE_ASH_IDLE_TIMEOUT
10114                         else if (errno == EAGAIN && timeout > 0) {
10115                                 puts("\007timed out waiting for input: auto-logout");
10116                                 exitshell();
10117                         }
10118 # endif
10119                 }
10120         }
10121 #else
10122         nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1);
10123 #endif
10124
10125 #if 0 /* disabled: nonblock_immune_read() handles this problem */
10126         if (nr < 0) {
10127                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
10128                         int flags = fcntl(0, F_GETFL);
10129                         if (flags >= 0 && (flags & O_NONBLOCK)) {
10130                                 flags &= ~O_NONBLOCK;
10131                                 if (fcntl(0, F_SETFL, flags) >= 0) {
10132                                         out2str("sh: turning off NDELAY mode\n");
10133                                         goto retry;
10134                                 }
10135                         }
10136                 }
10137         }
10138 #endif
10139         return nr;
10140 }
10141
10142 /*
10143  * Refill the input buffer and return the next input character:
10144  *
10145  * 1) If a string was pushed back on the input, pop it;
10146  * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
10147  *    or we are reading from a string so we can't refill the buffer,
10148  *    return EOF.
10149  * 3) If there is more stuff in this buffer, use it else call read to fill it.
10150  * 4) Process input up to the next newline, deleting nul characters.
10151  */
10152 //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
10153 #define pgetc_debug(...) ((void)0)
10154 static int pgetc(void);
10155 static int
10156 preadbuffer(void)
10157 {
10158         char *q;
10159         int more;
10160
10161         if (g_parsefile->strpush) {
10162 #if ENABLE_ASH_ALIAS
10163                 if (g_parsefile->left_in_line == -1
10164                  && g_parsefile->strpush->ap
10165                  && g_parsefile->next_to_pgetc[-1] != ' '
10166                  && g_parsefile->next_to_pgetc[-1] != '\t'
10167                 ) {
10168                         pgetc_debug("preadbuffer PEOA");
10169                         return PEOA;
10170                 }
10171 #endif
10172                 popstring();
10173                 return pgetc();
10174         }
10175         /* on both branches above g_parsefile->left_in_line < 0.
10176          * "pgetc" needs refilling.
10177          */
10178
10179         /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
10180          * pungetc() may increment it a few times.
10181          * Assuming it won't increment it to less than -90.
10182          */
10183         if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
10184                 pgetc_debug("preadbuffer PEOF1");
10185                 /* even in failure keep left_in_line and next_to_pgetc
10186                  * in lock step, for correct multi-layer pungetc.
10187                  * left_in_line was decremented before preadbuffer(),
10188                  * must inc next_to_pgetc: */
10189                 g_parsefile->next_to_pgetc++;
10190                 return PEOF;
10191         }
10192
10193         more = g_parsefile->left_in_buffer;
10194         if (more <= 0) {
10195                 flush_stdout_stderr();
10196  again:
10197                 more = preadfd();
10198                 if (more <= 0) {
10199                         /* don't try reading again */
10200                         g_parsefile->left_in_line = -99;
10201                         pgetc_debug("preadbuffer PEOF2");
10202                         g_parsefile->next_to_pgetc++;
10203                         return PEOF;
10204                 }
10205         }
10206
10207         /* Find out where's the end of line.
10208          * Set g_parsefile->left_in_line
10209          * and g_parsefile->left_in_buffer acordingly.
10210          * NUL chars are deleted.
10211          */
10212         q = g_parsefile->next_to_pgetc;
10213         for (;;) {
10214                 char c;
10215
10216                 more--;
10217
10218                 c = *q;
10219                 if (c == '\0') {
10220                         memmove(q, q + 1, more);
10221                 } else {
10222                         q++;
10223                         if (c == '\n') {
10224                                 g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10225                                 break;
10226                         }
10227                 }
10228
10229                 if (more <= 0) {
10230                         g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
10231                         if (g_parsefile->left_in_line < 0)
10232                                 goto again;
10233                         break;
10234                 }
10235         }
10236         g_parsefile->left_in_buffer = more;
10237
10238         if (vflag) {
10239                 char save = *q;
10240                 *q = '\0';
10241                 out2str(g_parsefile->next_to_pgetc);
10242                 *q = save;
10243         }
10244
10245         pgetc_debug("preadbuffer at %d:%p'%s'",
10246                         g_parsefile->left_in_line,
10247                         g_parsefile->next_to_pgetc,
10248                         g_parsefile->next_to_pgetc);
10249         return (unsigned char)*g_parsefile->next_to_pgetc++;
10250 }
10251
10252 static void
10253 nlprompt(void)
10254 {
10255         g_parsefile->linno++;
10256         setprompt_if(doprompt, 2);
10257 }
10258 static void
10259 nlnoprompt(void)
10260 {
10261         g_parsefile->linno++;
10262         needprompt = doprompt;
10263 }
10264
10265 static int
10266 pgetc(void)
10267 {
10268         int c;
10269
10270         pgetc_debug("pgetc at %d:%p'%s'",
10271                         g_parsefile->left_in_line,
10272                         g_parsefile->next_to_pgetc,
10273                         g_parsefile->next_to_pgetc);
10274         if (g_parsefile->unget)
10275                 return g_parsefile->lastc[--g_parsefile->unget];
10276
10277         if (--g_parsefile->left_in_line >= 0)
10278                 c = (unsigned char)*g_parsefile->next_to_pgetc++;
10279         else
10280                 c = preadbuffer();
10281
10282         g_parsefile->lastc[1] = g_parsefile->lastc[0];
10283         g_parsefile->lastc[0] = c;
10284
10285         return c;
10286 }
10287
10288 #if ENABLE_ASH_ALIAS
10289 static int
10290 pgetc_without_PEOA(void)
10291 {
10292         int c;
10293         do {
10294                 pgetc_debug("pgetc at %d:%p'%s'",
10295                                 g_parsefile->left_in_line,
10296                                 g_parsefile->next_to_pgetc,
10297                                 g_parsefile->next_to_pgetc);
10298                 c = pgetc();
10299         } while (c == PEOA);
10300         return c;
10301 }
10302 #else
10303 # define pgetc_without_PEOA() pgetc()
10304 #endif
10305
10306 /*
10307  * Undo a call to pgetc.  Only two characters may be pushed back.
10308  * PEOF may be pushed back.
10309  */
10310 static void
10311 pungetc(void)
10312 {
10313         g_parsefile->unget++;
10314 }
10315
10316 /* This one eats backslash+newline */
10317 static int
10318 pgetc_eatbnl(void)
10319 {
10320         int c;
10321
10322         while ((c = pgetc()) == '\\') {
10323                 if (pgetc() != '\n') {
10324                         pungetc();
10325                         break;
10326                 }
10327
10328                 nlprompt();
10329         }
10330
10331         return c;
10332 }
10333
10334 /*
10335  * To handle the "." command, a stack of input files is used.  Pushfile
10336  * adds a new entry to the stack and popfile restores the previous level.
10337  */
10338 static void
10339 pushfile(void)
10340 {
10341         struct parsefile *pf;
10342
10343         pf = ckzalloc(sizeof(*pf));
10344         pf->prev = g_parsefile;
10345         pf->pf_fd = -1;
10346         /*pf->strpush = NULL; - ckzalloc did it */
10347         /*pf->basestrpush.prev = NULL;*/
10348         /*pf->unget = 0;*/
10349         g_parsefile = pf;
10350 }
10351
10352 static void
10353 popfile(void)
10354 {
10355         struct parsefile *pf = g_parsefile;
10356
10357         if (pf == &basepf)
10358                 return;
10359
10360         INT_OFF;
10361         if (pf->pf_fd >= 0)
10362                 close(pf->pf_fd);
10363         free(pf->buf);
10364         while (pf->strpush)
10365                 popstring();
10366         g_parsefile = pf->prev;
10367         free(pf);
10368         INT_ON;
10369 }
10370
10371 /*
10372  * Return to top level.
10373  */
10374 static void
10375 popallfiles(void)
10376 {
10377         while (g_parsefile != &basepf)
10378                 popfile();
10379 }
10380
10381 /*
10382  * Close the file(s) that the shell is reading commands from.  Called
10383  * after a fork is done.
10384  */
10385 static void
10386 closescript(void)
10387 {
10388         popallfiles();
10389         if (g_parsefile->pf_fd > 0) {
10390                 close(g_parsefile->pf_fd);
10391                 g_parsefile->pf_fd = 0;
10392         }
10393 }
10394
10395 /*
10396  * Like setinputfile, but takes an open file descriptor.  Call this with
10397  * interrupts off.
10398  */
10399 static void
10400 setinputfd(int fd, int push)
10401 {
10402         if (push) {
10403                 pushfile();
10404                 g_parsefile->buf = NULL;
10405         }
10406         g_parsefile->pf_fd = fd;
10407         if (g_parsefile->buf == NULL)
10408                 g_parsefile->buf = ckmalloc(IBUFSIZ);
10409         g_parsefile->left_in_buffer = 0;
10410         g_parsefile->left_in_line = 0;
10411         g_parsefile->linno = 1;
10412 }
10413
10414 /*
10415  * Set the input to take input from a file.  If push is set, push the
10416  * old input onto the stack first.
10417  */
10418 static int
10419 setinputfile(const char *fname, int flags)
10420 {
10421         int fd;
10422
10423         INT_OFF;
10424         fd = open(fname, O_RDONLY);
10425         if (fd < 0) {
10426                 if (flags & INPUT_NOFILE_OK)
10427                         goto out;
10428                 exitstatus = 127;
10429                 ash_msg_and_raise_error("can't open '%s'", fname);
10430         }
10431         if (fd < 10)
10432                 fd = savefd(fd);
10433         else
10434                 close_on_exec_on(fd);
10435         setinputfd(fd, flags & INPUT_PUSH_FILE);
10436  out:
10437         INT_ON;
10438         return fd;
10439 }
10440
10441 /*
10442  * Like setinputfile, but takes input from a string.
10443  */
10444 static void
10445 setinputstring(char *string)
10446 {
10447         INT_OFF;
10448         pushfile();
10449         g_parsefile->next_to_pgetc = string;
10450         g_parsefile->left_in_line = strlen(string);
10451         g_parsefile->buf = NULL;
10452         g_parsefile->linno = 1;
10453         INT_ON;
10454 }
10455
10456
10457 /*
10458  * Routines to check for mail.
10459  */
10460
10461 #if ENABLE_ASH_MAIL
10462
10463 /* Hash of mtimes of mailboxes */
10464 static unsigned mailtime_hash;
10465 /* Set if MAIL or MAILPATH is changed. */
10466 static smallint mail_var_path_changed;
10467
10468 /*
10469  * Print appropriate message(s) if mail has arrived.
10470  * If mail_var_path_changed is set,
10471  * then the value of MAIL has mail_var_path_changed,
10472  * so we just update the values.
10473  */
10474 static void
10475 chkmail(void)
10476 {
10477         const char *mpath;
10478         char *p;
10479         char *q;
10480         unsigned new_hash;
10481         struct stackmark smark;
10482         struct stat statb;
10483
10484         setstackmark(&smark);
10485         mpath = mpathset() ? mpathval() : mailval();
10486         new_hash = 0;
10487         for (;;) {
10488                 p = path_advance(&mpath, nullstr);
10489                 if (p == NULL)
10490                         break;
10491                 if (*p == '\0')
10492                         continue;
10493                 for (q = p; *q; q++)
10494                         continue;
10495 #if DEBUG
10496                 if (q[-1] != '/')
10497                         abort();
10498 #endif
10499                 q[-1] = '\0';                   /* delete trailing '/' */
10500                 if (stat(p, &statb) < 0) {
10501                         continue;
10502                 }
10503                 /* Very simplistic "hash": just a sum of all mtimes */
10504                 new_hash += (unsigned)statb.st_mtime;
10505         }
10506         if (!mail_var_path_changed && mailtime_hash != new_hash) {
10507                 if (mailtime_hash != 0)
10508                         out2str("you have mail\n");
10509                 mailtime_hash = new_hash;
10510         }
10511         mail_var_path_changed = 0;
10512         popstackmark(&smark);
10513 }
10514
10515 static void FAST_FUNC
10516 changemail(const char *val UNUSED_PARAM)
10517 {
10518         mail_var_path_changed = 1;
10519 }
10520
10521 #endif /* ASH_MAIL */
10522
10523
10524 /* ============ ??? */
10525
10526 /*
10527  * Set the shell parameters.
10528  */
10529 static void
10530 setparam(char **argv)
10531 {
10532         char **newparam;
10533         char **ap;
10534         int nparam;
10535
10536         for (nparam = 0; argv[nparam]; nparam++)
10537                 continue;
10538         ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
10539         while (*argv) {
10540                 *ap++ = ckstrdup(*argv++);
10541         }
10542         *ap = NULL;
10543         freeparam(&shellparam);
10544         shellparam.malloced = 1;
10545         shellparam.nparam = nparam;
10546         shellparam.p = newparam;
10547 #if ENABLE_ASH_GETOPTS
10548         shellparam.optind = 1;
10549         shellparam.optoff = -1;
10550 #endif
10551 }
10552
10553 /*
10554  * Process shell options.  The global variable argptr contains a pointer
10555  * to the argument list; we advance it past the options.
10556  *
10557  * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
10558  * For a non-interactive shell, an error condition encountered
10559  * by a special built-in ... shall cause the shell to write a diagnostic message
10560  * to standard error and exit as shown in the following table:
10561  * Error                                           Special Built-In
10562  * ...
10563  * Utility syntax error (option or operand error)  Shall exit
10564  * ...
10565  * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
10566  * we see that bash does not do that (set "finishes" with error code 1 instead,
10567  * and shell continues), and people rely on this behavior!
10568  * Testcase:
10569  * set -o barfoo 2>/dev/null
10570  * echo $?
10571  *
10572  * Oh well. Let's mimic that.
10573  */
10574 static int
10575 plus_minus_o(char *name, int val)
10576 {
10577         int i;
10578
10579         if (name) {
10580                 for (i = 0; i < NOPTS; i++) {
10581                         if (strcmp(name, optnames(i)) == 0) {
10582                                 optlist[i] = val;
10583                                 return 0;
10584                         }
10585                 }
10586                 ash_msg("illegal option %co %s", val ? '-' : '+', name);
10587                 return 1;
10588         }
10589         for (i = 0; i < NOPTS; i++) {
10590                 if (val) {
10591                         out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
10592                 } else {
10593                         out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
10594                 }
10595         }
10596         return 0;
10597 }
10598 static void
10599 setoption(int flag, int val)
10600 {
10601         int i;
10602
10603         for (i = 0; i < NOPTS; i++) {
10604                 if (optletters(i) == flag) {
10605                         optlist[i] = val;
10606                         return;
10607                 }
10608         }
10609         ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
10610         /* NOTREACHED */
10611 }
10612 static int
10613 options(int cmdline)
10614 {
10615         char *p;
10616         int val;
10617         int c;
10618
10619         if (cmdline)
10620                 minusc = NULL;
10621         while ((p = *argptr) != NULL) {
10622                 c = *p++;
10623                 if (c != '-' && c != '+')
10624                         break;
10625                 argptr++;
10626                 val = 0; /* val = 0 if c == '+' */
10627                 if (c == '-') {
10628                         val = 1;
10629                         if (p[0] == '\0' || LONE_DASH(p)) {
10630                                 if (!cmdline) {
10631                                         /* "-" means turn off -x and -v */
10632                                         if (p[0] == '\0')
10633                                                 xflag = vflag = 0;
10634                                         /* "--" means reset params */
10635                                         else if (*argptr == NULL)
10636                                                 setparam(argptr);
10637                                 }
10638                                 break;    /* "-" or "--" terminates options */
10639                         }
10640                 }
10641                 /* first char was + or - */
10642                 while ((c = *p++) != '\0') {
10643                         /* bash 3.2 indeed handles -c CMD and +c CMD the same */
10644                         if (c == 'c' && cmdline) {
10645                                 minusc = p;     /* command is after shell args */
10646                         } else if (c == 'o') {
10647                                 if (plus_minus_o(*argptr, val)) {
10648                                         /* it already printed err message */
10649                                         return 1; /* error */
10650                                 }
10651                                 if (*argptr)
10652                                         argptr++;
10653                         } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
10654                                 isloginsh = 1;
10655                         /* bash does not accept +-login, we also won't */
10656                         } else if (cmdline && val && (c == '-')) { /* long options */
10657                                 if (strcmp(p, "login") == 0)
10658                                         isloginsh = 1;
10659                                 break;
10660                         } else {
10661                                 setoption(c, val);
10662                         }
10663                 }
10664         }
10665         return 0;
10666 }
10667
10668 /*
10669  * The shift builtin command.
10670  */
10671 static int FAST_FUNC
10672 shiftcmd(int argc UNUSED_PARAM, char **argv)
10673 {
10674         int n;
10675         char **ap1, **ap2;
10676
10677         n = 1;
10678         if (argv[1])
10679                 n = number(argv[1]);
10680         if (n > shellparam.nparam)
10681                 n = 0; /* bash compat, was = shellparam.nparam; */
10682         INT_OFF;
10683         shellparam.nparam -= n;
10684         for (ap1 = shellparam.p; --n >= 0; ap1++) {
10685                 if (shellparam.malloced)
10686                         free(*ap1);
10687         }
10688         ap2 = shellparam.p;
10689         while ((*ap2++ = *ap1++) != NULL)
10690                 continue;
10691 #if ENABLE_ASH_GETOPTS
10692         shellparam.optind = 1;
10693         shellparam.optoff = -1;
10694 #endif
10695         INT_ON;
10696         return 0;
10697 }
10698
10699 /*
10700  * POSIX requires that 'set' (but not export or readonly) output the
10701  * variables in lexicographic order - by the locale's collating order (sigh).
10702  * Maybe we could keep them in an ordered balanced binary tree
10703  * instead of hashed lists.
10704  * For now just roll 'em through qsort for printing...
10705  */
10706 static int
10707 showvars(const char *sep_prefix, int on, int off)
10708 {
10709         const char *sep;
10710         char **ep, **epend;
10711
10712         ep = listvars(on, off, &epend);
10713         qsort(ep, epend - ep, sizeof(char *), vpcmp);
10714
10715         sep = *sep_prefix ? " " : sep_prefix;
10716
10717         for (; ep < epend; ep++) {
10718                 const char *p;
10719                 const char *q;
10720
10721                 p = strchrnul(*ep, '=');
10722                 q = nullstr;
10723                 if (*p)
10724                         q = single_quote(++p);
10725                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
10726         }
10727         return 0;
10728 }
10729
10730 /*
10731  * The set command builtin.
10732  */
10733 static int FAST_FUNC
10734 setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10735 {
10736         int retval;
10737
10738         if (!argv[1])
10739                 return showvars(nullstr, 0, VUNSET);
10740
10741         INT_OFF;
10742         retval = options(/*cmdline:*/ 0);
10743         if (retval == 0) { /* if no parse error... */
10744                 optschanged();
10745                 if (*argptr != NULL) {
10746                         setparam(argptr);
10747                 }
10748         }
10749         INT_ON;
10750         return retval;
10751 }
10752
10753 #if ENABLE_ASH_RANDOM_SUPPORT
10754 static void FAST_FUNC
10755 change_random(const char *value)
10756 {
10757         uint32_t t;
10758
10759         if (value == NULL) {
10760                 /* "get", generate */
10761                 t = next_random(&random_gen);
10762                 /* set without recursion */
10763                 setvar(vrandom.var_text, utoa(t), VNOFUNC);
10764                 vrandom.flags &= ~VNOFUNC;
10765         } else {
10766                 /* set/reset */
10767                 t = strtoul(value, NULL, 10);
10768                 INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
10769         }
10770 }
10771 #endif
10772
10773 #if ENABLE_ASH_GETOPTS
10774 static int
10775 getopts(char *optstr, char *optvar, char **optfirst)
10776 {
10777         char *p, *q;
10778         char c = '?';
10779         int done = 0;
10780         char sbuf[2];
10781         char **optnext;
10782         int ind = shellparam.optind;
10783         int off = shellparam.optoff;
10784
10785         sbuf[1] = '\0';
10786
10787         shellparam.optind = -1;
10788         optnext = optfirst + ind - 1;
10789
10790         if (ind <= 1 || off < 0 || (int)strlen(optnext[-1]) < off)
10791                 p = NULL;
10792         else
10793                 p = optnext[-1] + off;
10794         if (p == NULL || *p == '\0') {
10795                 /* Current word is done, advance */
10796                 p = *optnext;
10797                 if (p == NULL || *p != '-' || *++p == '\0') {
10798  atend:
10799                         p = NULL;
10800                         done = 1;
10801                         goto out;
10802                 }
10803                 optnext++;
10804                 if (LONE_DASH(p))        /* check for "--" */
10805                         goto atend;
10806         }
10807
10808         c = *p++;
10809         for (q = optstr; *q != c;) {
10810                 if (*q == '\0') {
10811                         if (optstr[0] == ':') {
10812                                 sbuf[0] = c;
10813                                 /*sbuf[1] = '\0'; - already is */
10814                                 setvar0("OPTARG", sbuf);
10815                         } else {
10816                                 fprintf(stderr, "Illegal option -%c\n", c);
10817                                 unsetvar("OPTARG");
10818                         }
10819                         c = '?';
10820                         goto out;
10821                 }
10822                 if (*++q == ':')
10823                         q++;
10824         }
10825
10826         if (*++q == ':') {
10827                 if (*p == '\0' && (p = *optnext) == NULL) {
10828                         if (optstr[0] == ':') {
10829                                 sbuf[0] = c;
10830                                 /*sbuf[1] = '\0'; - already is */
10831                                 setvar0("OPTARG", sbuf);
10832                                 c = ':';
10833                         } else {
10834                                 fprintf(stderr, "No arg for -%c option\n", c);
10835                                 unsetvar("OPTARG");
10836                                 c = '?';
10837                         }
10838                         goto out;
10839                 }
10840
10841                 if (p == *optnext)
10842                         optnext++;
10843                 setvar0("OPTARG", p);
10844                 p = NULL;
10845         } else
10846                 setvar0("OPTARG", nullstr);
10847  out:
10848         ind = optnext - optfirst + 1;
10849         setvar("OPTIND", itoa(ind), VNOFUNC);
10850         sbuf[0] = c;
10851         /*sbuf[1] = '\0'; - already is */
10852         setvar0(optvar, sbuf);
10853
10854         shellparam.optoff = p ? p - *(optnext - 1) : -1;
10855         shellparam.optind = ind;
10856
10857         return done;
10858 }
10859
10860 /*
10861  * The getopts builtin.  Shellparam.optnext points to the next argument
10862  * to be processed.  Shellparam.optptr points to the next character to
10863  * be processed in the current argument.  If shellparam.optnext is NULL,
10864  * then it's the first time getopts has been called.
10865  */
10866 static int FAST_FUNC
10867 getoptscmd(int argc, char **argv)
10868 {
10869         char **optbase;
10870
10871         if (argc < 3)
10872                 ash_msg_and_raise_error("usage: getopts optstring var [arg]");
10873         if (argc == 3) {
10874                 optbase = shellparam.p;
10875                 if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
10876                         shellparam.optind = 1;
10877                         shellparam.optoff = -1;
10878                 }
10879         } else {
10880                 optbase = &argv[3];
10881                 if ((unsigned)shellparam.optind > argc - 2) {
10882                         shellparam.optind = 1;
10883                         shellparam.optoff = -1;
10884                 }
10885         }
10886
10887         return getopts(argv[1], argv[2], optbase);
10888 }
10889 #endif /* ASH_GETOPTS */
10890
10891
10892 /* ============ Shell parser */
10893
10894 struct heredoc {
10895         struct heredoc *next;   /* next here document in list */
10896         union node *here;       /* redirection node */
10897         char *eofmark;          /* string indicating end of input */
10898         smallint striptabs;     /* if set, strip leading tabs */
10899 };
10900
10901 static smallint tokpushback;           /* last token pushed back */
10902 static smallint quoteflag;             /* set if (part of) last token was quoted */
10903 static token_id_t lasttoken;           /* last token read (integer id Txxx) */
10904 static struct heredoc *heredoclist;    /* list of here documents to read */
10905 static char *wordtext;                 /* text of last word returned by readtoken */
10906 static struct nodelist *backquotelist;
10907 static union node *redirnode;
10908 static struct heredoc *heredoc;
10909
10910 static const char *
10911 tokname(char *buf, int tok)
10912 {
10913         if (tok < TSEMI)
10914                 return tokname_array[tok];
10915         sprintf(buf, "\"%s\"", tokname_array[tok]);
10916         return buf;
10917 }
10918
10919 /* raise_error_unexpected_syntax:
10920  * Called when an unexpected token is read during the parse.  The argument
10921  * is the token that is expected, or -1 if more than one type of token can
10922  * occur at this point.
10923  */
10924 static void raise_error_unexpected_syntax(int) NORETURN;
10925 static void
10926 raise_error_unexpected_syntax(int token)
10927 {
10928         char msg[64];
10929         char buf[16];
10930         int l;
10931
10932         l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
10933         if (token >= 0)
10934                 sprintf(msg + l, " (expecting %s)", tokname(buf, token));
10935         raise_error_syntax(msg);
10936         /* NOTREACHED */
10937 }
10938
10939 /* parsing is heavily cross-recursive, need these forward decls */
10940 static union node *andor(void);
10941 static union node *pipeline(void);
10942 static union node *parse_command(void);
10943 static void parseheredoc(void);
10944 static int peektoken(void);
10945 static int readtoken(void);
10946
10947 static union node *
10948 list(int nlflag)
10949 {
10950         union node *n1, *n2, *n3;
10951         int tok;
10952
10953         n1 = NULL;
10954         for (;;) {
10955                 switch (peektoken()) {
10956                 case TNL:
10957                         if (!(nlflag & 1))
10958                                 break;
10959                         parseheredoc();
10960                         return n1;
10961
10962                 case TEOF:
10963                         if (!n1 && (nlflag & 1))
10964                                 n1 = NODE_EOF;
10965                         parseheredoc();
10966                         return n1;
10967                 }
10968
10969                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
10970                 if (nlflag == 2 && ((1 << peektoken()) & tokendlist))
10971                         return n1;
10972                 nlflag |= 2;
10973
10974                 n2 = andor();
10975                 tok = readtoken();
10976                 if (tok == TBACKGND) {
10977                         if (n2->type == NPIPE) {
10978                                 n2->npipe.pipe_backgnd = 1;
10979                         } else {
10980                                 if (n2->type != NREDIR) {
10981                                         n3 = stzalloc(sizeof(struct nredir));
10982                                         n3->nredir.n = n2;
10983                                         /*n3->nredir.redirect = NULL; - stzalloc did it */
10984                                         n2 = n3;
10985                                 }
10986                                 n2->type = NBACKGND;
10987                         }
10988                 }
10989                 if (n1 == NULL) {
10990                         n1 = n2;
10991                 } else {
10992                         n3 = stzalloc(sizeof(struct nbinary));
10993                         n3->type = NSEMI;
10994                         n3->nbinary.ch1 = n1;
10995                         n3->nbinary.ch2 = n2;
10996                         n1 = n3;
10997                 }
10998                 switch (tok) {
10999                 case TNL:
11000                 case TEOF:
11001                         tokpushback = 1;
11002                         /* fall through */
11003                 case TBACKGND:
11004                 case TSEMI:
11005                         break;
11006                 default:
11007                         if ((nlflag & 1))
11008                                 raise_error_unexpected_syntax(-1);
11009                         tokpushback = 1;
11010                         return n1;
11011                 }
11012         }
11013 }
11014
11015 static union node *
11016 andor(void)
11017 {
11018         union node *n1, *n2, *n3;
11019         int t;
11020
11021         n1 = pipeline();
11022         for (;;) {
11023                 t = readtoken();
11024                 if (t == TAND) {
11025                         t = NAND;
11026                 } else if (t == TOR) {
11027                         t = NOR;
11028                 } else {
11029                         tokpushback = 1;
11030                         return n1;
11031                 }
11032                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11033                 n2 = pipeline();
11034                 n3 = stzalloc(sizeof(struct nbinary));
11035                 n3->type = t;
11036                 n3->nbinary.ch1 = n1;
11037                 n3->nbinary.ch2 = n2;
11038                 n1 = n3;
11039         }
11040 }
11041
11042 static union node *
11043 pipeline(void)
11044 {
11045         union node *n1, *n2, *pipenode;
11046         struct nodelist *lp, *prev;
11047         int negate;
11048
11049         negate = 0;
11050         TRACE(("pipeline: entered\n"));
11051         if (readtoken() == TNOT) {
11052                 negate = !negate;
11053                 checkkwd = CHKKWD | CHKALIAS;
11054         } else
11055                 tokpushback = 1;
11056         n1 = parse_command();
11057         if (readtoken() == TPIPE) {
11058                 pipenode = stzalloc(sizeof(struct npipe));
11059                 pipenode->type = NPIPE;
11060                 /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
11061                 lp = stzalloc(sizeof(struct nodelist));
11062                 pipenode->npipe.cmdlist = lp;
11063                 lp->n = n1;
11064                 do {
11065                         prev = lp;
11066                         lp = stzalloc(sizeof(struct nodelist));
11067                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
11068                         lp->n = parse_command();
11069                         prev->next = lp;
11070                 } while (readtoken() == TPIPE);
11071                 lp->next = NULL;
11072                 n1 = pipenode;
11073         }
11074         tokpushback = 1;
11075         if (negate) {
11076                 n2 = stzalloc(sizeof(struct nnot));
11077                 n2->type = NNOT;
11078                 n2->nnot.com = n1;
11079                 return n2;
11080         }
11081         return n1;
11082 }
11083
11084 static union node *
11085 makename(void)
11086 {
11087         union node *n;
11088
11089         n = stzalloc(sizeof(struct narg));
11090         n->type = NARG;
11091         /*n->narg.next = NULL; - stzalloc did it */
11092         n->narg.text = wordtext;
11093         n->narg.backquote = backquotelist;
11094         return n;
11095 }
11096
11097 static void
11098 fixredir(union node *n, const char *text, int err)
11099 {
11100         int fd;
11101
11102         TRACE(("Fix redir %s %d\n", text, err));
11103         if (!err)
11104                 n->ndup.vname = NULL;
11105
11106         fd = bb_strtou(text, NULL, 10);
11107         if (!errno && fd >= 0)
11108                 n->ndup.dupfd = fd;
11109         else if (LONE_DASH(text))
11110                 n->ndup.dupfd = -1;
11111         else {
11112                 if (err)
11113                         raise_error_syntax("bad fd number");
11114                 n->ndup.vname = makename();
11115         }
11116 }
11117
11118 static void
11119 parsefname(void)
11120 {
11121         union node *n = redirnode;
11122
11123         if (n->type == NHERE)
11124                 checkkwd = CHKEOFMARK;
11125         if (readtoken() != TWORD)
11126                 raise_error_unexpected_syntax(-1);
11127         if (n->type == NHERE) {
11128                 struct heredoc *here = heredoc;
11129                 struct heredoc *p;
11130
11131                 if (quoteflag == 0)
11132                         n->type = NXHERE;
11133                 TRACE(("Here document %d\n", n->type));
11134                 rmescapes(wordtext, 0);
11135                 here->eofmark = wordtext;
11136                 here->next = NULL;
11137                 if (heredoclist == NULL)
11138                         heredoclist = here;
11139                 else {
11140                         for (p = heredoclist; p->next; p = p->next)
11141                                 continue;
11142                         p->next = here;
11143                 }
11144         } else if (n->type == NTOFD || n->type == NFROMFD) {
11145                 fixredir(n, wordtext, 0);
11146         } else {
11147                 n->nfile.fname = makename();
11148         }
11149 }
11150
11151 static union node *
11152 simplecmd(void)
11153 {
11154         union node *args, **app;
11155         union node *n = NULL;
11156         union node *vars, **vpp;
11157         union node **rpp, *redir;
11158         int savecheckkwd;
11159 #if BASH_TEST2
11160         smallint double_brackets_flag = 0;
11161 #endif
11162         IF_BASH_FUNCTION(smallint function_flag = 0;)
11163
11164         args = NULL;
11165         app = &args;
11166         vars = NULL;
11167         vpp = &vars;
11168         redir = NULL;
11169         rpp = &redir;
11170
11171         savecheckkwd = CHKALIAS;
11172         for (;;) {
11173                 int t;
11174                 checkkwd = savecheckkwd;
11175                 t = readtoken();
11176                 switch (t) {
11177 #if BASH_FUNCTION
11178                 case TFUNCTION:
11179                         if (peektoken() != TWORD)
11180                                 raise_error_unexpected_syntax(TWORD);
11181                         function_flag = 1;
11182                         break;
11183 #endif
11184 #if BASH_TEST2
11185                 case TAND: /* "&&" */
11186                 case TOR: /* "||" */
11187                         if (!double_brackets_flag) {
11188                                 tokpushback = 1;
11189                                 goto out;
11190                         }
11191                         wordtext = (char *) (t == TAND ? "-a" : "-o");
11192 #endif
11193                 case TWORD:
11194                         n = stzalloc(sizeof(struct narg));
11195                         n->type = NARG;
11196                         /*n->narg.next = NULL; - stzalloc did it */
11197                         n->narg.text = wordtext;
11198 #if BASH_TEST2
11199                         if (strcmp("[[", wordtext) == 0)
11200                                 double_brackets_flag = 1;
11201                         else if (strcmp("]]", wordtext) == 0)
11202                                 double_brackets_flag = 0;
11203 #endif
11204                         n->narg.backquote = backquotelist;
11205                         if (savecheckkwd && isassignment(wordtext)) {
11206                                 *vpp = n;
11207                                 vpp = &n->narg.next;
11208                         } else {
11209                                 *app = n;
11210                                 app = &n->narg.next;
11211                                 savecheckkwd = 0;
11212                         }
11213 #if BASH_FUNCTION
11214                         if (function_flag) {
11215                                 checkkwd = CHKNL | CHKKWD;
11216                                 switch (peektoken()) {
11217                                 case TBEGIN:
11218                                 case TIF:
11219                                 case TCASE:
11220                                 case TUNTIL:
11221                                 case TWHILE:
11222                                 case TFOR:
11223                                         goto do_func;
11224                                 case TLP:
11225                                         function_flag = 0;
11226                                         break;
11227                                 case TWORD:
11228                                         if (strcmp("[[", wordtext) == 0)
11229                                                 goto do_func;
11230                                         /* fall through */
11231                                 default:
11232                                         raise_error_unexpected_syntax(-1);
11233                                 }
11234                         }
11235 #endif
11236                         break;
11237                 case TREDIR:
11238                         *rpp = n = redirnode;
11239                         rpp = &n->nfile.next;
11240                         parsefname();   /* read name of redirection file */
11241                         break;
11242                 case TLP:
11243  IF_BASH_FUNCTION(do_func:)
11244                         if (args && app == &args->narg.next
11245                          && !vars && !redir
11246                         ) {
11247                                 struct builtincmd *bcmd;
11248                                 const char *name;
11249
11250                                 /* We have a function */
11251                                 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11252                                         raise_error_unexpected_syntax(TRP);
11253                                 name = n->narg.text;
11254                                 if (!goodname(name)
11255                                  || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
11256                                 ) {
11257                                         raise_error_syntax("bad function name");
11258                                 }
11259                                 n->type = NDEFUN;
11260                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11261                                 n->narg.next = parse_command();
11262                                 return n;
11263                         }
11264                         IF_BASH_FUNCTION(function_flag = 0;)
11265                         /* fall through */
11266                 default:
11267                         tokpushback = 1;
11268                         goto out;
11269                 }
11270         }
11271  out:
11272         *app = NULL;
11273         *vpp = NULL;
11274         *rpp = NULL;
11275         n = stzalloc(sizeof(struct ncmd));
11276         n->type = NCMD;
11277         n->ncmd.args = args;
11278         n->ncmd.assign = vars;
11279         n->ncmd.redirect = redir;
11280         return n;
11281 }
11282
11283 static union node *
11284 parse_command(void)
11285 {
11286         union node *n1, *n2;
11287         union node *ap, **app;
11288         union node *cp, **cpp;
11289         union node *redir, **rpp;
11290         union node **rpp2;
11291         int t;
11292
11293         redir = NULL;
11294         rpp2 = &redir;
11295
11296         switch (readtoken()) {
11297         default:
11298                 raise_error_unexpected_syntax(-1);
11299                 /* NOTREACHED */
11300         case TIF:
11301                 n1 = stzalloc(sizeof(struct nif));
11302                 n1->type = NIF;
11303                 n1->nif.test = list(0);
11304                 if (readtoken() != TTHEN)
11305                         raise_error_unexpected_syntax(TTHEN);
11306                 n1->nif.ifpart = list(0);
11307                 n2 = n1;
11308                 while (readtoken() == TELIF) {
11309                         n2->nif.elsepart = stzalloc(sizeof(struct nif));
11310                         n2 = n2->nif.elsepart;
11311                         n2->type = NIF;
11312                         n2->nif.test = list(0);
11313                         if (readtoken() != TTHEN)
11314                                 raise_error_unexpected_syntax(TTHEN);
11315                         n2->nif.ifpart = list(0);
11316                 }
11317                 if (lasttoken == TELSE)
11318                         n2->nif.elsepart = list(0);
11319                 else {
11320                         n2->nif.elsepart = NULL;
11321                         tokpushback = 1;
11322                 }
11323                 t = TFI;
11324                 break;
11325         case TWHILE:
11326         case TUNTIL: {
11327                 int got;
11328                 n1 = stzalloc(sizeof(struct nbinary));
11329                 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
11330                 n1->nbinary.ch1 = list(0);
11331                 got = readtoken();
11332                 if (got != TDO) {
11333                         TRACE(("expecting DO got '%s' %s\n", tokname_array[got],
11334                                         got == TWORD ? wordtext : ""));
11335                         raise_error_unexpected_syntax(TDO);
11336                 }
11337                 n1->nbinary.ch2 = list(0);
11338                 t = TDONE;
11339                 break;
11340         }
11341         case TFOR:
11342                 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
11343                         raise_error_syntax("bad for loop variable");
11344                 n1 = stzalloc(sizeof(struct nfor));
11345                 n1->type = NFOR;
11346                 n1->nfor.var = wordtext;
11347                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11348                 if (readtoken() == TIN) {
11349                         app = &ap;
11350                         while (readtoken() == TWORD) {
11351                                 n2 = stzalloc(sizeof(struct narg));
11352                                 n2->type = NARG;
11353                                 /*n2->narg.next = NULL; - stzalloc did it */
11354                                 n2->narg.text = wordtext;
11355                                 n2->narg.backquote = backquotelist;
11356                                 *app = n2;
11357                                 app = &n2->narg.next;
11358                         }
11359                         *app = NULL;
11360                         n1->nfor.args = ap;
11361                         if (lasttoken != TNL && lasttoken != TSEMI)
11362                                 raise_error_unexpected_syntax(-1);
11363                 } else {
11364                         n2 = stzalloc(sizeof(struct narg));
11365                         n2->type = NARG;
11366                         /*n2->narg.next = NULL; - stzalloc did it */
11367                         n2->narg.text = (char *)dolatstr;
11368                         /*n2->narg.backquote = NULL;*/
11369                         n1->nfor.args = n2;
11370                         /*
11371                          * Newline or semicolon here is optional (but note
11372                          * that the original Bourne shell only allowed NL).
11373                          */
11374                         if (lasttoken != TSEMI)
11375                                 tokpushback = 1;
11376                 }
11377                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11378                 if (readtoken() != TDO)
11379                         raise_error_unexpected_syntax(TDO);
11380                 n1->nfor.body = list(0);
11381                 t = TDONE;
11382                 break;
11383         case TCASE:
11384                 n1 = stzalloc(sizeof(struct ncase));
11385                 n1->type = NCASE;
11386                 if (readtoken() != TWORD)
11387                         raise_error_unexpected_syntax(TWORD);
11388                 n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
11389                 n2->type = NARG;
11390                 /*n2->narg.next = NULL; - stzalloc did it */
11391                 n2->narg.text = wordtext;
11392                 n2->narg.backquote = backquotelist;
11393                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
11394                 if (readtoken() != TIN)
11395                         raise_error_unexpected_syntax(TIN);
11396                 cpp = &n1->ncase.cases;
11397  next_case:
11398                 checkkwd = CHKNL | CHKKWD;
11399                 t = readtoken();
11400                 while (t != TESAC) {
11401                         if (lasttoken == TLP)
11402                                 readtoken();
11403                         *cpp = cp = stzalloc(sizeof(struct nclist));
11404                         cp->type = NCLIST;
11405                         app = &cp->nclist.pattern;
11406                         for (;;) {
11407                                 *app = ap = stzalloc(sizeof(struct narg));
11408                                 ap->type = NARG;
11409                                 /*ap->narg.next = NULL; - stzalloc did it */
11410                                 ap->narg.text = wordtext;
11411                                 ap->narg.backquote = backquotelist;
11412                                 if (readtoken() != TPIPE)
11413                                         break;
11414                                 app = &ap->narg.next;
11415                                 readtoken();
11416                         }
11417                         //ap->narg.next = NULL;
11418                         if (lasttoken != TRP)
11419                                 raise_error_unexpected_syntax(TRP);
11420                         cp->nclist.body = list(2);
11421
11422                         cpp = &cp->nclist.next;
11423
11424                         checkkwd = CHKNL | CHKKWD;
11425                         t = readtoken();
11426                         if (t != TESAC) {
11427                                 if (t != TENDCASE)
11428                                         raise_error_unexpected_syntax(TENDCASE);
11429                                 goto next_case;
11430                         }
11431                 }
11432                 *cpp = NULL;
11433                 goto redir;
11434         case TLP:
11435                 n1 = stzalloc(sizeof(struct nredir));
11436                 n1->type = NSUBSHELL;
11437                 n1->nredir.n = list(0);
11438                 /*n1->nredir.redirect = NULL; - stzalloc did it */
11439                 t = TRP;
11440                 break;
11441         case TBEGIN:
11442                 n1 = list(0);
11443                 t = TEND;
11444                 break;
11445         IF_BASH_FUNCTION(case TFUNCTION:)
11446         case TWORD:
11447         case TREDIR:
11448                 tokpushback = 1;
11449                 return simplecmd();
11450         }
11451
11452         if (readtoken() != t)
11453                 raise_error_unexpected_syntax(t);
11454
11455  redir:
11456         /* Now check for redirection which may follow command */
11457         checkkwd = CHKKWD | CHKALIAS;
11458         rpp = rpp2;
11459         while (readtoken() == TREDIR) {
11460                 *rpp = n2 = redirnode;
11461                 rpp = &n2->nfile.next;
11462                 parsefname();
11463         }
11464         tokpushback = 1;
11465         *rpp = NULL;
11466         if (redir) {
11467                 if (n1->type != NSUBSHELL) {
11468                         n2 = stzalloc(sizeof(struct nredir));
11469                         n2->type = NREDIR;
11470                         n2->nredir.n = n1;
11471                         n1 = n2;
11472                 }
11473                 n1->nredir.redirect = redir;
11474         }
11475         return n1;
11476 }
11477
11478 #if BASH_DOLLAR_SQUOTE
11479 static int
11480 decode_dollar_squote(void)
11481 {
11482         static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
11483         int c, cnt;
11484         char *p;
11485         char buf[4];
11486
11487         c = pgetc();
11488         p = strchr(C_escapes, c);
11489         if (p) {
11490                 buf[0] = c;
11491                 p = buf;
11492                 cnt = 3;
11493                 if ((unsigned char)(c - '0') <= 7) { /* \ooo */
11494                         do {
11495                                 c = pgetc();
11496                                 *++p = c;
11497                         } while ((unsigned char)(c - '0') <= 7 && --cnt);
11498                         pungetc();
11499                 } else if (c == 'x') { /* \xHH */
11500                         do {
11501                                 c = pgetc();
11502                                 *++p = c;
11503                         } while (isxdigit(c) && --cnt);
11504                         pungetc();
11505                         if (cnt == 3) { /* \x but next char is "bad" */
11506                                 c = 'x';
11507                                 goto unrecognized;
11508                         }
11509                 } else { /* simple seq like \\ or \t */
11510                         p++;
11511                 }
11512                 *p = '\0';
11513                 p = buf;
11514                 c = bb_process_escape_sequence((void*)&p);
11515         } else { /* unrecognized "\z": print both chars unless ' or " */
11516                 if (c != '\'' && c != '"') {
11517  unrecognized:
11518                         c |= 0x100; /* "please encode \, then me" */
11519                 }
11520         }
11521         return c;
11522 }
11523 #endif
11524
11525 /*
11526  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
11527  * is not NULL, read a here document.  In the latter case, eofmark is the
11528  * word which marks the end of the document and striptabs is true if
11529  * leading tabs should be stripped from the document.  The argument c
11530  * is the first character of the input token or document.
11531  *
11532  * Because C does not have internal subroutines, I have simulated them
11533  * using goto's to implement the subroutine linkage.  The following macros
11534  * will run code that appears at the end of readtoken1.
11535  */
11536 #define CHECKEND()      {goto checkend; checkend_return:;}
11537 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
11538 #define PARSESUB()      {goto parsesub; parsesub_return:;}
11539 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
11540 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
11541 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
11542 static int
11543 readtoken1(int c, int syntax, char *eofmark, int striptabs)
11544 {
11545         /* NB: syntax parameter fits into smallint */
11546         /* c parameter is an unsigned char or PEOF or PEOA */
11547         char *out;
11548         size_t len;
11549         struct nodelist *bqlist;
11550         smallint quotef;
11551         smallint dblquote;
11552         smallint oldstyle;
11553         IF_FEATURE_SH_MATH(smallint prevsyntax;) /* syntax before arithmetic */
11554         smallint pssyntax;   /* we are expanding a prompt string */
11555         int varnest;         /* levels of variables expansion */
11556         IF_FEATURE_SH_MATH(int arinest;)    /* levels of arithmetic expansion */
11557         IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11558         int dqvarnest;       /* levels of variables expansion within double quotes */
11559
11560         IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11561
11562         startlinno = g_parsefile->linno;
11563         bqlist = NULL;
11564         quotef = 0;
11565         IF_FEATURE_SH_MATH(prevsyntax = 0;)
11566         pssyntax = (syntax == PSSYNTAX);
11567         if (pssyntax)
11568                 syntax = DQSYNTAX;
11569         dblquote = (syntax == DQSYNTAX);
11570         varnest = 0;
11571         IF_FEATURE_SH_MATH(arinest = 0;)
11572         IF_FEATURE_SH_MATH(parenlevel = 0;)
11573         dqvarnest = 0;
11574
11575         STARTSTACKSTR(out);
11576  loop:
11577         /* For each line, until end of word */
11578         CHECKEND();     /* set c to PEOF if at end of here document */
11579         for (;;) {      /* until end of line or end of word */
11580                 CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
11581                 switch (SIT(c, syntax)) {
11582                 case CNL:       /* '\n' */
11583                         if (syntax == BASESYNTAX)
11584                                 goto endword;   /* exit outer loop */
11585                         USTPUTC(c, out);
11586                         nlprompt();
11587                         c = pgetc();
11588                         goto loop;              /* continue outer loop */
11589                 case CWORD:
11590                         USTPUTC(c, out);
11591                         break;
11592                 case CCTL:
11593 #if BASH_DOLLAR_SQUOTE
11594                         if (c == '\\' && bash_dollar_squote) {
11595                                 c = decode_dollar_squote();
11596                                 if (c == '\0') {
11597                                         /* skip $'\000', $'\x00' (like bash) */
11598                                         break;
11599                                 }
11600                                 if (c & 0x100) {
11601                                         /* Unknown escape. Encode as '\z' */
11602                                         c = (unsigned char)c;
11603                                         if (eofmark == NULL || dblquote)
11604                                                 USTPUTC(CTLESC, out);
11605                                         USTPUTC('\\', out);
11606                                 }
11607                         }
11608 #endif
11609                         if (eofmark == NULL || dblquote)
11610                                 USTPUTC(CTLESC, out);
11611                         USTPUTC(c, out);
11612                         break;
11613                 case CBACK:     /* backslash */
11614                         c = pgetc_without_PEOA();
11615                         if (c == PEOF) {
11616                                 USTPUTC(CTLESC, out);
11617                                 USTPUTC('\\', out);
11618                                 pungetc();
11619                         } else if (c == '\n') {
11620                                 nlprompt();
11621                         } else {
11622                                 if (c == '$' && pssyntax) {
11623                                         USTPUTC(CTLESC, out);
11624                                         USTPUTC('\\', out);
11625                                 }
11626                                 /* Backslash is retained if we are in "str" and next char isn't special */
11627                                 if (dblquote
11628                                  && c != '\\'
11629                                  && c != '`'
11630                                  && c != '$'
11631                                  && (c != '"' || eofmark != NULL)
11632                                 ) {
11633                                         USTPUTC('\\', out);
11634                                 }
11635                                 USTPUTC(CTLESC, out);
11636                                 USTPUTC(c, out);
11637                                 quotef = 1;
11638                         }
11639                         break;
11640                 case CSQUOTE:
11641                         syntax = SQSYNTAX;
11642  quotemark:
11643                         if (eofmark == NULL) {
11644                                 USTPUTC(CTLQUOTEMARK, out);
11645                         }
11646                         break;
11647                 case CDQUOTE:
11648                         syntax = DQSYNTAX;
11649                         dblquote = 1;
11650                         goto quotemark;
11651                 case CENDQUOTE:
11652                         IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11653                         if (eofmark != NULL && varnest == 0) {
11654                                 USTPUTC(c, out);
11655                         } else {
11656                                 if (dqvarnest == 0) {
11657                                         syntax = BASESYNTAX;
11658                                         dblquote = 0;
11659                                 }
11660                                 quotef = 1;
11661                                 goto quotemark;
11662                         }
11663                         break;
11664                 case CVAR:      /* '$' */
11665                         PARSESUB();             /* parse substitution */
11666                         break;
11667                 case CENDVAR:   /* '}' */
11668                         if (varnest > 0) {
11669                                 varnest--;
11670                                 if (dqvarnest > 0) {
11671                                         dqvarnest--;
11672                                 }
11673                                 c = CTLENDVAR;
11674                         }
11675                         USTPUTC(c, out);
11676                         break;
11677 #if ENABLE_FEATURE_SH_MATH
11678                 case CLP:       /* '(' in arithmetic */
11679                         parenlevel++;
11680                         USTPUTC(c, out);
11681                         break;
11682                 case CRP:       /* ')' in arithmetic */
11683                         if (parenlevel > 0) {
11684                                 parenlevel--;
11685                         } else {
11686                                 if (pgetc_eatbnl() == ')') {
11687                                         c = CTLENDARI;
11688                                         if (--arinest == 0) {
11689                                                 syntax = prevsyntax;
11690                                         }
11691                                 } else {
11692                                         /*
11693                                          * unbalanced parens
11694                                          * (don't 2nd guess - no error)
11695                                          */
11696                                         pungetc();
11697                                 }
11698                         }
11699                         USTPUTC(c, out);
11700                         break;
11701 #endif
11702                 case CBQUOTE:   /* '`' */
11703                         PARSEBACKQOLD();
11704                         break;
11705                 case CENDFILE:
11706                         goto endword;           /* exit outer loop */
11707                 case CIGN:
11708                         break;
11709                 default:
11710                         if (varnest == 0) {
11711 #if BASH_REDIR_OUTPUT
11712                                 if (c == '&') {
11713 //Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11714                                         if (pgetc() == '>')
11715                                                 c = 0x100 + '>'; /* flag &> */
11716                                         pungetc();
11717                                 }
11718 #endif
11719                                 goto endword;   /* exit outer loop */
11720                         }
11721                         IF_ASH_ALIAS(if (c != PEOA))
11722                                 USTPUTC(c, out);
11723                 }
11724                 c = pgetc();
11725         } /* for (;;) */
11726  endword:
11727
11728 #if ENABLE_FEATURE_SH_MATH
11729         if (syntax == ARISYNTAX)
11730                 raise_error_syntax("missing '))'");
11731 #endif
11732         if (syntax != BASESYNTAX && eofmark == NULL)
11733                 raise_error_syntax("unterminated quoted string");
11734         if (varnest != 0) {
11735                 startlinno = g_parsefile->linno;
11736                 /* { */
11737                 raise_error_syntax("missing '}'");
11738         }
11739         USTPUTC('\0', out);
11740         len = out - (char *)stackblock();
11741         out = stackblock();
11742         if (eofmark == NULL) {
11743                 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11744                  && quotef == 0
11745                 ) {
11746                         if (isdigit_str9(out)) {
11747                                 PARSEREDIR(); /* passed as params: out, c */
11748                                 lasttoken = TREDIR;
11749                                 return lasttoken;
11750                         }
11751                         /* else: non-number X seen, interpret it
11752                          * as "NNNX>file" = "NNNX >file" */
11753                 }
11754                 pungetc();
11755         }
11756         quoteflag = quotef;
11757         backquotelist = bqlist;
11758         grabstackblock(len);
11759         wordtext = out;
11760         lasttoken = TWORD;
11761         return lasttoken;
11762 /* end of readtoken routine */
11763
11764 /*
11765  * Check to see whether we are at the end of the here document.  When this
11766  * is called, c is set to the first character of the next input line.  If
11767  * we are at the end of the here document, this routine sets the c to PEOF.
11768  */
11769 checkend: {
11770         if (eofmark) {
11771                 int markloc;
11772                 char *p;
11773
11774 #if ENABLE_ASH_ALIAS
11775                 if (c == PEOA)
11776                         c = pgetc_without_PEOA();
11777 #endif
11778                 if (striptabs) {
11779                         while (c == '\t') {
11780                                 c = pgetc_without_PEOA();
11781                         }
11782                 }
11783
11784                 markloc = out - (char *)stackblock();
11785                 for (p = eofmark; STPUTC(c, out), *p; p++) {
11786                         if (c != *p)
11787                                 goto more_heredoc;
11788
11789                         c = pgetc_without_PEOA();
11790                 }
11791
11792                 if (c == '\n' || c == PEOF) {
11793                         c = PEOF;
11794                         g_parsefile->linno++;
11795                         needprompt = doprompt;
11796                 } else {
11797                         int len_here;
11798
11799  more_heredoc:
11800                         p = (char *)stackblock() + markloc + 1;
11801                         len_here = out - p;
11802
11803                         if (len_here) {
11804                                 len_here -= (c >= PEOF);
11805                                 c = p[-1];
11806
11807                                 if (len_here) {
11808                                         char *str;
11809
11810                                         str = alloca(len_here + 1);
11811                                         *(char *)mempcpy(str, p, len_here) = '\0';
11812
11813                                         pushstring(str, NULL);
11814                                 }
11815                         }
11816                 }
11817
11818                 STADJUST((char *)stackblock() + markloc - out, out);
11819         }
11820         goto checkend_return;
11821 }
11822
11823 /*
11824  * Parse a redirection operator.  The variable "out" points to a string
11825  * specifying the fd to be redirected.  The variable "c" contains the
11826  * first character of the redirection operator.
11827  */
11828 parseredir: {
11829         /* out is already checked to be a valid number or "" */
11830         int fd = (*out == '\0' ? -1 : atoi(out));
11831         union node *np;
11832
11833         np = stzalloc(sizeof(struct nfile));
11834         if (c == '>') {
11835                 np->nfile.fd = 1;
11836                 c = pgetc();
11837                 if (c == '>')
11838                         np->type = NAPPEND;
11839                 else if (c == '|')
11840                         np->type = NCLOBBER;
11841                 else if (c == '&')
11842                         np->type = NTOFD;
11843                         /* it also can be NTO2 (>&file), but we can't figure it out yet */
11844                 else {
11845                         np->type = NTO;
11846                         pungetc();
11847                 }
11848         }
11849 #if BASH_REDIR_OUTPUT
11850         else if (c == 0x100 + '>') { /* this flags &> redirection */
11851                 np->nfile.fd = 1;
11852                 pgetc(); /* this is '>', no need to check */
11853                 np->type = NTO2;
11854         }
11855 #endif
11856         else { /* c == '<' */
11857                 /*np->nfile.fd = 0; - stzalloc did it */
11858                 c = pgetc();
11859                 switch (c) {
11860                 case '<':
11861                         if (sizeof(struct nfile) != sizeof(struct nhere)) {
11862                                 np = stzalloc(sizeof(struct nhere));
11863                                 /*np->nfile.fd = 0; - stzalloc did it */
11864                         }
11865                         np->type = NHERE;
11866                         heredoc = stzalloc(sizeof(struct heredoc));
11867                         heredoc->here = np;
11868                         c = pgetc();
11869                         if (c == '-') {
11870                                 heredoc->striptabs = 1;
11871                         } else {
11872                                 /*heredoc->striptabs = 0; - stzalloc did it */
11873                                 pungetc();
11874                         }
11875                         break;
11876
11877                 case '&':
11878                         np->type = NFROMFD;
11879                         break;
11880
11881                 case '>':
11882                         np->type = NFROMTO;
11883                         break;
11884
11885                 default:
11886                         np->type = NFROM;
11887                         pungetc();
11888                         break;
11889                 }
11890         }
11891         if (fd >= 0)
11892                 np->nfile.fd = fd;
11893         redirnode = np;
11894         goto parseredir_return;
11895 }
11896
11897 /*
11898  * Parse a substitution.  At this point, we have read the dollar sign
11899  * and nothing else.
11900  */
11901
11902 /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
11903  * (assuming ascii char codes, as the original implementation did) */
11904 #define is_special(c) \
11905         (((unsigned)(c) - 33 < 32) \
11906                         && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
11907 parsesub: {
11908         unsigned char subtype;
11909         int typeloc;
11910
11911         c = pgetc_eatbnl();
11912         if ((checkkwd & CHKEOFMARK)
11913          || c > 255 /* PEOA or PEOF */
11914          || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11915         ) {
11916 #if BASH_DOLLAR_SQUOTE
11917                 if (syntax != DQSYNTAX && c == '\'')
11918                         bash_dollar_squote = 1;
11919                 else
11920 #endif
11921                         USTPUTC('$', out);
11922                 pungetc();
11923         } else if (c == '(') {
11924                 /* $(command) or $((arith)) */
11925                 if (pgetc_eatbnl() == '(') {
11926 #if ENABLE_FEATURE_SH_MATH
11927                         PARSEARITH();
11928 #else
11929                         raise_error_syntax("support for $((arith)) is disabled");
11930 #endif
11931                 } else {
11932                         pungetc();
11933                         PARSEBACKQNEW();
11934                 }
11935         } else {
11936                 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11937                 USTPUTC(CTLVAR, out);
11938                 typeloc = out - (char *)stackblock();
11939                 STADJUST(1, out);
11940                 subtype = VSNORMAL;
11941                 if (c == '{') {
11942                         c = pgetc_eatbnl();
11943                         subtype = 0;
11944                 }
11945  varname:
11946                 if (is_name(c)) {
11947                         /* $[{[#]]NAME[}] */
11948                         do {
11949                                 STPUTC(c, out);
11950                                 c = pgetc_eatbnl();
11951                         } while (is_in_name(c));
11952                 } else if (isdigit(c)) {
11953                         /* $[{[#]]NUM[}] */
11954                         do {
11955                                 STPUTC(c, out);
11956                                 c = pgetc_eatbnl();
11957                         } while (isdigit(c));
11958                 } else if (is_special(c)) {
11959                         /* $[{[#]]<specialchar>[}] */
11960                         int cc = c;
11961
11962                         c = pgetc_eatbnl();
11963                         if (!subtype && cc == '#') {
11964                                 subtype = VSLENGTH;
11965                                 if (c == '_' || isalnum(c))
11966                                         goto varname;
11967                                 cc = c;
11968                                 c = pgetc_eatbnl();
11969                                 if (cc == '}' || c != '}') {
11970                                         pungetc();
11971                                         subtype = 0;
11972                                         c = cc;
11973                                         cc = '#';
11974                                 }
11975                         }
11976                         USTPUTC(cc, out);
11977                 } else {
11978                         goto badsub;
11979                 }
11980                 if (c != '}' && subtype == VSLENGTH) {
11981                         /* ${#VAR didn't end with } */
11982                         goto badsub;
11983                 }
11984
11985                 if (subtype == 0) {
11986                         static const char types[] ALIGN1 = "}-+?=";
11987                         /* ${VAR...} but not $VAR or ${#VAR} */
11988                         /* c == first char after VAR */
11989                         switch (c) {
11990                         case ':':
11991                                 c = pgetc_eatbnl();
11992 #if BASH_SUBSTR
11993                                 /* This check is only needed to not misinterpret
11994                                  * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
11995                                  * constructs.
11996                                  */
11997                                 if (!strchr(types, c)) {
11998                                         subtype = VSSUBSTR;
11999                                         pungetc();
12000                                         break; /* "goto badsub" is bigger (!) */
12001                                 }
12002 #endif
12003                                 subtype = VSNUL;
12004                                 /*FALLTHROUGH*/
12005                         default: {
12006                                 const char *p = strchr(types, c);
12007                                 if (p == NULL)
12008                                         break;
12009                                 subtype |= p - types + VSNORMAL;
12010                                 break;
12011                         }
12012                         case '%':
12013                         case '#': {
12014                                 int cc = c;
12015                                 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
12016                                 c = pgetc_eatbnl();
12017                                 if (c != cc)
12018                                         goto badsub;
12019                                 subtype++;
12020                                 break;
12021                         }
12022 #if BASH_PATTERN_SUBST
12023                         case '/':
12024                                 /* ${v/[/]pattern/repl} */
12025 //TODO: encode pattern and repl separately.
12026 // Currently ${v/$var_with_slash/repl} is horribly broken
12027                                 subtype = VSREPLACE;
12028                                 c = pgetc_eatbnl();
12029                                 if (c != '/')
12030                                         goto badsub;
12031                                 subtype++; /* VSREPLACEALL */
12032                                 break;
12033 #endif
12034                         }
12035                 } else {
12036  badsub:
12037                         pungetc();
12038                 }
12039                 ((unsigned char *)stackblock())[typeloc] = subtype;
12040                 if (subtype != VSNORMAL) {
12041                         varnest++;
12042                         if (dblquote)
12043                                 dqvarnest++;
12044                 }
12045                 STPUTC('=', out);
12046         }
12047         goto parsesub_return;
12048 }
12049
12050 /*
12051  * Called to parse command substitutions.  Newstyle is set if the command
12052  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
12053  * list of commands (passed by reference), and savelen is the number of
12054  * characters on the top of the stack which must be preserved.
12055  */
12056 parsebackq: {
12057         struct nodelist **nlpp;
12058         union node *n;
12059         char *str;
12060         size_t savelen;
12061         smallint saveprompt = 0;
12062
12063         str = NULL;
12064         savelen = out - (char *)stackblock();
12065         if (savelen > 0) {
12066                 /*
12067                  * FIXME: this can allocate very large block on stack and SEGV.
12068                  * Example:
12069                  * echo "..<100kbytes>..`true` $(true) `true` ..."
12070                  * allocates 100kb for every command subst. With about
12071                  * a hundred command substitutions stack overflows.
12072                  * With larger prepended string, SEGV happens sooner.
12073                  */
12074                 str = alloca(savelen);
12075                 memcpy(str, stackblock(), savelen);
12076         }
12077
12078         if (oldstyle) {
12079                 /* We must read until the closing backquote, giving special
12080                  * treatment to some slashes, and then push the string and
12081                  * reread it as input, interpreting it normally.
12082                  */
12083                 char *pout;
12084                 size_t psavelen;
12085                 char *pstr;
12086
12087                 STARTSTACKSTR(pout);
12088                 for (;;) {
12089                         int pc;
12090
12091                         setprompt_if(needprompt, 2);
12092                         pc = pgetc();
12093                         switch (pc) {
12094                         case '`':
12095                                 goto done;
12096
12097                         case '\\':
12098                                 pc = pgetc();
12099                                 if (pc == '\n') {
12100                                         nlprompt();
12101                                         /*
12102                                          * If eating a newline, avoid putting
12103                                          * the newline into the new character
12104                                          * stream (via the STPUTC after the
12105                                          * switch).
12106                                          */
12107                                         continue;
12108                                 }
12109                                 if (pc != '\\' && pc != '`' && pc != '$'
12110                                  && (!dblquote || pc != '"')
12111                                 ) {
12112                                         STPUTC('\\', pout);
12113                                 }
12114                                 if (pc <= 255 /* not PEOA or PEOF */) {
12115                                         break;
12116                                 }
12117                                 /* fall through */
12118
12119                         case PEOF:
12120                         IF_ASH_ALIAS(case PEOA:)
12121                                 startlinno = g_parsefile->linno;
12122                                 raise_error_syntax("EOF in backquote substitution");
12123
12124                         case '\n':
12125                                 nlnoprompt();
12126                                 break;
12127
12128                         default:
12129                                 break;
12130                         }
12131                         STPUTC(pc, pout);
12132                 }
12133  done:
12134                 STPUTC('\0', pout);
12135                 psavelen = pout - (char *)stackblock();
12136                 if (psavelen > 0) {
12137                         pstr = grabstackstr(pout);
12138                         setinputstring(pstr);
12139                 }
12140         }
12141         nlpp = &bqlist;
12142         while (*nlpp)
12143                 nlpp = &(*nlpp)->next;
12144         *nlpp = stzalloc(sizeof(**nlpp));
12145         /* (*nlpp)->next = NULL; - stzalloc did it */
12146
12147         if (oldstyle) {
12148                 saveprompt = doprompt;
12149                 doprompt = 0;
12150         }
12151
12152         n = list(2);
12153
12154         if (oldstyle)
12155                 doprompt = saveprompt;
12156         else if (readtoken() != TRP)
12157                 raise_error_unexpected_syntax(TRP);
12158
12159         (*nlpp)->n = n;
12160         if (oldstyle) {
12161                 /*
12162                  * Start reading from old file again, ignoring any pushed back
12163                  * tokens left from the backquote parsing
12164                  */
12165                 popfile();
12166                 tokpushback = 0;
12167         }
12168         while (stackblocksize() <= savelen)
12169                 growstackblock();
12170         STARTSTACKSTR(out);
12171         if (str) {
12172                 memcpy(out, str, savelen);
12173                 STADJUST(savelen, out);
12174         }
12175         USTPUTC(CTLBACKQ, out);
12176         if (oldstyle)
12177                 goto parsebackq_oldreturn;
12178         goto parsebackq_newreturn;
12179 }
12180
12181 #if ENABLE_FEATURE_SH_MATH
12182 /*
12183  * Parse an arithmetic expansion (indicate start of one and set state)
12184  */
12185 parsearith: {
12186         if (++arinest == 1) {
12187                 prevsyntax = syntax;
12188                 syntax = ARISYNTAX;
12189         }
12190         USTPUTC(CTLARI, out);
12191         goto parsearith_return;
12192 }
12193 #endif
12194 } /* end of readtoken */
12195
12196 /*
12197  * Read the next input token.
12198  * If the token is a word, we set backquotelist to the list of cmds in
12199  *      backquotes.  We set quoteflag to true if any part of the word was
12200  *      quoted.
12201  * If the token is TREDIR, then we set redirnode to a structure containing
12202  *      the redirection.
12203  * In all cases, the variable startlinno is set to the number of the line
12204  *      on which the token starts.
12205  *
12206  * [Change comment:  here documents and internal procedures]
12207  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
12208  *  word parsing code into a separate routine.  In this case, readtoken
12209  *  doesn't need to have any internal procedures, but parseword does.
12210  *  We could also make parseoperator in essence the main routine, and
12211  *  have parseword (readtoken1?) handle both words and redirection.]
12212  */
12213 #define NEW_xxreadtoken
12214 #ifdef NEW_xxreadtoken
12215 /* singles must be first! */
12216 static const char xxreadtoken_chars[7] ALIGN1 = {
12217         '\n', '(', ')', /* singles */
12218         '&', '|', ';',  /* doubles */
12219         0
12220 };
12221
12222 #define xxreadtoken_singles 3
12223 #define xxreadtoken_doubles 3
12224
12225 static const char xxreadtoken_tokens[] ALIGN1 = {
12226         TNL, TLP, TRP,          /* only single occurrence allowed */
12227         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
12228         TEOF,                   /* corresponds to trailing nul */
12229         TAND, TOR, TENDCASE     /* if double occurrence */
12230 };
12231
12232 static int
12233 xxreadtoken(void)
12234 {
12235         int c;
12236
12237         if (tokpushback) {
12238                 tokpushback = 0;
12239                 return lasttoken;
12240         }
12241         setprompt_if(needprompt, 2);
12242         startlinno = g_parsefile->linno;
12243         for (;;) {                      /* until token or start of word found */
12244                 c = pgetc();
12245                 if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
12246                         continue;
12247
12248                 if (c == '#') {
12249                         while ((c = pgetc()) != '\n' && c != PEOF)
12250                                 continue;
12251                         pungetc();
12252                 } else if (c == '\\') {
12253                         if (pgetc() != '\n') {
12254                                 pungetc();
12255                                 break; /* return readtoken1(...) */
12256                         }
12257                         nlprompt();
12258                 } else {
12259                         const char *p;
12260
12261                         p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
12262                         if (c != PEOF) {
12263                                 if (c == '\n') {
12264                                         nlnoprompt();
12265                                 }
12266
12267                                 p = strchr(xxreadtoken_chars, c);
12268                                 if (p == NULL)
12269                                         break; /* return readtoken1(...) */
12270
12271                                 if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
12272                                         int cc = pgetc();
12273                                         if (cc == c) {    /* double occurrence? */
12274                                                 p += xxreadtoken_doubles + 1;
12275                                         } else {
12276                                                 pungetc();
12277 #if BASH_REDIR_OUTPUT
12278                                                 if (c == '&' && cc == '>') /* &> */
12279                                                         break; /* return readtoken1(...) */
12280 #endif
12281                                         }
12282                                 }
12283                         }
12284                         lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
12285                         return lasttoken;
12286                 }
12287         } /* for (;;) */
12288
12289         return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
12290 }
12291 #else /* old xxreadtoken */
12292 #define RETURN(token)   return lasttoken = token
12293 static int
12294 xxreadtoken(void)
12295 {
12296         int c;
12297
12298         if (tokpushback) {
12299                 tokpushback = 0;
12300                 return lasttoken;
12301         }
12302         setprompt_if(needprompt, 2);
12303         startlinno = g_parsefile->linno;
12304         for (;;) {      /* until token or start of word found */
12305                 c = pgetc();
12306                 switch (c) {
12307                 case ' ': case '\t':
12308                 IF_ASH_ALIAS(case PEOA:)
12309                         continue;
12310                 case '#':
12311                         while ((c = pgetc()) != '\n' && c != PEOF)
12312                                 continue;
12313                         pungetc();
12314                         continue;
12315                 case '\\':
12316                         if (pgetc() == '\n') {
12317                                 nlprompt();
12318                                 continue;
12319                         }
12320                         pungetc();
12321                         goto breakloop;
12322                 case '\n':
12323                         nlnoprompt();
12324                         RETURN(TNL);
12325                 case PEOF:
12326                         RETURN(TEOF);
12327                 case '&':
12328                         if (pgetc() == '&')
12329                                 RETURN(TAND);
12330                         pungetc();
12331                         RETURN(TBACKGND);
12332                 case '|':
12333                         if (pgetc() == '|')
12334                                 RETURN(TOR);
12335                         pungetc();
12336                         RETURN(TPIPE);
12337                 case ';':
12338                         if (pgetc() == ';')
12339                                 RETURN(TENDCASE);
12340                         pungetc();
12341                         RETURN(TSEMI);
12342                 case '(':
12343                         RETURN(TLP);
12344                 case ')':
12345                         RETURN(TRP);
12346                 default:
12347                         goto breakloop;
12348                 }
12349         }
12350  breakloop:
12351         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
12352 #undef RETURN
12353 }
12354 #endif /* old xxreadtoken */
12355
12356 static int
12357 readtoken(void)
12358 {
12359         int t;
12360         int kwd = checkkwd;
12361 #if DEBUG
12362         smallint alreadyseen = tokpushback;
12363 #endif
12364
12365 #if ENABLE_ASH_ALIAS
12366  top:
12367 #endif
12368
12369         t = xxreadtoken();
12370
12371         /*
12372          * eat newlines
12373          */
12374         if (kwd & CHKNL) {
12375                 while (t == TNL) {
12376                         parseheredoc();
12377                         t = xxreadtoken();
12378                 }
12379         }
12380
12381         if (t != TWORD || quoteflag) {
12382                 goto out;
12383         }
12384
12385         /*
12386          * check for keywords
12387          */
12388         if (kwd & CHKKWD) {
12389                 const char *const *pp;
12390
12391                 pp = findkwd(wordtext);
12392                 if (pp) {
12393                         lasttoken = t = pp - tokname_array;
12394                         TRACE(("keyword '%s' recognized\n", tokname_array[t]));
12395                         goto out;
12396                 }
12397         }
12398
12399         if (checkkwd & CHKALIAS) {
12400 #if ENABLE_ASH_ALIAS
12401                 struct alias *ap;
12402                 ap = lookupalias(wordtext, 1);
12403                 if (ap != NULL) {
12404                         if (*ap->val) {
12405                                 pushstring(ap->val, ap);
12406                         }
12407                         goto top;
12408                 }
12409 #endif
12410         }
12411  out:
12412         checkkwd = 0;
12413 #if DEBUG
12414         if (!alreadyseen)
12415                 TRACE(("token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12416         else
12417                 TRACE(("reread token '%s' %s\n", tokname_array[t], t == TWORD ? wordtext : ""));
12418 #endif
12419         return t;
12420 }
12421
12422 static int
12423 peektoken(void)
12424 {
12425         int t;
12426
12427         t = readtoken();
12428         tokpushback = 1;
12429         return t;
12430 }
12431
12432 /*
12433  * Read and parse a command.  Returns NODE_EOF on end of file.
12434  * (NULL is a valid parse tree indicating a blank line.)
12435  */
12436 static union node *
12437 parsecmd(int interact)
12438 {
12439         tokpushback = 0;
12440         checkkwd = 0;
12441         heredoclist = 0;
12442         doprompt = interact;
12443         setprompt_if(doprompt, doprompt);
12444         needprompt = 0;
12445         return list(1);
12446 }
12447
12448 /*
12449  * Input any here documents.
12450  */
12451 static void
12452 parseheredoc(void)
12453 {
12454         struct heredoc *here;
12455         union node *n;
12456
12457         here = heredoclist;
12458         heredoclist = NULL;
12459
12460         while (here) {
12461                 setprompt_if(needprompt, 2);
12462                 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
12463                                 here->eofmark, here->striptabs);
12464                 n = stzalloc(sizeof(struct narg));
12465                 n->narg.type = NARG;
12466                 /*n->narg.next = NULL; - stzalloc did it */
12467                 n->narg.text = wordtext;
12468                 n->narg.backquote = backquotelist;
12469                 here->here->nhere.doc = n;
12470                 here = here->next;
12471         }
12472 }
12473
12474
12475 /*
12476  * called by editline -- any expansions to the prompt should be added here.
12477  */
12478 static const char *
12479 expandstr(const char *ps)
12480 {
12481         union node n;
12482         int saveprompt;
12483
12484         /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
12485          * and token processing _can_ alter it (delete NULs etc). */
12486         setinputstring((char *)ps);
12487
12488         saveprompt = doprompt;
12489         doprompt = 0;
12490         readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
12491         doprompt = saveprompt;
12492
12493         popfile();
12494
12495         n.narg.type = NARG;
12496         n.narg.next = NULL;
12497         n.narg.text = wordtext;
12498         n.narg.backquote = backquotelist;
12499
12500         expandarg(&n, NULL, EXP_QUOTED);
12501         return stackblock();
12502 }
12503
12504 static inline int
12505 parser_eof(void)
12506 {
12507         return tokpushback && lasttoken == TEOF;
12508 }
12509
12510 /*
12511  * Execute a command or commands contained in a string.
12512  */
12513 static int
12514 evalstring(char *s, int flags)
12515 {
12516         struct jmploc *volatile savehandler;
12517         struct jmploc jmploc;
12518         int ex;
12519
12520         union node *n;
12521         struct stackmark smark;
12522         int status;
12523
12524         s = sstrdup(s);
12525         setinputstring(s);
12526         setstackmark(&smark);
12527
12528         status = 0;
12529         /* On exception inside execution loop, we must popfile().
12530          * Try interactively:
12531          *      readonly a=a
12532          *      command eval "a=b"  # throws "is read only" error
12533          * "command BLTIN" is not supposed to abort (even in non-interactive use).
12534          * But if we skip popfile(), we hit EOF in eval's string, and exit.
12535          */
12536         savehandler = exception_handler;
12537         ex = setjmp(jmploc.loc);
12538         if (ex)
12539                 goto out;
12540         exception_handler = &jmploc;
12541
12542         while ((n = parsecmd(0)) != NODE_EOF) {
12543                 int i;
12544
12545                 i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
12546                 if (n)
12547                         status = i;
12548                 popstackmark(&smark);
12549                 if (evalskip)
12550                         break;
12551         }
12552  out:
12553         popstackmark(&smark);
12554         popfile();
12555         stunalloc(s);
12556
12557         exception_handler = savehandler;
12558         if (ex)
12559                 longjmp(exception_handler->loc, ex);
12560
12561         return status;
12562 }
12563
12564 /*
12565  * The eval command.
12566  */
12567 static int FAST_FUNC
12568 evalcmd(int argc UNUSED_PARAM, char **argv, int flags)
12569 {
12570         char *p;
12571         char *concat;
12572
12573         if (argv[1]) {
12574                 p = argv[1];
12575                 argv += 2;
12576                 if (argv[0]) {
12577                         STARTSTACKSTR(concat);
12578                         for (;;) {
12579                                 concat = stack_putstr(p, concat);
12580                                 p = *argv++;
12581                                 if (p == NULL)
12582                                         break;
12583                                 STPUTC(' ', concat);
12584                         }
12585                         STPUTC('\0', concat);
12586                         p = grabstackstr(concat);
12587                 }
12588                 return evalstring(p, flags & EV_TESTED);
12589         }
12590         return 0;
12591 }
12592
12593 /*
12594  * Read and execute commands.
12595  * "Top" is nonzero for the top level command loop;
12596  * it turns on prompting if the shell is interactive.
12597  */
12598 static int
12599 cmdloop(int top)
12600 {
12601         union node *n;
12602         struct stackmark smark;
12603         int inter;
12604         int status = 0;
12605         int numeof = 0;
12606
12607         TRACE(("cmdloop(%d) called\n", top));
12608         for (;;) {
12609                 int skip;
12610
12611                 setstackmark(&smark);
12612 #if JOBS
12613                 if (doing_jobctl)
12614                         showjobs(SHOW_CHANGED|SHOW_STDERR);
12615 #endif
12616                 inter = 0;
12617                 if (iflag && top) {
12618                         inter++;
12619                         chkmail();
12620                 }
12621                 n = parsecmd(inter);
12622 #if DEBUG
12623                 if (DEBUG > 2 && debug && (n != NODE_EOF))
12624                         showtree(n);
12625 #endif
12626                 if (n == NODE_EOF) {
12627                         if (!top || numeof >= 50)
12628                                 break;
12629                         if (!stoppedjobs()) {
12630                                 if (!Iflag)
12631                                         break;
12632                                 out2str("\nUse \"exit\" to leave shell.\n");
12633                         }
12634                         numeof++;
12635                 } else if (nflag == 0) {
12636                         int i;
12637
12638                         /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
12639                         job_warning >>= 1;
12640                         numeof = 0;
12641                         i = evaltree(n, 0);
12642                         if (n)
12643                                 status = i;
12644                 }
12645                 popstackmark(&smark);
12646                 skip = evalskip;
12647
12648                 if (skip) {
12649                         evalskip &= ~SKIPFUNC;
12650                         break;
12651                 }
12652         }
12653         return status;
12654 }
12655
12656 /*
12657  * Take commands from a file.  To be compatible we should do a path
12658  * search for the file, which is necessary to find sub-commands.
12659  */
12660 static char *
12661 find_dot_file(char *name)
12662 {
12663         char *fullname;
12664         const char *path = pathval();
12665         struct stat statb;
12666
12667         /* don't try this for absolute or relative paths */
12668         if (strchr(name, '/'))
12669                 return name;
12670
12671         while ((fullname = path_advance(&path, name)) != NULL) {
12672                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
12673                         /*
12674                          * Don't bother freeing here, since it will
12675                          * be freed by the caller.
12676                          */
12677                         return fullname;
12678                 }
12679                 if (fullname != name)
12680                         stunalloc(fullname);
12681         }
12682
12683         /* not found in the PATH */
12684         ash_msg_and_raise_error("%s: not found", name);
12685         /* NOTREACHED */
12686 }
12687
12688 static int FAST_FUNC
12689 dotcmd(int argc_ UNUSED_PARAM, char **argv_ UNUSED_PARAM)
12690 {
12691         /* "false; . empty_file; echo $?" should print 0, not 1: */
12692         int status = 0;
12693         char *fullname;
12694         char **argv;
12695         char *args_need_save;
12696         volatile struct shparam saveparam;
12697
12698 //???
12699 //      struct strlist *sp;
12700 //      for (sp = cmdenviron; sp; sp = sp->next)
12701 //              setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
12702
12703         nextopt(nullstr); /* handle possible "--" */
12704         argv = argptr;
12705
12706         if (!argv[0]) {
12707                 /* bash says: "bash: .: filename argument required" */
12708                 return 2; /* bash compat */
12709         }
12710
12711         /* This aborts if file isn't found, which is POSIXly correct.
12712          * bash returns exitcode 1 instead.
12713          */
12714         fullname = find_dot_file(argv[0]);
12715         argv++;
12716         args_need_save = argv[0];
12717         if (args_need_save) { /* ". FILE ARGS", and ARGS are not empty */
12718                 int argc;
12719                 saveparam = shellparam;
12720                 shellparam.malloced = 0;
12721                 argc = 1;
12722                 while (argv[argc])
12723                         argc++;
12724                 shellparam.nparam = argc;
12725                 shellparam.p = argv;
12726         };
12727
12728         /* This aborts if file can't be opened, which is POSIXly correct.
12729          * bash returns exitcode 1 instead.
12730          */
12731         setinputfile(fullname, INPUT_PUSH_FILE);
12732         commandname = fullname;
12733         status = cmdloop(0);
12734         popfile();
12735
12736         if (args_need_save) {
12737                 freeparam(&shellparam);
12738                 shellparam = saveparam;
12739         };
12740
12741         return status;
12742 }
12743
12744 static int FAST_FUNC
12745 exitcmd(int argc UNUSED_PARAM, char **argv)
12746 {
12747         if (stoppedjobs())
12748                 return 0;
12749         if (argv[1])
12750                 exitstatus = number(argv[1]);
12751         raise_exception(EXEXIT);
12752         /* NOTREACHED */
12753 }
12754
12755 /*
12756  * Read a file containing shell functions.
12757  */
12758 static void
12759 readcmdfile(char *name)
12760 {
12761         setinputfile(name, INPUT_PUSH_FILE);
12762         cmdloop(0);
12763         popfile();
12764 }
12765
12766
12767 /* ============ find_command inplementation */
12768
12769 /*
12770  * Resolve a command name.  If you change this routine, you may have to
12771  * change the shellexec routine as well.
12772  */
12773 static void
12774 find_command(char *name, struct cmdentry *entry, int act, const char *path)
12775 {
12776         struct tblentry *cmdp;
12777         int idx;
12778         int prev;
12779         char *fullname;
12780         struct stat statb;
12781         int e;
12782         int updatetbl;
12783         struct builtincmd *bcmd;
12784
12785         /* If name contains a slash, don't use PATH or hash table */
12786         if (strchr(name, '/') != NULL) {
12787                 entry->u.index = -1;
12788                 if (act & DO_ABS) {
12789                         while (stat(name, &statb) < 0) {
12790 #ifdef SYSV
12791                                 if (errno == EINTR)
12792                                         continue;
12793 #endif
12794                                 entry->cmdtype = CMDUNKNOWN;
12795                                 return;
12796                         }
12797                 }
12798                 entry->cmdtype = CMDNORMAL;
12799                 return;
12800         }
12801
12802 /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
12803
12804         updatetbl = (path == pathval());
12805         if (!updatetbl) {
12806                 act |= DO_ALTPATH;
12807                 if (strstr(path, "%builtin") != NULL)
12808                         act |= DO_ALTBLTIN;
12809         }
12810
12811         /* If name is in the table, check answer will be ok */
12812         cmdp = cmdlookup(name, 0);
12813         if (cmdp != NULL) {
12814                 int bit;
12815
12816                 switch (cmdp->cmdtype) {
12817                 default:
12818 #if DEBUG
12819                         abort();
12820 #endif
12821                 case CMDNORMAL:
12822                         bit = DO_ALTPATH;
12823                         break;
12824                 case CMDFUNCTION:
12825                         bit = DO_NOFUNC;
12826                         break;
12827                 case CMDBUILTIN:
12828                         bit = DO_ALTBLTIN;
12829                         break;
12830                 }
12831                 if (act & bit) {
12832                         updatetbl = 0;
12833                         cmdp = NULL;
12834                 } else if (cmdp->rehash == 0)
12835                         /* if not invalidated by cd, we're done */
12836                         goto success;
12837         }
12838
12839         /* If %builtin not in path, check for builtin next */
12840         bcmd = find_builtin(name);
12841         if (bcmd) {
12842                 if (IS_BUILTIN_REGULAR(bcmd))
12843                         goto builtin_success;
12844                 if (act & DO_ALTPATH) {
12845                         if (!(act & DO_ALTBLTIN))
12846                                 goto builtin_success;
12847                 } else if (builtinloc <= 0) {
12848                         goto builtin_success;
12849                 }
12850         }
12851
12852 #if ENABLE_FEATURE_SH_STANDALONE
12853         {
12854                 int applet_no = find_applet_by_name(name);
12855                 if (applet_no >= 0) {
12856                         entry->cmdtype = CMDNORMAL;
12857                         entry->u.index = -2 - applet_no;
12858                         return;
12859                 }
12860         }
12861 #endif
12862
12863         /* We have to search path. */
12864         prev = -1;              /* where to start */
12865         if (cmdp && cmdp->rehash) {     /* doing a rehash */
12866                 if (cmdp->cmdtype == CMDBUILTIN)
12867                         prev = builtinloc;
12868                 else
12869                         prev = cmdp->param.index;
12870         }
12871
12872         e = ENOENT;
12873         idx = -1;
12874  loop:
12875         while ((fullname = path_advance(&path, name)) != NULL) {
12876                 stunalloc(fullname);
12877                 /* NB: code below will still use fullname
12878                  * despite it being "unallocated" */
12879                 idx++;
12880                 if (pathopt) {
12881                         if (prefix(pathopt, "builtin")) {
12882                                 if (bcmd)
12883                                         goto builtin_success;
12884                                 continue;
12885                         }
12886                         if ((act & DO_NOFUNC)
12887                          || !prefix(pathopt, "func")
12888                         ) {     /* ignore unimplemented options */
12889                                 continue;
12890                         }
12891                 }
12892                 /* if rehash, don't redo absolute path names */
12893                 if (fullname[0] == '/' && idx <= prev) {
12894                         if (idx < prev)
12895                                 continue;
12896                         TRACE(("searchexec \"%s\": no change\n", name));
12897                         goto success;
12898                 }
12899                 while (stat(fullname, &statb) < 0) {
12900 #ifdef SYSV
12901                         if (errno == EINTR)
12902                                 continue;
12903 #endif
12904                         if (errno != ENOENT && errno != ENOTDIR)
12905                                 e = errno;
12906                         goto loop;
12907                 }
12908                 e = EACCES;     /* if we fail, this will be the error */
12909                 if (!S_ISREG(statb.st_mode))
12910                         continue;
12911                 if (pathopt) {          /* this is a %func directory */
12912                         stalloc(strlen(fullname) + 1);
12913                         /* NB: stalloc will return space pointed by fullname
12914                          * (because we don't have any intervening allocations
12915                          * between stunalloc above and this stalloc) */
12916                         readcmdfile(fullname);
12917                         cmdp = cmdlookup(name, 0);
12918                         if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
12919                                 ash_msg_and_raise_error("%s not defined in %s", name, fullname);
12920                         stunalloc(fullname);
12921                         goto success;
12922                 }
12923                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
12924                 if (!updatetbl) {
12925                         entry->cmdtype = CMDNORMAL;
12926                         entry->u.index = idx;
12927                         return;
12928                 }
12929                 INT_OFF;
12930                 cmdp = cmdlookup(name, 1);
12931                 cmdp->cmdtype = CMDNORMAL;
12932                 cmdp->param.index = idx;
12933                 INT_ON;
12934                 goto success;
12935         }
12936
12937         /* We failed.  If there was an entry for this command, delete it */
12938         if (cmdp && updatetbl)
12939                 delete_cmd_entry();
12940         if (act & DO_ERR)
12941                 ash_msg("%s: %s", name, errmsg(e, "not found"));
12942         entry->cmdtype = CMDUNKNOWN;
12943         return;
12944
12945  builtin_success:
12946         if (!updatetbl) {
12947                 entry->cmdtype = CMDBUILTIN;
12948                 entry->u.cmd = bcmd;
12949                 return;
12950         }
12951         INT_OFF;
12952         cmdp = cmdlookup(name, 1);
12953         cmdp->cmdtype = CMDBUILTIN;
12954         cmdp->param.cmd = bcmd;
12955         INT_ON;
12956  success:
12957         cmdp->rehash = 0;
12958         entry->cmdtype = cmdp->cmdtype;
12959         entry->u = cmdp->param;
12960 }
12961
12962
12963 /*
12964  * The trap builtin.
12965  */
12966 static int FAST_FUNC
12967 trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
12968 {
12969         char *action;
12970         char **ap;
12971         int signo, exitcode;
12972
12973         nextopt(nullstr);
12974         ap = argptr;
12975         if (!*ap) {
12976                 for (signo = 0; signo < NSIG; signo++) {
12977                         char *tr = trap_ptr[signo];
12978                         if (tr) {
12979                                 /* note: bash adds "SIG", but only if invoked
12980                                  * as "bash". If called as "sh", or if set -o posix,
12981                                  * then it prints short signal names.
12982                                  * We are printing short names: */
12983                                 out1fmt("trap -- %s %s\n",
12984                                                 single_quote(tr),
12985                                                 get_signame(signo));
12986                 /* trap_ptr != trap only if we are in special-cased `trap` code.
12987                  * In this case, we will exit very soon, no need to free(). */
12988                                 /* if (trap_ptr != trap && tp[0]) */
12989                                 /*      free(tr); */
12990                         }
12991                 }
12992                 /*
12993                 if (trap_ptr != trap) {
12994                         free(trap_ptr);
12995                         trap_ptr = trap;
12996                 }
12997                 */
12998                 return 0;
12999         }
13000
13001         /* Why the second check?
13002          * "trap NUM [sig2]..." is the same as "trap - NUM [sig2]..."
13003          * In this case, NUM is signal no, not an action.
13004          */
13005         action = NULL;
13006         if (ap[1] && !is_number(ap[0]))
13007                 action = *ap++;
13008
13009         exitcode = 0;
13010         while (*ap) {
13011                 signo = get_signum(*ap);
13012                 if (signo < 0) {
13013                         /* Mimic bash message exactly */
13014                         ash_msg("%s: invalid signal specification", *ap);
13015                         exitcode = 1;
13016                         goto next;
13017                 }
13018                 INT_OFF;
13019                 if (action) {
13020                         if (LONE_DASH(action))
13021                                 action = NULL;
13022                         else {
13023                                 if (action[0]) /* not NULL and not "" and not "-" */
13024                                         may_have_traps = 1;
13025                                 action = ckstrdup(action);
13026                         }
13027                 }
13028                 free(trap[signo]);
13029                 trap[signo] = action;
13030                 if (signo != 0)
13031                         setsignal(signo);
13032                 INT_ON;
13033  next:
13034                 ap++;
13035         }
13036         return exitcode;
13037 }
13038
13039
13040 /* ============ Builtins */
13041
13042 #if ENABLE_ASH_HELP
13043 static int FAST_FUNC
13044 helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13045 {
13046         unsigned col;
13047         unsigned i;
13048
13049         out1fmt(
13050                 "Built-in commands:\n"
13051                 "------------------\n");
13052         for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
13053                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
13054                                         builtintab[i].name + 1);
13055                 if (col > 60) {
13056                         out1fmt("\n");
13057                         col = 0;
13058                 }
13059         }
13060 # if ENABLE_FEATURE_SH_STANDALONE
13061         {
13062                 const char *a = applet_names;
13063                 while (*a) {
13064                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
13065                         if (col > 60) {
13066                                 out1fmt("\n");
13067                                 col = 0;
13068                         }
13069                         while (*a++ != '\0')
13070                                 continue;
13071                 }
13072         }
13073 # endif
13074         newline_and_flush(stdout);
13075         return EXIT_SUCCESS;
13076 }
13077 #endif
13078
13079 #if MAX_HISTORY
13080 static int FAST_FUNC
13081 historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13082 {
13083         show_history(line_input_state);
13084         return EXIT_SUCCESS;
13085 }
13086 #endif
13087
13088 /*
13089  * The export and readonly commands.
13090  */
13091 static int FAST_FUNC
13092 exportcmd(int argc UNUSED_PARAM, char **argv)
13093 {
13094         struct var *vp;
13095         char *name;
13096         const char *p;
13097         char **aptr;
13098         char opt;
13099         int flag;
13100         int flag_off;
13101
13102         /* "readonly" in bash accepts, but ignores -n.
13103          * We do the same: it saves a conditional in nextopt's param.
13104          */
13105         flag_off = 0;
13106         while ((opt = nextopt("np")) != '\0') {
13107                 if (opt == 'n')
13108                         flag_off = VEXPORT;
13109         }
13110         flag = VEXPORT;
13111         if (argv[0][0] == 'r') {
13112                 flag = VREADONLY;
13113                 flag_off = 0; /* readonly ignores -n */
13114         }
13115         flag_off = ~flag_off;
13116
13117         /*if (opt_p_not_specified) - bash doesn't check this. Try "export -p NAME" */
13118         {
13119                 aptr = argptr;
13120                 name = *aptr;
13121                 if (name) {
13122                         do {
13123                                 p = strchr(name, '=');
13124                                 if (p != NULL) {
13125                                         p++;
13126                                 } else {
13127                                         vp = *findvar(hashvar(name), name);
13128                                         if (vp) {
13129                                                 vp->flags = ((vp->flags | flag) & flag_off);
13130                                                 continue;
13131                                         }
13132                                 }
13133                                 setvar(name, p, (flag & flag_off));
13134                         } while ((name = *++aptr) != NULL);
13135                         return 0;
13136                 }
13137         }
13138
13139         /* No arguments. Show the list of exported or readonly vars.
13140          * -n is ignored.
13141          */
13142         showvars(argv[0], flag, 0);
13143         return 0;
13144 }
13145
13146 /*
13147  * Delete a function if it exists.
13148  */
13149 static void
13150 unsetfunc(const char *name)
13151 {
13152         struct tblentry *cmdp;
13153
13154         cmdp = cmdlookup(name, 0);
13155         if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
13156                 delete_cmd_entry();
13157 }
13158
13159 /*
13160  * The unset builtin command.  We unset the function before we unset the
13161  * variable to allow a function to be unset when there is a readonly variable
13162  * with the same name.
13163  */
13164 static int FAST_FUNC
13165 unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13166 {
13167         char **ap;
13168         int i;
13169         int flag = 0;
13170
13171         while ((i = nextopt("vf")) != 0) {
13172                 flag = i;
13173         }
13174
13175         for (ap = argptr; *ap; ap++) {
13176                 if (flag != 'f') {
13177                         unsetvar(*ap);
13178                         continue;
13179                 }
13180                 if (flag != 'v')
13181                         unsetfunc(*ap);
13182         }
13183         return 0;
13184 }
13185
13186 static const unsigned char timescmd_str[] ALIGN1 = {
13187         ' ',  offsetof(struct tms, tms_utime),
13188         '\n', offsetof(struct tms, tms_stime),
13189         ' ',  offsetof(struct tms, tms_cutime),
13190         '\n', offsetof(struct tms, tms_cstime),
13191         0
13192 };
13193 static int FAST_FUNC
13194 timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13195 {
13196         unsigned long clk_tck, s, t;
13197         const unsigned char *p;
13198         struct tms buf;
13199
13200         clk_tck = bb_clk_tck();
13201         times(&buf);
13202
13203         p = timescmd_str;
13204         do {
13205                 t = *(clock_t *)(((char *) &buf) + p[1]);
13206                 s = t / clk_tck;
13207                 t = t % clk_tck;
13208                 out1fmt("%lum%lu.%03lus%c",
13209                         s / 60, s % 60,
13210                         (t * 1000) / clk_tck,
13211                         p[0]);
13212                 p += 2;
13213         } while (*p);
13214
13215         return 0;
13216 }
13217
13218 #if ENABLE_FEATURE_SH_MATH
13219 /*
13220  * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
13221  * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
13222  *
13223  * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13224  */
13225 static int FAST_FUNC
13226 letcmd(int argc UNUSED_PARAM, char **argv)
13227 {
13228         arith_t i;
13229
13230         argv++;
13231         if (!*argv)
13232                 ash_msg_and_raise_error("expression expected");
13233         do {
13234                 i = ash_arith(*argv);
13235         } while (*++argv);
13236
13237         return !i;
13238 }
13239 #endif
13240
13241 /*
13242  * The read builtin. Options:
13243  *      -r              Do not interpret '\' specially
13244  *      -s              Turn off echo (tty only)
13245  *      -n NCHARS       Read NCHARS max
13246  *      -p PROMPT       Display PROMPT on stderr (if input is from tty)
13247  *      -t SECONDS      Timeout after SECONDS (tty or pipe only)
13248  *      -u FD           Read from given FD instead of fd 0
13249  * This uses unbuffered input, which may be avoidable in some cases.
13250  * TODO: bash also has:
13251  *      -a ARRAY        Read into array[0],[1],etc
13252  *      -d DELIM        End on DELIM char, not newline
13253  *      -e              Use line editing (tty only)
13254  */
13255 static int FAST_FUNC
13256 readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13257 {
13258         char *opt_n = NULL;
13259         char *opt_p = NULL;
13260         char *opt_t = NULL;
13261         char *opt_u = NULL;
13262         int read_flags = 0;
13263         const char *r;
13264         int i;
13265
13266         while ((i = nextopt("p:u:rt:n:s")) != '\0') {
13267                 switch (i) {
13268                 case 'p':
13269                         opt_p = optionarg;
13270                         break;
13271                 case 'n':
13272                         opt_n = optionarg;
13273                         break;
13274                 case 's':
13275                         read_flags |= BUILTIN_READ_SILENT;
13276                         break;
13277                 case 't':
13278                         opt_t = optionarg;
13279                         break;
13280                 case 'r':
13281                         read_flags |= BUILTIN_READ_RAW;
13282                         break;
13283                 case 'u':
13284                         opt_u = optionarg;
13285                         break;
13286                 default:
13287                         break;
13288                 }
13289         }
13290
13291         /* "read -s" needs to save/restore termios, can't allow ^C
13292          * to jump out of it.
13293          */
13294  again:
13295         INT_OFF;
13296         r = shell_builtin_read(setvar0,
13297                 argptr,
13298                 bltinlookup("IFS"), /* can be NULL */
13299                 read_flags,
13300                 opt_n,
13301                 opt_p,
13302                 opt_t,
13303                 opt_u
13304         );
13305         INT_ON;
13306
13307         if ((uintptr_t)r == 1 && errno == EINTR) {
13308                 /* to get SIGCHLD: sleep 1 & read x; echo $x */
13309                 if (pending_sig == 0)
13310                         goto again;
13311         }
13312
13313         if ((uintptr_t)r > 1)
13314                 ash_msg_and_raise_error(r);
13315
13316         return (uintptr_t)r;
13317 }
13318
13319 static int FAST_FUNC
13320 umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
13321 {
13322         static const char permuser[3] ALIGN1 = "ogu";
13323
13324         mode_t mask;
13325         int symbolic_mode = 0;
13326
13327         while (nextopt("S") != '\0') {
13328                 symbolic_mode = 1;
13329         }
13330
13331         INT_OFF;
13332         mask = umask(0);
13333         umask(mask);
13334         INT_ON;
13335
13336         if (*argptr == NULL) {
13337                 if (symbolic_mode) {
13338                         char buf[sizeof(",u=rwx,g=rwx,o=rwx")];
13339                         char *p = buf;
13340                         int i;
13341
13342                         i = 2;
13343                         for (;;) {
13344                                 *p++ = ',';
13345                                 *p++ = permuser[i];
13346                                 *p++ = '=';
13347                                 /* mask is 0..0uuugggooo. i=2 selects uuu bits */
13348                                 if (!(mask & 0400)) *p++ = 'r';
13349                                 if (!(mask & 0200)) *p++ = 'w';
13350                                 if (!(mask & 0100)) *p++ = 'x';
13351                                 mask <<= 3;
13352                                 if (--i < 0)
13353                                         break;
13354                         }
13355                         *p = '\0';
13356                         puts(buf + 1);
13357                 } else {
13358                         out1fmt("%04o\n", mask);
13359                 }
13360         } else {
13361                 char *modestr = *argptr;
13362                 /* numeric umasks are taken as-is */
13363                 /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
13364                 if (!isdigit(modestr[0]))
13365                         mask ^= 0777;
13366                 mask = bb_parse_mode(modestr, mask);
13367                 if ((unsigned)mask > 0777) {
13368                         ash_msg_and_raise_error("illegal mode: %s", modestr);
13369                 }
13370                 if (!isdigit(modestr[0]))
13371                         mask ^= 0777;
13372                 umask(mask);
13373         }
13374         return 0;
13375 }
13376
13377 static int FAST_FUNC
13378 ulimitcmd(int argc UNUSED_PARAM, char **argv)
13379 {
13380         return shell_builtin_ulimit(argv);
13381 }
13382
13383 /* ============ main() and helpers */
13384
13385 /*
13386  * Called to exit the shell.
13387  */
13388 static void
13389 exitshell(void)
13390 {
13391         struct jmploc loc;
13392         char *p;
13393         int status;
13394
13395 #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
13396         save_history(line_input_state);
13397 #endif
13398         status = exitstatus;
13399         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
13400         if (setjmp(loc.loc)) {
13401                 if (exception_type == EXEXIT)
13402                         status = exitstatus;
13403                 goto out;
13404         }
13405         exception_handler = &loc;
13406         p = trap[0];
13407         if (p) {
13408                 trap[0] = NULL;
13409                 evalskip = 0;
13410                 evalstring(p, 0);
13411                 /*free(p); - we'll exit soon */
13412         }
13413  out:
13414         /* dash wraps setjobctl(0) in "if (setjmp(loc.loc) == 0) {...}".
13415          * our setjobctl(0) does not panic if tcsetpgrp fails inside it.
13416          */
13417         setjobctl(0);
13418         flush_stdout_stderr();
13419         _exit(status);
13420         /* NOTREACHED */
13421 }
13422
13423 static void
13424 init(void)
13425 {
13426         /* we will never free this */
13427         basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
13428
13429         sigmode[SIGCHLD - 1] = S_DFL;
13430         setsignal(SIGCHLD);
13431
13432         /* bash re-enables SIGHUP which is SIG_IGNed on entry.
13433          * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
13434          */
13435         signal(SIGHUP, SIG_DFL);
13436
13437         {
13438                 char **envp;
13439                 const char *p;
13440                 struct stat st1, st2;
13441
13442                 initvar();
13443                 for (envp = environ; envp && *envp; envp++) {
13444                         p = endofname(*envp);
13445                         if (p != *envp && *p == '=') {
13446                                 setvareq(*envp, VEXPORT|VTEXTFIXED);
13447                         }
13448                 }
13449
13450                 setvareq((char*)defoptindvar, VTEXTFIXED);
13451
13452                 setvar0("PPID", utoa(getppid()));
13453 #if BASH_SHLVL_VAR
13454                 p = lookupvar("SHLVL");
13455                 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13456 #endif
13457 #if BASH_HOSTNAME_VAR
13458                 if (!lookupvar("HOSTNAME")) {
13459                         struct utsname uts;
13460                         uname(&uts);
13461                         setvar0("HOSTNAME", uts.nodename);
13462                 }
13463 #endif
13464                 p = lookupvar("PWD");
13465                 if (p) {
13466                         if (p[0] != '/' || stat(p, &st1) || stat(".", &st2)
13467                          || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13468                         ) {
13469                                 p = NULL;
13470                         }
13471                 }
13472                 setpwd(p, 0);
13473         }
13474 }
13475
13476
13477 //usage:#define ash_trivial_usage
13478 //usage:        "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13479 //usage:#define ash_full_usage "\n\n"
13480 //usage:        "Unix shell interpreter"
13481
13482 /*
13483  * Process the shell command line arguments.
13484  */
13485 static void
13486 procargs(char **argv)
13487 {
13488         int i;
13489         const char *xminusc;
13490         char **xargv;
13491
13492         xargv = argv;
13493         arg0 = xargv[0];
13494         /* if (xargv[0]) - mmm, this is always true! */
13495                 xargv++;
13496         for (i = 0; i < NOPTS; i++)
13497                 optlist[i] = 2;
13498         argptr = xargv;
13499         if (options(/*cmdline:*/ 1)) {
13500                 /* it already printed err message */
13501                 raise_exception(EXERROR);
13502         }
13503         xargv = argptr;
13504         xminusc = minusc;
13505         if (*xargv == NULL) {
13506                 if (xminusc)
13507                         ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
13508                 sflag = 1;
13509         }
13510         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
13511                 iflag = 1;
13512         if (mflag == 2)
13513                 mflag = iflag;
13514         for (i = 0; i < NOPTS; i++)
13515                 if (optlist[i] == 2)
13516                         optlist[i] = 0;
13517 #if DEBUG == 2
13518         debug = 1;
13519 #endif
13520         /* POSIX 1003.2: first arg after "-c CMD" is $0, remainder $1... */
13521         if (xminusc) {
13522                 minusc = *xargv++;
13523                 if (*xargv)
13524                         goto setarg0;
13525         } else if (!sflag) {
13526                 setinputfile(*xargv, 0);
13527  setarg0:
13528                 arg0 = *xargv++;
13529                 commandname = arg0;
13530         }
13531
13532         shellparam.p = xargv;
13533 #if ENABLE_ASH_GETOPTS
13534         shellparam.optind = 1;
13535         shellparam.optoff = -1;
13536 #endif
13537         /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
13538         while (*xargv) {
13539                 shellparam.nparam++;
13540                 xargv++;
13541         }
13542         optschanged();
13543 }
13544
13545 /*
13546  * Read /etc/profile, ~/.profile, $ENV.
13547  */
13548 static void
13549 read_profile(const char *name)
13550 {
13551         name = expandstr(name);
13552         if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
13553                 return;
13554         cmdloop(0);
13555         popfile();
13556 }
13557
13558 /*
13559  * This routine is called when an error or an interrupt occurs in an
13560  * interactive shell and control is returned to the main command loop.
13561  * (In dash, this function is auto-generated by build machinery).
13562  */
13563 static void
13564 reset(void)
13565 {
13566         /* from eval.c: */
13567         evalskip = 0;
13568         loopnest = 0;
13569
13570         /* from expand.c: */
13571         ifsfree();
13572
13573         /* from input.c: */
13574         g_parsefile->left_in_buffer = 0;
13575         g_parsefile->left_in_line = 0;      /* clear input buffer */
13576         popallfiles();
13577
13578         /* from redir.c: */
13579         while (redirlist)
13580                 popredir(/*drop:*/ 0, /*restore:*/ 0);
13581
13582         /* from var.c: */
13583         unwindlocalvars(NULL);
13584 }
13585
13586 #if PROFILE
13587 static short profile_buf[16384];
13588 extern int etext();
13589 #endif
13590
13591 /*
13592  * Main routine.  We initialize things, parse the arguments, execute
13593  * profiles if we're a login shell, and then call cmdloop to execute
13594  * commands.  The setjmp call sets up the location to jump to when an
13595  * exception occurs.  When an exception occurs the variable "state"
13596  * is used to figure out how far we had gotten.
13597  */
13598 int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13599 int ash_main(int argc UNUSED_PARAM, char **argv)
13600 {
13601         volatile smallint state;
13602         struct jmploc jmploc;
13603         struct stackmark smark;
13604
13605         /* Initialize global data */
13606         INIT_G_misc();
13607         INIT_G_memstack();
13608         INIT_G_var();
13609 #if ENABLE_ASH_ALIAS
13610         INIT_G_alias();
13611 #endif
13612         INIT_G_cmdtable();
13613
13614 #if PROFILE
13615         monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
13616 #endif
13617
13618 #if ENABLE_FEATURE_EDITING
13619         line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
13620 #endif
13621         state = 0;
13622         if (setjmp(jmploc.loc)) {
13623                 smallint e;
13624                 smallint s;
13625
13626                 reset();
13627
13628                 e = exception_type;
13629                 s = state;
13630                 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
13631                         exitshell();
13632                 }
13633                 if (e == EXINT) {
13634                         newline_and_flush(stderr);
13635                 }
13636
13637                 popstackmark(&smark);
13638                 FORCE_INT_ON; /* enable interrupts */
13639                 if (s == 1)
13640                         goto state1;
13641                 if (s == 2)
13642                         goto state2;
13643                 if (s == 3)
13644                         goto state3;
13645                 goto state4;
13646         }
13647         exception_handler = &jmploc;
13648         rootpid = getpid();
13649
13650         init();
13651         setstackmark(&smark);
13652         procargs(argv);
13653 #if DEBUG
13654         TRACE(("Shell args: "));
13655         trace_puts_args(argv);
13656 #endif
13657
13658         if (argv[0] && argv[0][0] == '-')
13659                 isloginsh = 1;
13660         if (isloginsh) {
13661                 const char *hp;
13662
13663                 state = 1;
13664                 read_profile("/etc/profile");
13665  state1:
13666                 state = 2;
13667                 hp = lookupvar("HOME");
13668                 if (hp)
13669                         read_profile("$HOME/.profile");
13670         }
13671  state2:
13672         state = 3;
13673         if (
13674 #ifndef linux
13675          getuid() == geteuid() && getgid() == getegid() &&
13676 #endif
13677          iflag
13678         ) {
13679                 const char *shinit = lookupvar("ENV");
13680                 if (shinit != NULL && *shinit != '\0')
13681                         read_profile(shinit);
13682         }
13683         popstackmark(&smark);
13684  state3:
13685         state = 4;
13686         if (minusc) {
13687                 /* evalstring pushes parsefile stack.
13688                  * Ensure we don't falsely claim that 0 (stdin)
13689                  * is one of stacked source fds.
13690                  * Testcase: ash -c 'exec 1>&0' must not complain. */
13691                 // if (!sflag) g_parsefile->pf_fd = -1;
13692                 // ^^ not necessary since now we special-case fd 0
13693                 // in is_hidden_fd() to not be considered "hidden fd"
13694                 evalstring(minusc, sflag ? 0 : EV_EXIT);
13695         }
13696
13697         if (sflag || minusc == NULL) {
13698 #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
13699                 if (iflag) {
13700                         const char *hp = lookupvar("HISTFILE");
13701                         if (!hp) {
13702                                 hp = lookupvar("HOME");
13703                                 if (hp) {
13704                                         INT_OFF;
13705                                         hp = concat_path_file(hp, ".ash_history");
13706                                         setvar0("HISTFILE", hp);
13707                                         free((char*)hp);
13708                                         INT_ON;
13709                                         hp = lookupvar("HISTFILE");
13710                                 }
13711                         }
13712                         if (hp)
13713                                 line_input_state->hist_file = hp;
13714 # if ENABLE_FEATURE_SH_HISTFILESIZE
13715                         hp = lookupvar("HISTFILESIZE");
13716                         line_input_state->max_history = size_from_HISTFILESIZE(hp);
13717 # endif
13718                 }
13719 #endif
13720  state4: /* XXX ??? - why isn't this before the "if" statement */
13721                 cmdloop(1);
13722         }
13723 #if PROFILE
13724         monitor(0);
13725 #endif
13726 #ifdef GPROF
13727         {
13728                 extern void _mcleanup(void);
13729                 _mcleanup();
13730         }
13731 #endif
13732         TRACE(("End of main reached\n"));
13733         exitshell();
13734         /* NOTREACHED */
13735 }
13736
13737
13738 /*-
13739  * Copyright (c) 1989, 1991, 1993, 1994
13740  *      The Regents of the University of California.  All rights reserved.
13741  *
13742  * This code is derived from software contributed to Berkeley by
13743  * Kenneth Almquist.
13744  *
13745  * Redistribution and use in source and binary forms, with or without
13746  * modification, are permitted provided that the following conditions
13747  * are met:
13748  * 1. Redistributions of source code must retain the above copyright
13749  *    notice, this list of conditions and the following disclaimer.
13750  * 2. Redistributions in binary form must reproduce the above copyright
13751  *    notice, this list of conditions and the following disclaimer in the
13752  *    documentation and/or other materials provided with the distribution.
13753  * 3. Neither the name of the University nor the names of its contributors
13754  *    may be used to endorse or promote products derived from this software
13755  *    without specific prior written permission.
13756  *
13757  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13758  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13759  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13760  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13761  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13762  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13763  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13764  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13765  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13766  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13767  * SUCH DAMAGE.
13768  */