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