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